hush: implement "silent" optstrings of ":opts"
[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 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
194
195 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
196 /* Bionic at least up to version 24 has no glob() */
197 # undef  ENABLE_ASH_INTERNAL_GLOB
198 # define ENABLE_ASH_INTERNAL_GLOB 1
199 #endif
200
201 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
202 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
203 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
204 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
205 # error glob() should unbackslash them and match. uClibc does not unbackslash,
206 # error fails to match dirname, subsequently not expanding <pattern> in it.
207 // Testcase:
208 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
209 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
210 #endif
211
212 #if !ENABLE_ASH_INTERNAL_GLOB
213 # include <glob.h>
214 #endif
215
216 #include "unicode.h"
217 #include "shell_common.h"
218 #if ENABLE_FEATURE_SH_MATH
219 # include "math.h"
220 #else
221 typedef long arith_t;
222 # define ARITH_FMT "%ld"
223 #endif
224 #if ENABLE_ASH_RANDOM_SUPPORT
225 # include "random.h"
226 #else
227 # define CLEAR_RANDOM_T(rnd) ((void)0)
228 #endif
229
230 #include "NUM_APPLETS.h"
231 #if NUM_APPLETS == 1
232 /* STANDALONE does not make sense, and won't compile */
233 # undef CONFIG_FEATURE_SH_STANDALONE
234 # undef ENABLE_FEATURE_SH_STANDALONE
235 # undef IF_FEATURE_SH_STANDALONE
236 # undef IF_NOT_FEATURE_SH_STANDALONE
237 # define ENABLE_FEATURE_SH_STANDALONE 0
238 # define IF_FEATURE_SH_STANDALONE(...)
239 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
240 #endif
241
242 #ifndef PIPE_BUF
243 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
244 #endif
245
246 #if !BB_MMU
247 # error "Do not even bother, ash will not run on NOMMU machine"
248 #endif
249
250
251 /* ============ Hash table sizes. Configurable. */
252
253 #define VTABSIZE 39
254 #define ATABSIZE 39
255 #define CMDTABLESIZE 31         /* should be prime */
256
257
258 /* ============ Shell options */
259
260 static const char *const optletters_optnames[] = {
261         "e"   "errexit",
262         "f"   "noglob",
263         "I"   "ignoreeof",
264         "i"   "interactive",
265         "m"   "monitor",
266         "n"   "noexec",
267         "s"   "stdin",
268         "x"   "xtrace",
269         "v"   "verbose",
270         "C"   "noclobber",
271         "a"   "allexport",
272         "b"   "notify",
273         "u"   "nounset",
274         "\0"  "vi"
275 #if BASH_PIPEFAIL
276         ,"\0"  "pipefail"
277 #endif
278 #if DEBUG
279         ,"\0"  "nolog"
280         ,"\0"  "debug"
281 #endif
282 };
283
284 #define optletters(n)  optletters_optnames[n][0]
285 #define optnames(n)   (optletters_optnames[n] + 1)
286
287 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
288
289
290 /* ============ Misc data */
291
292 #define msg_illnum "Illegal number: %s"
293
294 /*
295  * We enclose jmp_buf in a structure so that we can declare pointers to
296  * jump locations.  The global variable handler contains the location to
297  * jump to when an exception occurs, and the global variable exception_type
298  * contains a code identifying the exception.  To implement nested
299  * exception handlers, the user should save the value of handler on entry
300  * to an inner scope, set handler to point to a jmploc structure for the
301  * inner scope, and restore handler on exit from the scope.
302  */
303 struct jmploc {
304         jmp_buf loc;
305 };
306
307 struct globals_misc {
308         uint8_t exitstatus;     /* exit status of last command */
309         uint8_t back_exitstatus;/* exit status of backquoted command */
310         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
311         int rootpid;            /* pid of main shell */
312         /* shell level: 0 for the main shell, 1 for its children, and so on */
313         int shlvl;
314 #define rootshell (!shlvl)
315         char *minusc;  /* argument to -c option */
316
317         char *curdir; // = nullstr;     /* current working directory */
318         char *physdir; // = nullstr;    /* physical working directory */
319
320         char *arg0; /* value of $0 */
321
322         struct jmploc *exception_handler;
323
324         volatile int suppress_int; /* counter */
325         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
326         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
327         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
328         smallint exception_type; /* kind of exception (0..5) */
329         /* exceptions */
330 #define EXINT 0         /* SIGINT received */
331 #define EXERROR 1       /* a generic error */
332 #define EXEXIT 4        /* exit the shell */
333
334         char nullstr[1];        /* zero length string */
335
336         char optlist[NOPTS];
337 #define eflag optlist[0]
338 #define fflag optlist[1]
339 #define Iflag optlist[2]
340 #define iflag optlist[3]
341 #define mflag optlist[4]
342 #define nflag optlist[5]
343 #define sflag optlist[6]
344 #define xflag optlist[7]
345 #define vflag optlist[8]
346 #define Cflag optlist[9]
347 #define aflag optlist[10]
348 #define bflag optlist[11]
349 #define uflag optlist[12]
350 #define viflag optlist[13]
351 #if BASH_PIPEFAIL
352 # define pipefail optlist[14]
353 #else
354 # define pipefail 0
355 #endif
356 #if DEBUG
357 # define nolog optlist[14 + BASH_PIPEFAIL]
358 # define debug optlist[15 + BASH_PIPEFAIL]
359 #endif
360
361         /* trap handler commands */
362         /*
363          * Sigmode records the current value of the signal handlers for the various
364          * modes.  A value of zero means that the current handler is not known.
365          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
366          */
367         char sigmode[NSIG - 1];
368 #define S_DFL      1            /* default signal handling (SIG_DFL) */
369 #define S_CATCH    2            /* signal is caught */
370 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
371 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
372
373         /* indicates specified signal received */
374         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
375         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
376         char *trap[NSIG];
377         char **trap_ptr;        /* used only by "trap hack" */
378
379         /* Rarely referenced stuff */
380 #if ENABLE_ASH_RANDOM_SUPPORT
381         random_t random_gen;
382 #endif
383         pid_t backgndpid;        /* pid of last background process */
384 };
385 extern struct globals_misc *const ash_ptr_to_globals_misc;
386 #define G_misc (*ash_ptr_to_globals_misc)
387 #define exitstatus        (G_misc.exitstatus )
388 #define back_exitstatus   (G_misc.back_exitstatus )
389 #define job_warning       (G_misc.job_warning)
390 #define rootpid     (G_misc.rootpid    )
391 #define shlvl       (G_misc.shlvl      )
392 #define minusc      (G_misc.minusc     )
393 #define curdir      (G_misc.curdir     )
394 #define physdir     (G_misc.physdir    )
395 #define arg0        (G_misc.arg0       )
396 #define exception_handler (G_misc.exception_handler)
397 #define exception_type    (G_misc.exception_type   )
398 #define suppress_int      (G_misc.suppress_int     )
399 #define pending_int       (G_misc.pending_int      )
400 #define got_sigchld       (G_misc.got_sigchld      )
401 #define pending_sig       (G_misc.pending_sig      )
402 #define nullstr     (G_misc.nullstr    )
403 #define optlist     (G_misc.optlist    )
404 #define sigmode     (G_misc.sigmode    )
405 #define gotsig      (G_misc.gotsig     )
406 #define may_have_traps    (G_misc.may_have_traps   )
407 #define trap        (G_misc.trap       )
408 #define trap_ptr    (G_misc.trap_ptr   )
409 #define random_gen  (G_misc.random_gen )
410 #define backgndpid  (G_misc.backgndpid )
411 #define INIT_G_misc() do { \
412         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
413         barrier(); \
414         curdir = nullstr; \
415         physdir = nullstr; \
416         trap_ptr = trap; \
417 } while (0)
418
419
420 /* ============ DEBUG */
421 #if DEBUG
422 static void trace_printf(const char *fmt, ...);
423 static void trace_vprintf(const char *fmt, va_list va);
424 # define TRACE(param)    trace_printf param
425 # define TRACEV(param)   trace_vprintf param
426 # define close(fd) do { \
427         int dfd = (fd); \
428         if (close(dfd) < 0) \
429                 bb_error_msg("bug on %d: closing %d(0x%x)", \
430                         __LINE__, dfd, dfd); \
431 } while (0)
432 #else
433 # define TRACE(param)
434 # define TRACEV(param)
435 #endif
436
437
438 /* ============ Utility functions */
439 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
440 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
441
442 static int
443 isdigit_str9(const char *str)
444 {
445         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
446         while (--maxlen && isdigit(*str))
447                 str++;
448         return (*str == '\0');
449 }
450
451 static const char *
452 var_end(const char *var)
453 {
454         while (*var)
455                 if (*var++ == '=')
456                         break;
457         return var;
458 }
459
460
461 /* ============ Interrupts / exceptions */
462
463 static void exitshell(void) NORETURN;
464
465 /*
466  * These macros allow the user to suspend the handling of interrupt signals
467  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
468  * much more efficient and portable.  (But hacking the kernel is so much
469  * more fun than worrying about efficiency and portability. :-))
470  */
471 #if DEBUG_INTONOFF
472 # define INT_OFF do { \
473         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
474         suppress_int++; \
475         barrier(); \
476 } while (0)
477 #else
478 # define INT_OFF do { \
479         suppress_int++; \
480         barrier(); \
481 } while (0)
482 #endif
483
484 /*
485  * Called to raise an exception.  Since C doesn't include exceptions, we
486  * just do a longjmp to the exception handler.  The type of exception is
487  * stored in the global variable "exception_type".
488  */
489 static void raise_exception(int) NORETURN;
490 static void
491 raise_exception(int e)
492 {
493 #if DEBUG
494         if (exception_handler == NULL)
495                 abort();
496 #endif
497         INT_OFF;
498         exception_type = e;
499         longjmp(exception_handler->loc, 1);
500 }
501 #if DEBUG
502 #define raise_exception(e) do { \
503         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
504         raise_exception(e); \
505 } while (0)
506 #endif
507
508 /*
509  * Called when a SIGINT is received.  (If the user specifies
510  * that SIGINT is to be trapped or ignored using the trap builtin, then
511  * this routine is not called.)  Suppressint is nonzero when interrupts
512  * are held using the INT_OFF macro.  (The test for iflag is just
513  * defensive programming.)
514  */
515 static void raise_interrupt(void) NORETURN;
516 static void
517 raise_interrupt(void)
518 {
519         pending_int = 0;
520         /* Signal is not automatically unmasked after it is raised,
521          * do it ourself - unmask all signals */
522         sigprocmask_allsigs(SIG_UNBLOCK);
523         /* pending_sig = 0; - now done in signal_handler() */
524
525         if (!(rootshell && iflag)) {
526                 /* Kill ourself with SIGINT */
527                 signal(SIGINT, SIG_DFL);
528                 raise(SIGINT);
529         }
530         /* bash: ^C even on empty command line sets $? */
531         exitstatus = SIGINT + 128;
532         raise_exception(EXINT);
533         /* NOTREACHED */
534 }
535 #if DEBUG
536 #define raise_interrupt() do { \
537         TRACE(("raising interrupt on line %d\n", __LINE__)); \
538         raise_interrupt(); \
539 } while (0)
540 #endif
541
542 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
543 int_on(void)
544 {
545         barrier();
546         if (--suppress_int == 0 && pending_int) {
547                 raise_interrupt();
548         }
549 }
550 #if DEBUG_INTONOFF
551 # define INT_ON do { \
552         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
553         int_on(); \
554 } while (0)
555 #else
556 # define INT_ON int_on()
557 #endif
558 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
559 force_int_on(void)
560 {
561         barrier();
562         suppress_int = 0;
563         if (pending_int)
564                 raise_interrupt();
565 }
566 #define FORCE_INT_ON force_int_on()
567
568 #define SAVE_INT(v) ((v) = suppress_int)
569
570 #define RESTORE_INT(v) do { \
571         barrier(); \
572         suppress_int = (v); \
573         if (suppress_int == 0 && pending_int) \
574                 raise_interrupt(); \
575 } while (0)
576
577
578 /* ============ Stdout/stderr output */
579
580 static void
581 outstr(const char *p, FILE *file)
582 {
583         INT_OFF;
584         fputs(p, file);
585         INT_ON;
586 }
587
588 static void
589 flush_stdout_stderr(void)
590 {
591         INT_OFF;
592         fflush_all();
593         INT_ON;
594 }
595
596 /* Was called outcslow(c,FILE*), but c was always '\n' */
597 static void
598 newline_and_flush(FILE *dest)
599 {
600         INT_OFF;
601         putc('\n', dest);
602         fflush(dest);
603         INT_ON;
604 }
605
606 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
607 static int
608 out1fmt(const char *fmt, ...)
609 {
610         va_list ap;
611         int r;
612
613         INT_OFF;
614         va_start(ap, fmt);
615         r = vprintf(fmt, ap);
616         va_end(ap);
617         INT_ON;
618         return r;
619 }
620
621 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
622 static int
623 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
624 {
625         va_list ap;
626         int ret;
627
628         INT_OFF;
629         va_start(ap, fmt);
630         ret = vsnprintf(outbuf, length, fmt, ap);
631         va_end(ap);
632         INT_ON;
633         return ret;
634 }
635
636 static void
637 out1str(const char *p)
638 {
639         outstr(p, stdout);
640 }
641
642 static void
643 out2str(const char *p)
644 {
645         outstr(p, stderr);
646         flush_stdout_stderr();
647 }
648
649
650 /* ============ Parser structures */
651
652 /* control characters in argument strings */
653 #define CTL_FIRST CTLESC
654 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
655 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
656 #define CTLENDVAR    ((unsigned char)'\203')
657 #define CTLBACKQ     ((unsigned char)'\204')
658 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
659 #define CTLENDARI    ((unsigned char)'\207')
660 #define CTLQUOTEMARK ((unsigned char)'\210')
661 #define CTL_LAST CTLQUOTEMARK
662
663 /* variable substitution byte (follows CTLVAR) */
664 #define VSTYPE  0x0f            /* type of variable substitution */
665 #define VSNUL   0x10            /* colon--treat the empty string as unset */
666
667 /* values of VSTYPE field */
668 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
669 #define VSMINUS         0x2     /* ${var-text} */
670 #define VSPLUS          0x3     /* ${var+text} */
671 #define VSQUESTION      0x4     /* ${var?message} */
672 #define VSASSIGN        0x5     /* ${var=text} */
673 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
674 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
675 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
676 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
677 #define VSLENGTH        0xa     /* ${#var} */
678 #if BASH_SUBSTR
679 #define VSSUBSTR        0xc     /* ${var:position:length} */
680 #endif
681 #if BASH_PATTERN_SUBST
682 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
683 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
684 #endif
685
686 static const char dolatstr[] ALIGN1 = {
687         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
688 };
689 #define DOLATSTRLEN 6
690
691 #define NCMD      0
692 #define NPIPE     1
693 #define NREDIR    2
694 #define NBACKGND  3
695 #define NSUBSHELL 4
696 #define NAND      5
697 #define NOR       6
698 #define NSEMI     7
699 #define NIF       8
700 #define NWHILE    9
701 #define NUNTIL   10
702 #define NFOR     11
703 #define NCASE    12
704 #define NCLIST   13
705 #define NDEFUN   14
706 #define NARG     15
707 #define NTO      16
708 #if BASH_REDIR_OUTPUT
709 #define NTO2     17
710 #endif
711 #define NCLOBBER 18
712 #define NFROM    19
713 #define NFROMTO  20
714 #define NAPPEND  21
715 #define NTOFD    22
716 #define NFROMFD  23
717 #define NHERE    24
718 #define NXHERE   25
719 #define NNOT     26
720 #define N_NUMBER 27
721
722 union node;
723
724 struct ncmd {
725         smallint type; /* Nxxxx */
726         union node *assign;
727         union node *args;
728         union node *redirect;
729 };
730
731 struct npipe {
732         smallint type;
733         smallint pipe_backgnd;
734         struct nodelist *cmdlist;
735 };
736
737 struct nredir {
738         smallint type;
739         union node *n;
740         union node *redirect;
741 };
742
743 struct nbinary {
744         smallint type;
745         union node *ch1;
746         union node *ch2;
747 };
748
749 struct nif {
750         smallint type;
751         union node *test;
752         union node *ifpart;
753         union node *elsepart;
754 };
755
756 struct nfor {
757         smallint type;
758         union node *args;
759         union node *body;
760         char *var;
761 };
762
763 struct ncase {
764         smallint type;
765         union node *expr;
766         union node *cases;
767 };
768
769 struct nclist {
770         smallint type;
771         union node *next;
772         union node *pattern;
773         union node *body;
774 };
775
776 struct narg {
777         smallint type;
778         union node *next;
779         char *text;
780         struct nodelist *backquote;
781 };
782
783 /* nfile and ndup layout must match!
784  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
785  * that it is actually NTO2 (>&file), and change its type.
786  */
787 struct nfile {
788         smallint type;
789         union node *next;
790         int fd;
791         int _unused_dupfd;
792         union node *fname;
793         char *expfname;
794 };
795
796 struct ndup {
797         smallint type;
798         union node *next;
799         int fd;
800         int dupfd;
801         union node *vname;
802         char *_unused_expfname;
803 };
804
805 struct nhere {
806         smallint type;
807         union node *next;
808         int fd;
809         union node *doc;
810 };
811
812 struct nnot {
813         smallint type;
814         union node *com;
815 };
816
817 union node {
818         smallint type;
819         struct ncmd ncmd;
820         struct npipe npipe;
821         struct nredir nredir;
822         struct nbinary nbinary;
823         struct nif nif;
824         struct nfor nfor;
825         struct ncase ncase;
826         struct nclist nclist;
827         struct narg narg;
828         struct nfile nfile;
829         struct ndup ndup;
830         struct nhere nhere;
831         struct nnot nnot;
832 };
833
834 /*
835  * NODE_EOF is returned by parsecmd when it encounters an end of file.
836  * It must be distinct from NULL.
837  */
838 #define NODE_EOF ((union node *) -1L)
839
840 struct nodelist {
841         struct nodelist *next;
842         union node *n;
843 };
844
845 struct funcnode {
846         int count;
847         union node n;
848 };
849
850 /*
851  * Free a parse tree.
852  */
853 static void
854 freefunc(struct funcnode *f)
855 {
856         if (f && --f->count < 0)
857                 free(f);
858 }
859
860
861 /* ============ Debugging output */
862
863 #if DEBUG
864
865 static FILE *tracefile;
866
867 static void
868 trace_printf(const char *fmt, ...)
869 {
870         va_list va;
871
872         if (debug != 1)
873                 return;
874         if (DEBUG_TIME)
875                 fprintf(tracefile, "%u ", (int) time(NULL));
876         if (DEBUG_PID)
877                 fprintf(tracefile, "[%u] ", (int) getpid());
878         if (DEBUG_SIG)
879                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
880         va_start(va, fmt);
881         vfprintf(tracefile, fmt, va);
882         va_end(va);
883 }
884
885 static void
886 trace_vprintf(const char *fmt, va_list va)
887 {
888         if (debug != 1)
889                 return;
890         vfprintf(tracefile, fmt, va);
891         fprintf(tracefile, "\n");
892 }
893
894 static void
895 trace_puts(const char *s)
896 {
897         if (debug != 1)
898                 return;
899         fputs(s, tracefile);
900 }
901
902 static void
903 trace_puts_quoted(char *s)
904 {
905         char *p;
906         char c;
907
908         if (debug != 1)
909                 return;
910         putc('"', tracefile);
911         for (p = s; *p; p++) {
912                 switch ((unsigned char)*p) {
913                 case '\n': c = 'n'; goto backslash;
914                 case '\t': c = 't'; goto backslash;
915                 case '\r': c = 'r'; goto backslash;
916                 case '\"': c = '\"'; goto backslash;
917                 case '\\': c = '\\'; goto backslash;
918                 case CTLESC: c = 'e'; goto backslash;
919                 case CTLVAR: c = 'v'; goto backslash;
920                 case CTLBACKQ: c = 'q'; goto backslash;
921  backslash:
922                         putc('\\', tracefile);
923                         putc(c, tracefile);
924                         break;
925                 default:
926                         if (*p >= ' ' && *p <= '~')
927                                 putc(*p, tracefile);
928                         else {
929                                 putc('\\', tracefile);
930                                 putc((*p >> 6) & 03, tracefile);
931                                 putc((*p >> 3) & 07, tracefile);
932                                 putc(*p & 07, tracefile);
933                         }
934                         break;
935                 }
936         }
937         putc('"', tracefile);
938 }
939
940 static void
941 trace_puts_args(char **ap)
942 {
943         if (debug != 1)
944                 return;
945         if (!*ap)
946                 return;
947         while (1) {
948                 trace_puts_quoted(*ap);
949                 if (!*++ap) {
950                         putc('\n', tracefile);
951                         break;
952                 }
953                 putc(' ', tracefile);
954         }
955 }
956
957 static void
958 opentrace(void)
959 {
960         char s[100];
961 #ifdef O_APPEND
962         int flags;
963 #endif
964
965         if (debug != 1) {
966                 if (tracefile)
967                         fflush(tracefile);
968                 /* leave open because libedit might be using it */
969                 return;
970         }
971         strcpy(s, "./trace");
972         if (tracefile) {
973                 if (!freopen(s, "a", tracefile)) {
974                         fprintf(stderr, "Can't re-open %s\n", s);
975                         debug = 0;
976                         return;
977                 }
978         } else {
979                 tracefile = fopen(s, "a");
980                 if (tracefile == NULL) {
981                         fprintf(stderr, "Can't open %s\n", s);
982                         debug = 0;
983                         return;
984                 }
985         }
986 #ifdef O_APPEND
987         flags = fcntl(fileno(tracefile), F_GETFL);
988         if (flags >= 0)
989                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
990 #endif
991         setlinebuf(tracefile);
992         fputs("\nTracing started.\n", tracefile);
993 }
994
995 static void
996 indent(int amount, char *pfx, FILE *fp)
997 {
998         int i;
999
1000         for (i = 0; i < amount; i++) {
1001                 if (pfx && i == amount - 1)
1002                         fputs(pfx, fp);
1003                 putc('\t', fp);
1004         }
1005 }
1006
1007 /* little circular references here... */
1008 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1009
1010 static void
1011 sharg(union node *arg, FILE *fp)
1012 {
1013         char *p;
1014         struct nodelist *bqlist;
1015         unsigned char subtype;
1016
1017         if (arg->type != NARG) {
1018                 out1fmt("<node type %d>\n", arg->type);
1019                 abort();
1020         }
1021         bqlist = arg->narg.backquote;
1022         for (p = arg->narg.text; *p; p++) {
1023                 switch ((unsigned char)*p) {
1024                 case CTLESC:
1025                         p++;
1026                         putc(*p, fp);
1027                         break;
1028                 case CTLVAR:
1029                         putc('$', fp);
1030                         putc('{', fp);
1031                         subtype = *++p;
1032                         if (subtype == VSLENGTH)
1033                                 putc('#', fp);
1034
1035                         while (*p != '=') {
1036                                 putc(*p, fp);
1037                                 p++;
1038                         }
1039
1040                         if (subtype & VSNUL)
1041                                 putc(':', fp);
1042
1043                         switch (subtype & VSTYPE) {
1044                         case VSNORMAL:
1045                                 putc('}', fp);
1046                                 break;
1047                         case VSMINUS:
1048                                 putc('-', fp);
1049                                 break;
1050                         case VSPLUS:
1051                                 putc('+', fp);
1052                                 break;
1053                         case VSQUESTION:
1054                                 putc('?', fp);
1055                                 break;
1056                         case VSASSIGN:
1057                                 putc('=', fp);
1058                                 break;
1059                         case VSTRIMLEFT:
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMLEFTMAX:
1063                                 putc('#', fp);
1064                                 putc('#', fp);
1065                                 break;
1066                         case VSTRIMRIGHT:
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSTRIMRIGHTMAX:
1070                                 putc('%', fp);
1071                                 putc('%', fp);
1072                                 break;
1073                         case VSLENGTH:
1074                                 break;
1075                         default:
1076                                 out1fmt("<subtype %d>", subtype);
1077                         }
1078                         break;
1079                 case CTLENDVAR:
1080                         putc('}', fp);
1081                         break;
1082                 case CTLBACKQ:
1083                         putc('$', fp);
1084                         putc('(', fp);
1085                         shtree(bqlist->n, -1, NULL, fp);
1086                         putc(')', fp);
1087                         break;
1088                 default:
1089                         putc(*p, fp);
1090                         break;
1091                 }
1092         }
1093 }
1094
1095 static void
1096 shcmd(union node *cmd, FILE *fp)
1097 {
1098         union node *np;
1099         int first;
1100         const char *s;
1101         int dftfd;
1102
1103         first = 1;
1104         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1105                 if (!first)
1106                         putc(' ', fp);
1107                 sharg(np, fp);
1108                 first = 0;
1109         }
1110         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1111                 if (!first)
1112                         putc(' ', fp);
1113                 dftfd = 0;
1114                 switch (np->nfile.type) {
1115                 case NTO:      s = ">>"+1; dftfd = 1; break;
1116                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1117                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1118 #if BASH_REDIR_OUTPUT
1119                 case NTO2:
1120 #endif
1121                 case NTOFD:    s = ">&"; dftfd = 1; break;
1122                 case NFROM:    s = "<"; break;
1123                 case NFROMFD:  s = "<&"; break;
1124                 case NFROMTO:  s = "<>"; break;
1125                 default:       s = "*error*"; break;
1126                 }
1127                 if (np->nfile.fd != dftfd)
1128                         fprintf(fp, "%d", np->nfile.fd);
1129                 fputs(s, fp);
1130                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1131                         fprintf(fp, "%d", np->ndup.dupfd);
1132                 } else {
1133                         sharg(np->nfile.fname, fp);
1134                 }
1135                 first = 0;
1136         }
1137 }
1138
1139 static void
1140 shtree(union node *n, int ind, char *pfx, FILE *fp)
1141 {
1142         struct nodelist *lp;
1143         const char *s;
1144
1145         if (n == NULL)
1146                 return;
1147
1148         indent(ind, pfx, fp);
1149
1150         if (n == NODE_EOF) {
1151                 fputs("<EOF>", fp);
1152                 return;
1153         }
1154
1155         switch (n->type) {
1156         case NSEMI:
1157                 s = "; ";
1158                 goto binop;
1159         case NAND:
1160                 s = " && ";
1161                 goto binop;
1162         case NOR:
1163                 s = " || ";
1164  binop:
1165                 shtree(n->nbinary.ch1, ind, NULL, fp);
1166                 /* if (ind < 0) */
1167                         fputs(s, fp);
1168                 shtree(n->nbinary.ch2, ind, NULL, fp);
1169                 break;
1170         case NCMD:
1171                 shcmd(n, fp);
1172                 if (ind >= 0)
1173                         putc('\n', fp);
1174                 break;
1175         case NPIPE:
1176                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1177                         shtree(lp->n, 0, NULL, fp);
1178                         if (lp->next)
1179                                 fputs(" | ", fp);
1180                 }
1181                 if (n->npipe.pipe_backgnd)
1182                         fputs(" &", fp);
1183                 if (ind >= 0)
1184                         putc('\n', fp);
1185                 break;
1186         default:
1187                 fprintf(fp, "<node type %d>", n->type);
1188                 if (ind >= 0)
1189                         putc('\n', fp);
1190                 break;
1191         }
1192 }
1193
1194 static void
1195 showtree(union node *n)
1196 {
1197         trace_puts("showtree called\n");
1198         shtree(n, 1, NULL, stderr);
1199 }
1200
1201 #endif /* DEBUG */
1202
1203
1204 /* ============ Parser data */
1205
1206 /*
1207  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1208  */
1209 struct strlist {
1210         struct strlist *next;
1211         char *text;
1212 };
1213
1214 struct alias;
1215
1216 struct strpush {
1217         struct strpush *prev;   /* preceding string on stack */
1218         char *prev_string;
1219         int prev_left_in_line;
1220 #if ENABLE_ASH_ALIAS
1221         struct alias *ap;       /* if push was associated with an alias */
1222 #endif
1223         char *string;           /* remember the string since it may change */
1224
1225         /* Remember last two characters for pungetc. */
1226         int lastc[2];
1227
1228         /* Number of outstanding calls to pungetc. */
1229         int unget;
1230 };
1231
1232 struct parsefile {
1233         struct parsefile *prev; /* preceding file on stack */
1234         int linno;              /* current line */
1235         int pf_fd;              /* file descriptor (or -1 if string) */
1236         int left_in_line;       /* number of chars left in this line */
1237         int left_in_buffer;     /* number of chars left in this buffer past the line */
1238         char *next_to_pgetc;    /* next char in buffer */
1239         char *buf;              /* input buffer */
1240         struct strpush *strpush; /* for pushing strings at this level */
1241         struct strpush basestrpush; /* so pushing one is fast */
1242
1243         /* Remember last two characters for pungetc. */
1244         int lastc[2];
1245
1246         /* Number of outstanding calls to pungetc. */
1247         int unget;
1248 };
1249
1250 static struct parsefile basepf;        /* top level input file */
1251 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1252 static int startlinno;                 /* line # where last token started */
1253 static char *commandname;              /* currently executing command */
1254
1255
1256 /* ============ Message printing */
1257
1258 static void
1259 ash_vmsg(const char *msg, va_list ap)
1260 {
1261         fprintf(stderr, "%s: ", arg0);
1262         if (commandname) {
1263                 if (strcmp(arg0, commandname))
1264                         fprintf(stderr, "%s: ", commandname);
1265                 if (!iflag || g_parsefile->pf_fd > 0)
1266                         fprintf(stderr, "line %d: ", startlinno);
1267         }
1268         vfprintf(stderr, msg, ap);
1269         newline_and_flush(stderr);
1270 }
1271
1272 /*
1273  * Exverror is called to raise the error exception.  If the second argument
1274  * is not NULL then error prints an error message using printf style
1275  * formatting.  It then raises the error exception.
1276  */
1277 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1278 static void
1279 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1280 {
1281 #if DEBUG
1282         if (msg) {
1283                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1284                 TRACEV((msg, ap));
1285         } else
1286                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1287         if (msg)
1288 #endif
1289                 ash_vmsg(msg, ap);
1290
1291         flush_stdout_stderr();
1292         raise_exception(cond);
1293         /* NOTREACHED */
1294 }
1295
1296 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1297 static void
1298 ash_msg_and_raise_error(const char *msg, ...)
1299 {
1300         va_list ap;
1301
1302         exitstatus = 2;
1303
1304         va_start(ap, msg);
1305         ash_vmsg_and_raise(EXERROR, msg, ap);
1306         /* NOTREACHED */
1307         va_end(ap);
1308 }
1309
1310 /*
1311  * Use '%m' to append error string on platforms that support it, '%s' and
1312  * strerror() on those that don't.
1313  *
1314  * 'fmt' must be a string literal.
1315  */
1316 #ifdef HAVE_PRINTF_PERCENTM
1317 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1318 #else
1319 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1320 #endif
1321
1322 static void raise_error_syntax(const char *) NORETURN;
1323 static void
1324 raise_error_syntax(const char *msg)
1325 {
1326         ash_msg_and_raise_error("syntax error: %s", msg);
1327         /* NOTREACHED */
1328 }
1329
1330 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1331 static void
1332 ash_msg_and_raise(int cond, const char *msg, ...)
1333 {
1334         va_list ap;
1335
1336         va_start(ap, msg);
1337         ash_vmsg_and_raise(cond, msg, ap);
1338         /* NOTREACHED */
1339         va_end(ap);
1340 }
1341
1342 /*
1343  * error/warning routines for external builtins
1344  */
1345 static void
1346 ash_msg(const char *fmt, ...)
1347 {
1348         va_list ap;
1349
1350         va_start(ap, fmt);
1351         ash_vmsg(fmt, ap);
1352         va_end(ap);
1353 }
1354
1355 /*
1356  * Return a string describing an error.  The returned string may be a
1357  * pointer to a static buffer that will be overwritten on the next call.
1358  * Action describes the operation that got the error.
1359  */
1360 static const char *
1361 errmsg(int e, const char *em)
1362 {
1363         if (e == ENOENT || e == ENOTDIR) {
1364                 return em;
1365         }
1366         return strerror(e);
1367 }
1368
1369
1370 /* ============ Memory allocation */
1371
1372 #if 0
1373 /* I consider these wrappers nearly useless:
1374  * ok, they return you to nearest exception handler, but
1375  * how much memory do you leak in the process, making
1376  * memory starvation worse?
1377  */
1378 static void *
1379 ckrealloc(void * p, size_t nbytes)
1380 {
1381         p = realloc(p, nbytes);
1382         if (!p)
1383                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1384         return p;
1385 }
1386
1387 static void *
1388 ckmalloc(size_t nbytes)
1389 {
1390         return ckrealloc(NULL, nbytes);
1391 }
1392
1393 static void *
1394 ckzalloc(size_t nbytes)
1395 {
1396         return memset(ckmalloc(nbytes), 0, nbytes);
1397 }
1398
1399 static char *
1400 ckstrdup(const char *s)
1401 {
1402         char *p = strdup(s);
1403         if (!p)
1404                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1405         return p;
1406 }
1407 #else
1408 /* Using bbox equivalents. They exit if out of memory */
1409 # define ckrealloc xrealloc
1410 # define ckmalloc  xmalloc
1411 # define ckzalloc  xzalloc
1412 # define ckstrdup  xstrdup
1413 #endif
1414
1415 /*
1416  * It appears that grabstackstr() will barf with such alignments
1417  * because stalloc() will return a string allocated in a new stackblock.
1418  */
1419 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1420 enum {
1421         /* Most machines require the value returned from malloc to be aligned
1422          * in some way.  The following macro will get this right
1423          * on many machines.  */
1424         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1425         /* Minimum size of a block */
1426         MINSIZE = SHELL_ALIGN(504),
1427 };
1428
1429 struct stack_block {
1430         struct stack_block *prev;
1431         char space[MINSIZE];
1432 };
1433
1434 struct stackmark {
1435         struct stack_block *stackp;
1436         char *stacknxt;
1437         size_t stacknleft;
1438 };
1439
1440
1441 struct globals_memstack {
1442         struct stack_block *g_stackp; // = &stackbase;
1443         char *g_stacknxt; // = stackbase.space;
1444         char *sstrend; // = stackbase.space + MINSIZE;
1445         size_t g_stacknleft; // = MINSIZE;
1446         struct stack_block stackbase;
1447 };
1448 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1449 #define G_memstack (*ash_ptr_to_globals_memstack)
1450 #define g_stackp     (G_memstack.g_stackp    )
1451 #define g_stacknxt   (G_memstack.g_stacknxt  )
1452 #define sstrend      (G_memstack.sstrend     )
1453 #define g_stacknleft (G_memstack.g_stacknleft)
1454 #define stackbase    (G_memstack.stackbase   )
1455 #define INIT_G_memstack() do { \
1456         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1457         barrier(); \
1458         g_stackp = &stackbase; \
1459         g_stacknxt = stackbase.space; \
1460         g_stacknleft = MINSIZE; \
1461         sstrend = stackbase.space + MINSIZE; \
1462 } while (0)
1463
1464
1465 #define stackblock()     ((void *)g_stacknxt)
1466 #define stackblocksize() g_stacknleft
1467
1468 /*
1469  * Parse trees for commands are allocated in lifo order, so we use a stack
1470  * to make this more efficient, and also to avoid all sorts of exception
1471  * handling code to handle interrupts in the middle of a parse.
1472  *
1473  * The size 504 was chosen because the Ultrix malloc handles that size
1474  * well.
1475  */
1476 static void *
1477 stalloc(size_t nbytes)
1478 {
1479         char *p;
1480         size_t aligned;
1481
1482         aligned = SHELL_ALIGN(nbytes);
1483         if (aligned > g_stacknleft) {
1484                 size_t len;
1485                 size_t blocksize;
1486                 struct stack_block *sp;
1487
1488                 blocksize = aligned;
1489                 if (blocksize < MINSIZE)
1490                         blocksize = MINSIZE;
1491                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1492                 if (len < blocksize)
1493                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1494                 INT_OFF;
1495                 sp = ckmalloc(len);
1496                 sp->prev = g_stackp;
1497                 g_stacknxt = sp->space;
1498                 g_stacknleft = blocksize;
1499                 sstrend = g_stacknxt + blocksize;
1500                 g_stackp = sp;
1501                 INT_ON;
1502         }
1503         p = g_stacknxt;
1504         g_stacknxt += aligned;
1505         g_stacknleft -= aligned;
1506         return p;
1507 }
1508
1509 static void *
1510 stzalloc(size_t nbytes)
1511 {
1512         return memset(stalloc(nbytes), 0, nbytes);
1513 }
1514
1515 static void
1516 stunalloc(void *p)
1517 {
1518 #if DEBUG
1519         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1520                 write(STDERR_FILENO, "stunalloc\n", 10);
1521                 abort();
1522         }
1523 #endif
1524         g_stacknleft += g_stacknxt - (char *)p;
1525         g_stacknxt = p;
1526 }
1527
1528 /*
1529  * Like strdup but works with the ash stack.
1530  */
1531 static char *
1532 sstrdup(const char *p)
1533 {
1534         size_t len = strlen(p) + 1;
1535         return memcpy(stalloc(len), p, len);
1536 }
1537
1538 static inline void
1539 grabstackblock(size_t len)
1540 {
1541         stalloc(len);
1542 }
1543
1544 static void
1545 pushstackmark(struct stackmark *mark, size_t len)
1546 {
1547         mark->stackp = g_stackp;
1548         mark->stacknxt = g_stacknxt;
1549         mark->stacknleft = g_stacknleft;
1550         grabstackblock(len);
1551 }
1552
1553 static void
1554 setstackmark(struct stackmark *mark)
1555 {
1556         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1557 }
1558
1559 static void
1560 popstackmark(struct stackmark *mark)
1561 {
1562         struct stack_block *sp;
1563
1564         if (!mark->stackp)
1565                 return;
1566
1567         INT_OFF;
1568         while (g_stackp != mark->stackp) {
1569                 sp = g_stackp;
1570                 g_stackp = sp->prev;
1571                 free(sp);
1572         }
1573         g_stacknxt = mark->stacknxt;
1574         g_stacknleft = mark->stacknleft;
1575         sstrend = mark->stacknxt + mark->stacknleft;
1576         INT_ON;
1577 }
1578
1579 /*
1580  * When the parser reads in a string, it wants to stick the string on the
1581  * stack and only adjust the stack pointer when it knows how big the
1582  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1583  * of space on top of the stack and stackblocklen returns the length of
1584  * this block.  Growstackblock will grow this space by at least one byte,
1585  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1586  * part of the block that has been used.
1587  */
1588 static void
1589 growstackblock(void)
1590 {
1591         size_t newlen;
1592
1593         newlen = g_stacknleft * 2;
1594         if (newlen < g_stacknleft)
1595                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1596         if (newlen < 128)
1597                 newlen += 128;
1598
1599         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1600                 struct stack_block *sp;
1601                 struct stack_block *prevstackp;
1602                 size_t grosslen;
1603
1604                 INT_OFF;
1605                 sp = g_stackp;
1606                 prevstackp = sp->prev;
1607                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1608                 sp = ckrealloc(sp, grosslen);
1609                 sp->prev = prevstackp;
1610                 g_stackp = sp;
1611                 g_stacknxt = sp->space;
1612                 g_stacknleft = newlen;
1613                 sstrend = sp->space + newlen;
1614                 INT_ON;
1615         } else {
1616                 char *oldspace = g_stacknxt;
1617                 size_t oldlen = g_stacknleft;
1618                 char *p = stalloc(newlen);
1619
1620                 /* free the space we just allocated */
1621                 g_stacknxt = memcpy(p, oldspace, oldlen);
1622                 g_stacknleft += newlen;
1623         }
1624 }
1625
1626 /*
1627  * The following routines are somewhat easier to use than the above.
1628  * The user declares a variable of type STACKSTR, which may be declared
1629  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1630  * the user uses the macro STPUTC to add characters to the string.  In
1631  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1632  * grown as necessary.  When the user is done, she can just leave the
1633  * string there and refer to it using stackblock().  Or she can allocate
1634  * the space for it using grabstackstr().  If it is necessary to allow
1635  * someone else to use the stack temporarily and then continue to grow
1636  * the string, the user should use grabstack to allocate the space, and
1637  * then call ungrabstr(p) to return to the previous mode of operation.
1638  *
1639  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1640  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1641  * is space for at least one character.
1642  */
1643 static void *
1644 growstackstr(void)
1645 {
1646         size_t len = stackblocksize();
1647         growstackblock();
1648         return (char *)stackblock() + len;
1649 }
1650
1651 /*
1652  * Called from CHECKSTRSPACE.
1653  */
1654 static char *
1655 makestrspace(size_t newlen, char *p)
1656 {
1657         size_t len = p - g_stacknxt;
1658         size_t size;
1659
1660         for (;;) {
1661                 size_t nleft;
1662
1663                 size = stackblocksize();
1664                 nleft = size - len;
1665                 if (nleft >= newlen)
1666                         break;
1667                 growstackblock();
1668         }
1669         return (char *)stackblock() + len;
1670 }
1671
1672 static char *
1673 stack_nputstr(const char *s, size_t n, char *p)
1674 {
1675         p = makestrspace(n, p);
1676         p = (char *)mempcpy(p, s, n);
1677         return p;
1678 }
1679
1680 static char *
1681 stack_putstr(const char *s, char *p)
1682 {
1683         return stack_nputstr(s, strlen(s), p);
1684 }
1685
1686 static char *
1687 _STPUTC(int c, char *p)
1688 {
1689         if (p == sstrend)
1690                 p = growstackstr();
1691         *p++ = c;
1692         return p;
1693 }
1694
1695 #define STARTSTACKSTR(p)        ((p) = stackblock())
1696 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1697 #define CHECKSTRSPACE(n, p) do { \
1698         char *q = (p); \
1699         size_t l = (n); \
1700         size_t m = sstrend - q; \
1701         if (l > m) \
1702                 (p) = makestrspace(l, q); \
1703 } while (0)
1704 #define USTPUTC(c, p)           (*(p)++ = (c))
1705 #define STACKSTRNUL(p) do { \
1706         if ((p) == sstrend) \
1707                 (p) = growstackstr(); \
1708         *(p) = '\0'; \
1709 } while (0)
1710 #define STUNPUTC(p)             (--(p))
1711 #define STTOPC(p)               ((p)[-1])
1712 #define STADJUST(amount, p)     ((p) += (amount))
1713
1714 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1715 #define ungrabstackstr(s, p)    stunalloc(s)
1716 #define stackstrend()           ((void *)sstrend)
1717
1718
1719 /* ============ String helpers */
1720
1721 /*
1722  * prefix -- see if pfx is a prefix of string.
1723  */
1724 static char *
1725 prefix(const char *string, const char *pfx)
1726 {
1727         while (*pfx) {
1728                 if (*pfx++ != *string++)
1729                         return NULL;
1730         }
1731         return (char *) string;
1732 }
1733
1734 /*
1735  * Check for a valid number.  This should be elsewhere.
1736  */
1737 static int
1738 is_number(const char *p)
1739 {
1740         do {
1741                 if (!isdigit(*p))
1742                         return 0;
1743         } while (*++p != '\0');
1744         return 1;
1745 }
1746
1747 /*
1748  * Convert a string of digits to an integer, printing an error message on
1749  * failure.
1750  */
1751 static int
1752 number(const char *s)
1753 {
1754         if (!is_number(s))
1755                 ash_msg_and_raise_error(msg_illnum, s);
1756         return atoi(s);
1757 }
1758
1759 /*
1760  * Produce a single quoted string suitable as input to the shell.
1761  * The return string is allocated on the stack.
1762  */
1763 static char *
1764 single_quote(const char *s)
1765 {
1766         char *p;
1767
1768         STARTSTACKSTR(p);
1769
1770         do {
1771                 char *q;
1772                 size_t len;
1773
1774                 len = strchrnul(s, '\'') - s;
1775
1776                 q = p = makestrspace(len + 3, p);
1777
1778                 *q++ = '\'';
1779                 q = (char *)mempcpy(q, s, len);
1780                 *q++ = '\'';
1781                 s += len;
1782
1783                 STADJUST(q - p, p);
1784
1785                 if (*s != '\'')
1786                         break;
1787                 len = 0;
1788                 do len++; while (*++s == '\'');
1789
1790                 q = p = makestrspace(len + 3, p);
1791
1792                 *q++ = '"';
1793                 q = (char *)mempcpy(q, s - len, len);
1794                 *q++ = '"';
1795
1796                 STADJUST(q - p, p);
1797         } while (*s);
1798
1799         USTPUTC('\0', p);
1800
1801         return stackblock();
1802 }
1803
1804 /*
1805  * Produce a possibly single quoted string suitable as input to the shell.
1806  * If quoting was done, the return string is allocated on the stack,
1807  * otherwise a pointer to the original string is returned.
1808  */
1809 static const char *
1810 maybe_single_quote(const char *s)
1811 {
1812         const char *p = s;
1813
1814         while (*p) {
1815                 /* Assuming ACSII */
1816                 /* quote ctrl_chars space !"#$%&'()* */
1817                 if (*p < '+')
1818                         goto need_quoting;
1819                 /* quote ;<=>? */
1820                 if (*p >= ';' && *p <= '?')
1821                         goto need_quoting;
1822                 /* quote `[\ */
1823                 if (*p == '`')
1824                         goto need_quoting;
1825                 if (*p == '[')
1826                         goto need_quoting;
1827                 if (*p == '\\')
1828                         goto need_quoting;
1829                 /* quote {|}~ DEL and high bytes */
1830                 if (*p > 'z')
1831                         goto need_quoting;
1832                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1833                 /* TODO: maybe avoid quoting % */
1834                 p++;
1835         }
1836         return s;
1837
1838  need_quoting:
1839         return single_quote(s);
1840 }
1841
1842
1843 /* ============ nextopt */
1844
1845 static char **argptr;                  /* argument list for builtin commands */
1846 static char *optionarg;                /* set by nextopt (like getopt) */
1847 static char *optptr;                   /* used by nextopt */
1848
1849 /*
1850  * XXX - should get rid of. Have all builtins use getopt(3).
1851  * The library getopt must have the BSD extension static variable
1852  * "optreset", otherwise it can't be used within the shell safely.
1853  *
1854  * Standard option processing (a la getopt) for builtin routines.
1855  * The only argument that is passed to nextopt is the option string;
1856  * the other arguments are unnecessary. It returns the character,
1857  * or '\0' on end of input.
1858  */
1859 static int
1860 nextopt(const char *optstring)
1861 {
1862         char *p;
1863         const char *q;
1864         char c;
1865
1866         p = optptr;
1867         if (p == NULL || *p == '\0') {
1868                 /* We ate entire "-param", take next one */
1869                 p = *argptr;
1870                 if (p == NULL)
1871                         return '\0';
1872                 if (*p != '-')
1873                         return '\0';
1874                 if (*++p == '\0') /* just "-" ? */
1875                         return '\0';
1876                 argptr++;
1877                 if (LONE_DASH(p)) /* "--" ? */
1878                         return '\0';
1879                 /* p => next "-param" */
1880         }
1881         /* p => some option char in the middle of a "-param" */
1882         c = *p++;
1883         for (q = optstring; *q != c;) {
1884                 if (*q == '\0')
1885                         ash_msg_and_raise_error("illegal option -%c", c);
1886                 if (*++q == ':')
1887                         q++;
1888         }
1889         if (*++q == ':') {
1890                 if (*p == '\0') {
1891                         p = *argptr++;
1892                         if (p == NULL)
1893                                 ash_msg_and_raise_error("no arg for -%c option", c);
1894                 }
1895                 optionarg = p;
1896                 p = NULL;
1897         }
1898         optptr = p;
1899         return c;
1900 }
1901
1902
1903 /* ============ Shell variables */
1904
1905 /*
1906  * The parsefile structure pointed to by the global variable parsefile
1907  * contains information about the current file being read.
1908  */
1909 struct shparam {
1910         int nparam;             /* # of positional parameters (without $0) */
1911 #if ENABLE_ASH_GETOPTS
1912         int optind;             /* next parameter to be processed by getopts */
1913         int optoff;             /* used by getopts */
1914 #endif
1915         unsigned char malloced; /* if parameter list dynamically allocated */
1916         char **p;               /* parameter list */
1917 };
1918
1919 /*
1920  * Free the list of positional parameters.
1921  */
1922 static void
1923 freeparam(volatile struct shparam *param)
1924 {
1925         if (param->malloced) {
1926                 char **ap, **ap1;
1927                 ap = ap1 = param->p;
1928                 while (*ap)
1929                         free(*ap++);
1930                 free(ap1);
1931         }
1932 }
1933
1934 #if ENABLE_ASH_GETOPTS
1935 static void FAST_FUNC getoptsreset(const char *value);
1936 #endif
1937
1938 struct var {
1939         struct var *next;               /* next entry in hash list */
1940         int flags;                      /* flags are defined above */
1941         const char *var_text;           /* name=value */
1942         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1943                                         /* the variable gets set/unset */
1944 };
1945
1946 struct localvar {
1947         struct localvar *next;          /* next local variable in list */
1948         struct var *vp;                 /* the variable that was made local */
1949         int flags;                      /* saved flags */
1950         const char *text;               /* saved text */
1951 };
1952
1953 /* flags */
1954 #define VEXPORT         0x01    /* variable is exported */
1955 #define VREADONLY       0x02    /* variable cannot be modified */
1956 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1957 #define VTEXTFIXED      0x08    /* text is statically allocated */
1958 #define VSTACK          0x10    /* text is allocated on the stack */
1959 #define VUNSET          0x20    /* the variable is not set */
1960 #define VNOFUNC         0x40    /* don't call the callback function */
1961 #define VNOSET          0x80    /* do not set variable - just readonly test */
1962 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1963 #if ENABLE_ASH_RANDOM_SUPPORT
1964 # define VDYNAMIC       0x200   /* dynamic variable */
1965 #else
1966 # define VDYNAMIC       0
1967 #endif
1968
1969
1970 /* Need to be before varinit_data[] */
1971 #if ENABLE_LOCALE_SUPPORT
1972 static void FAST_FUNC
1973 change_lc_all(const char *value)
1974 {
1975         if (value && *value != '\0')
1976                 setlocale(LC_ALL, value);
1977 }
1978 static void FAST_FUNC
1979 change_lc_ctype(const char *value)
1980 {
1981         if (value && *value != '\0')
1982                 setlocale(LC_CTYPE, value);
1983 }
1984 #endif
1985 #if ENABLE_ASH_MAIL
1986 static void chkmail(void);
1987 static void changemail(const char *var_value) FAST_FUNC;
1988 #else
1989 # define chkmail()  ((void)0)
1990 #endif
1991 static void changepath(const char *) FAST_FUNC;
1992 #if ENABLE_ASH_RANDOM_SUPPORT
1993 static void change_random(const char *) FAST_FUNC;
1994 #endif
1995
1996 static const struct {
1997         int flags;
1998         const char *var_text;
1999         void (*var_func)(const char *) FAST_FUNC;
2000 } varinit_data[] = {
2001         /*
2002          * Note: VEXPORT would not work correctly here for NOFORK applets:
2003          * some environment strings may be constant.
2004          */
2005         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2006 #if ENABLE_ASH_MAIL
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2008         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2009 #endif
2010         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2011         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2013         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2014 #if ENABLE_ASH_GETOPTS
2015         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2016 #endif
2017 #if ENABLE_ASH_RANDOM_SUPPORT
2018         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2019 #endif
2020 #if ENABLE_LOCALE_SUPPORT
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2022         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2023 #endif
2024 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2025         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2026 #endif
2027 };
2028
2029 struct redirtab;
2030
2031 struct globals_var {
2032         struct shparam shellparam;      /* $@ current positional parameters */
2033         struct redirtab *redirlist;
2034         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2035         struct var *vartab[VTABSIZE];
2036         struct var varinit[ARRAY_SIZE(varinit_data)];
2037 };
2038 extern struct globals_var *const ash_ptr_to_globals_var;
2039 #define G_var (*ash_ptr_to_globals_var)
2040 #define shellparam    (G_var.shellparam   )
2041 //#define redirlist     (G_var.redirlist    )
2042 #define preverrout_fd (G_var.preverrout_fd)
2043 #define vartab        (G_var.vartab       )
2044 #define varinit       (G_var.varinit      )
2045 #define INIT_G_var() do { \
2046         unsigned i; \
2047         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2048         barrier(); \
2049         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2050                 varinit[i].flags    = varinit_data[i].flags; \
2051                 varinit[i].var_text = varinit_data[i].var_text; \
2052                 varinit[i].var_func = varinit_data[i].var_func; \
2053         } \
2054 } while (0)
2055
2056 #define vifs      varinit[0]
2057 #if ENABLE_ASH_MAIL
2058 # define vmail    (&vifs)[1]
2059 # define vmpath   (&vmail)[1]
2060 # define vpath    (&vmpath)[1]
2061 #else
2062 # define vpath    (&vifs)[1]
2063 #endif
2064 #define vps1      (&vpath)[1]
2065 #define vps2      (&vps1)[1]
2066 #define vps4      (&vps2)[1]
2067 #if ENABLE_ASH_GETOPTS
2068 # define voptind  (&vps4)[1]
2069 # if ENABLE_ASH_RANDOM_SUPPORT
2070 #  define vrandom (&voptind)[1]
2071 # endif
2072 #else
2073 # if ENABLE_ASH_RANDOM_SUPPORT
2074 #  define vrandom (&vps4)[1]
2075 # endif
2076 #endif
2077
2078 /*
2079  * The following macros access the values of the above variables.
2080  * They have to skip over the name.  They return the null string
2081  * for unset variables.
2082  */
2083 #define ifsval()        (vifs.var_text + 4)
2084 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2085 #if ENABLE_ASH_MAIL
2086 # define mailval()      (vmail.var_text + 5)
2087 # define mpathval()     (vmpath.var_text + 9)
2088 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2089 #endif
2090 #define pathval()       (vpath.var_text + 5)
2091 #define ps1val()        (vps1.var_text + 4)
2092 #define ps2val()        (vps2.var_text + 4)
2093 #define ps4val()        (vps4.var_text + 4)
2094 #if ENABLE_ASH_GETOPTS
2095 # define optindval()    (voptind.var_text + 7)
2096 #endif
2097
2098 #if ENABLE_ASH_GETOPTS
2099 static void FAST_FUNC
2100 getoptsreset(const char *value)
2101 {
2102         shellparam.optind = 1;
2103         if (is_number(value))
2104                 shellparam.optind = number(value) ?: 1;
2105         shellparam.optoff = -1;
2106 }
2107 #endif
2108
2109 /*
2110  * Compares two strings up to the first = or '\0'.  The first
2111  * string must be terminated by '='; the second may be terminated by
2112  * either '=' or '\0'.
2113  */
2114 static int
2115 varcmp(const char *p, const char *q)
2116 {
2117         int c, d;
2118
2119         while ((c = *p) == (d = *q)) {
2120                 if (c == '\0' || c == '=')
2121                         goto out;
2122                 p++;
2123                 q++;
2124         }
2125         if (c == '=')
2126                 c = '\0';
2127         if (d == '=')
2128                 d = '\0';
2129  out:
2130         return c - d;
2131 }
2132
2133 /*
2134  * Find the appropriate entry in the hash table from the name.
2135  */
2136 static struct var **
2137 hashvar(const char *p)
2138 {
2139         unsigned hashval;
2140
2141         hashval = ((unsigned char) *p) << 4;
2142         while (*p && *p != '=')
2143                 hashval += (unsigned char) *p++;
2144         return &vartab[hashval % VTABSIZE];
2145 }
2146
2147 static int
2148 vpcmp(const void *a, const void *b)
2149 {
2150         return varcmp(*(const char **)a, *(const char **)b);
2151 }
2152
2153 /*
2154  * This routine initializes the builtin variables.
2155  */
2156 static void
2157 initvar(void)
2158 {
2159         struct var *vp;
2160         struct var *end;
2161         struct var **vpp;
2162
2163         /*
2164          * PS1 depends on uid
2165          */
2166 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2167         vps1.var_text = "PS1=\\w \\$ ";
2168 #else
2169         if (!geteuid())
2170                 vps1.var_text = "PS1=# ";
2171 #endif
2172         vp = varinit;
2173         end = vp + ARRAY_SIZE(varinit);
2174         do {
2175                 vpp = hashvar(vp->var_text);
2176                 vp->next = *vpp;
2177                 *vpp = vp;
2178         } while (++vp < end);
2179 }
2180
2181 static struct var **
2182 findvar(struct var **vpp, const char *name)
2183 {
2184         for (; *vpp; vpp = &(*vpp)->next) {
2185                 if (varcmp((*vpp)->var_text, name) == 0) {
2186                         break;
2187                 }
2188         }
2189         return vpp;
2190 }
2191
2192 /*
2193  * Find the value of a variable.  Returns NULL if not set.
2194  */
2195 static const char* FAST_FUNC
2196 lookupvar(const char *name)
2197 {
2198         struct var *v;
2199
2200         v = *findvar(hashvar(name), name);
2201         if (v) {
2202 #if ENABLE_ASH_RANDOM_SUPPORT
2203         /*
2204          * Dynamic variables are implemented roughly the same way they are
2205          * in bash. Namely, they're "special" so long as they aren't unset.
2206          * As soon as they're unset, they're no longer dynamic, and dynamic
2207          * lookup will no longer happen at that point. -- PFM.
2208          */
2209                 if (v->flags & VDYNAMIC)
2210                         v->var_func(NULL);
2211 #endif
2212                 if (!(v->flags & VUNSET))
2213                         return var_end(v->var_text);
2214         }
2215         return NULL;
2216 }
2217
2218 #if ENABLE_UNICODE_SUPPORT
2219 static void
2220 reinit_unicode_for_ash(void)
2221 {
2222         /* Unicode support should be activated even if LANG is set
2223          * _during_ shell execution, not only if it was set when
2224          * shell was started. Therefore, re-check LANG every time:
2225          */
2226         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2227          || ENABLE_UNICODE_USING_LOCALE
2228         ) {
2229                 const char *s = lookupvar("LC_ALL");
2230                 if (!s) s = lookupvar("LC_CTYPE");
2231                 if (!s) s = lookupvar("LANG");
2232                 reinit_unicode(s);
2233         }
2234 }
2235 #else
2236 # define reinit_unicode_for_ash() ((void)0)
2237 #endif
2238
2239 /*
2240  * Search the environment of a builtin command.
2241  */
2242 static ALWAYS_INLINE const char *
2243 bltinlookup(const char *name)
2244 {
2245         return lookupvar(name);
2246 }
2247
2248 /*
2249  * Same as setvar except that the variable and value are passed in
2250  * the first argument as name=value.  Since the first argument will
2251  * be actually stored in the table, it should not be a string that
2252  * will go away.
2253  * Called with interrupts off.
2254  */
2255 static struct var *
2256 setvareq(char *s, int flags)
2257 {
2258         struct var *vp, **vpp;
2259
2260         vpp = hashvar(s);
2261         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2262         vpp = findvar(vpp, s);
2263         vp = *vpp;
2264         if (vp) {
2265                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2266                         const char *n;
2267
2268                         if (flags & VNOSAVE)
2269                                 free(s);
2270                         n = vp->var_text;
2271                         exitstatus = 1;
2272                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2273                 }
2274
2275                 if (flags & VNOSET)
2276                         goto out;
2277
2278                 if (vp->var_func && !(flags & VNOFUNC))
2279                         vp->var_func(var_end(s));
2280
2281                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2282                         free((char*)vp->var_text);
2283
2284                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2285                         *vpp = vp->next;
2286                         free(vp);
2287  out_free:
2288                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2289                                 free(s);
2290                         goto out;
2291                 }
2292
2293                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2294         } else {
2295                 /* variable s is not found */
2296                 if (flags & VNOSET)
2297                         goto out;
2298                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2299                         goto out_free;
2300                 vp = ckzalloc(sizeof(*vp));
2301                 vp->next = *vpp;
2302                 /*vp->func = NULL; - ckzalloc did it */
2303                 *vpp = vp;
2304         }
2305         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2306                 s = ckstrdup(s);
2307         vp->var_text = s;
2308         vp->flags = flags;
2309
2310  out:
2311         return vp;
2312 }
2313
2314 /*
2315  * Set the value of a variable.  The flags argument is ored with the
2316  * flags of the variable.  If val is NULL, the variable is unset.
2317  */
2318 static struct var *
2319 setvar(const char *name, const char *val, int flags)
2320 {
2321         const char *q;
2322         char *p;
2323         char *nameeq;
2324         size_t namelen;
2325         size_t vallen;
2326         struct var *vp;
2327
2328         q = endofname(name);
2329         p = strchrnul(q, '=');
2330         namelen = p - name;
2331         if (!namelen || p != q)
2332                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2333         vallen = 0;
2334         if (val == NULL) {
2335                 flags |= VUNSET;
2336         } else {
2337                 vallen = strlen(val);
2338         }
2339
2340         INT_OFF;
2341         nameeq = ckmalloc(namelen + vallen + 2);
2342         p = mempcpy(nameeq, name, namelen);
2343         if (val) {
2344                 *p++ = '=';
2345                 p = mempcpy(p, val, vallen);
2346         }
2347         *p = '\0';
2348         vp = setvareq(nameeq, flags | VNOSAVE);
2349         INT_ON;
2350
2351         return vp;
2352 }
2353
2354 static void FAST_FUNC
2355 setvar0(const char *name, const char *val)
2356 {
2357         setvar(name, val, 0);
2358 }
2359
2360 /*
2361  * Unset the specified variable.
2362  */
2363 static void
2364 unsetvar(const char *s)
2365 {
2366         setvar(s, NULL, 0);
2367 }
2368
2369 /*
2370  * Process a linked list of variable assignments.
2371  */
2372 static void
2373 listsetvar(struct strlist *list_set_var, int flags)
2374 {
2375         struct strlist *lp = list_set_var;
2376
2377         if (!lp)
2378                 return;
2379         INT_OFF;
2380         do {
2381                 setvareq(lp->text, flags);
2382                 lp = lp->next;
2383         } while (lp);
2384         INT_ON;
2385 }
2386
2387 /*
2388  * Generate a list of variables satisfying the given conditions.
2389  */
2390 static char **
2391 listvars(int on, int off, char ***end)
2392 {
2393         struct var **vpp;
2394         struct var *vp;
2395         char **ep;
2396         int mask;
2397
2398         STARTSTACKSTR(ep);
2399         vpp = vartab;
2400         mask = on | off;
2401         do {
2402                 for (vp = *vpp; vp; vp = vp->next) {
2403                         if ((vp->flags & mask) == on) {
2404                                 if (ep == stackstrend())
2405                                         ep = growstackstr();
2406                                 *ep++ = (char*)vp->var_text;
2407                         }
2408                 }
2409         } while (++vpp < vartab + VTABSIZE);
2410         if (ep == stackstrend())
2411                 ep = growstackstr();
2412         if (end)
2413                 *end = ep;
2414         *ep++ = NULL;
2415         return grabstackstr(ep);
2416 }
2417
2418
2419 /* ============ Path search helper
2420  *
2421  * The variable path (passed by reference) should be set to the start
2422  * of the path before the first call; path_advance will update
2423  * this value as it proceeds.  Successive calls to path_advance will return
2424  * the possible path expansions in sequence.  If an option (indicated by
2425  * a percent sign) appears in the path entry then the global variable
2426  * pathopt will be set to point to it; otherwise pathopt will be set to
2427  * NULL.
2428  */
2429 static const char *pathopt;     /* set by path_advance */
2430
2431 static char *
2432 path_advance(const char **path, const char *name)
2433 {
2434         const char *p;
2435         char *q;
2436         const char *start;
2437         size_t len;
2438
2439         if (*path == NULL)
2440                 return NULL;
2441         start = *path;
2442         for (p = start; *p && *p != ':' && *p != '%'; p++)
2443                 continue;
2444         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2445         while (stackblocksize() < len)
2446                 growstackblock();
2447         q = stackblock();
2448         if (p != start) {
2449                 q = mempcpy(q, start, p - start);
2450                 *q++ = '/';
2451         }
2452         strcpy(q, name);
2453         pathopt = NULL;
2454         if (*p == '%') {
2455                 pathopt = ++p;
2456                 while (*p && *p != ':')
2457                         p++;
2458         }
2459         if (*p == ':')
2460                 *path = p + 1;
2461         else
2462                 *path = NULL;
2463         return stalloc(len);
2464 }
2465
2466
2467 /* ============ Prompt */
2468
2469 static smallint doprompt;                   /* if set, prompt the user */
2470 static smallint needprompt;                 /* true if interactive and at start of line */
2471
2472 #if ENABLE_FEATURE_EDITING
2473 static line_input_t *line_input_state;
2474 static const char *cmdedit_prompt;
2475 static void
2476 putprompt(const char *s)
2477 {
2478         if (ENABLE_ASH_EXPAND_PRMT) {
2479                 free((char*)cmdedit_prompt);
2480                 cmdedit_prompt = ckstrdup(s);
2481                 return;
2482         }
2483         cmdedit_prompt = s;
2484 }
2485 #else
2486 static void
2487 putprompt(const char *s)
2488 {
2489         out2str(s);
2490 }
2491 #endif
2492
2493 /* expandstr() needs parsing machinery, so it is far away ahead... */
2494 static const char *expandstr(const char *ps, int syntax_type);
2495 /* Values for syntax param */
2496 #define BASESYNTAX 0    /* not in quotes */
2497 #define DQSYNTAX   1    /* in double quotes */
2498 #define SQSYNTAX   2    /* in single quotes */
2499 #define ARISYNTAX  3    /* in arithmetic */
2500 #if ENABLE_ASH_EXPAND_PRMT
2501 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2502 #endif
2503 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2504
2505 /*
2506  * called by editline -- any expansions to the prompt should be added here.
2507  */
2508 static void
2509 setprompt_if(smallint do_set, int whichprompt)
2510 {
2511         const char *prompt;
2512         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2513
2514         if (!do_set)
2515                 return;
2516
2517         needprompt = 0;
2518
2519         switch (whichprompt) {
2520         case 1:
2521                 prompt = ps1val();
2522                 break;
2523         case 2:
2524                 prompt = ps2val();
2525                 break;
2526         default:                        /* 0 */
2527                 prompt = nullstr;
2528         }
2529 #if ENABLE_ASH_EXPAND_PRMT
2530         pushstackmark(&smark, stackblocksize());
2531         putprompt(expandstr(prompt, PSSYNTAX));
2532         popstackmark(&smark);
2533 #else
2534         putprompt(prompt);
2535 #endif
2536 }
2537
2538
2539 /* ============ The cd and pwd commands */
2540
2541 #define CD_PHYSICAL 1
2542 #define CD_PRINT 2
2543
2544 static int
2545 cdopt(void)
2546 {
2547         int flags = 0;
2548         int i, j;
2549
2550         j = 'L';
2551         while ((i = nextopt("LP")) != '\0') {
2552                 if (i != j) {
2553                         flags ^= CD_PHYSICAL;
2554                         j = i;
2555                 }
2556         }
2557
2558         return flags;
2559 }
2560
2561 /*
2562  * Update curdir (the name of the current directory) in response to a
2563  * cd command.
2564  */
2565 static const char *
2566 updatepwd(const char *dir)
2567 {
2568         char *new;
2569         char *p;
2570         char *cdcomppath;
2571         const char *lim;
2572
2573         cdcomppath = sstrdup(dir);
2574         STARTSTACKSTR(new);
2575         if (*dir != '/') {
2576                 if (curdir == nullstr)
2577                         return 0;
2578                 new = stack_putstr(curdir, new);
2579         }
2580         new = makestrspace(strlen(dir) + 2, new);
2581         lim = (char *)stackblock() + 1;
2582         if (*dir != '/') {
2583                 if (new[-1] != '/')
2584                         USTPUTC('/', new);
2585                 if (new > lim && *lim == '/')
2586                         lim++;
2587         } else {
2588                 USTPUTC('/', new);
2589                 cdcomppath++;
2590                 if (dir[1] == '/' && dir[2] != '/') {
2591                         USTPUTC('/', new);
2592                         cdcomppath++;
2593                         lim++;
2594                 }
2595         }
2596         p = strtok(cdcomppath, "/");
2597         while (p) {
2598                 switch (*p) {
2599                 case '.':
2600                         if (p[1] == '.' && p[2] == '\0') {
2601                                 while (new > lim) {
2602                                         STUNPUTC(new);
2603                                         if (new[-1] == '/')
2604                                                 break;
2605                                 }
2606                                 break;
2607                         }
2608                         if (p[1] == '\0')
2609                                 break;
2610                         /* fall through */
2611                 default:
2612                         new = stack_putstr(p, new);
2613                         USTPUTC('/', new);
2614                 }
2615                 p = strtok(NULL, "/");
2616         }
2617         if (new > lim)
2618                 STUNPUTC(new);
2619         *new = 0;
2620         return stackblock();
2621 }
2622
2623 /*
2624  * Find out what the current directory is. If we already know the current
2625  * directory, this routine returns immediately.
2626  */
2627 static char *
2628 getpwd(void)
2629 {
2630         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2631         return dir ? dir : nullstr;
2632 }
2633
2634 static void
2635 setpwd(const char *val, int setold)
2636 {
2637         char *oldcur, *dir;
2638
2639         oldcur = dir = curdir;
2640
2641         if (setold) {
2642                 setvar("OLDPWD", oldcur, VEXPORT);
2643         }
2644         INT_OFF;
2645         if (physdir != nullstr) {
2646                 if (physdir != oldcur)
2647                         free(physdir);
2648                 physdir = nullstr;
2649         }
2650         if (oldcur == val || !val) {
2651                 char *s = getpwd();
2652                 physdir = s;
2653                 if (!val)
2654                         dir = s;
2655         } else
2656                 dir = ckstrdup(val);
2657         if (oldcur != dir && oldcur != nullstr) {
2658                 free(oldcur);
2659         }
2660         curdir = dir;
2661         INT_ON;
2662         setvar("PWD", dir, VEXPORT);
2663 }
2664
2665 static void hashcd(void);
2666
2667 /*
2668  * Actually do the chdir.  We also call hashcd to let other routines
2669  * know that the current directory has changed.
2670  */
2671 static int
2672 docd(const char *dest, int flags)
2673 {
2674         const char *dir = NULL;
2675         int err;
2676
2677         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2678
2679         INT_OFF;
2680         if (!(flags & CD_PHYSICAL)) {
2681                 dir = updatepwd(dest);
2682                 if (dir)
2683                         dest = dir;
2684         }
2685         err = chdir(dest);
2686         if (err)
2687                 goto out;
2688         setpwd(dir, 1);
2689         hashcd();
2690  out:
2691         INT_ON;
2692         return err;
2693 }
2694
2695 static int FAST_FUNC
2696 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2697 {
2698         const char *dest;
2699         const char *path;
2700         const char *p;
2701         char c;
2702         struct stat statb;
2703         int flags;
2704
2705         flags = cdopt();
2706         dest = *argptr;
2707         if (!dest)
2708                 dest = bltinlookup("HOME");
2709         else if (LONE_DASH(dest)) {
2710                 dest = bltinlookup("OLDPWD");
2711                 flags |= CD_PRINT;
2712         }
2713         if (!dest)
2714                 dest = nullstr;
2715         if (*dest == '/')
2716                 goto step6;
2717         if (*dest == '.') {
2718                 c = dest[1];
2719  dotdot:
2720                 switch (c) {
2721                 case '\0':
2722                 case '/':
2723                         goto step6;
2724                 case '.':
2725                         c = dest[2];
2726                         if (c != '.')
2727                                 goto dotdot;
2728                 }
2729         }
2730         if (!*dest)
2731                 dest = ".";
2732         path = bltinlookup("CDPATH");
2733         while (path) {
2734                 c = *path;
2735                 p = path_advance(&path, dest);
2736                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2737                         if (c && c != ':')
2738                                 flags |= CD_PRINT;
2739  docd:
2740                         if (!docd(p, flags))
2741                                 goto out;
2742                         goto err;
2743                 }
2744         }
2745
2746  step6:
2747         p = dest;
2748         goto docd;
2749
2750  err:
2751         ash_msg_and_raise_error("can't cd to %s", dest);
2752         /* NOTREACHED */
2753  out:
2754         if (flags & CD_PRINT)
2755                 out1fmt("%s\n", curdir);
2756         return 0;
2757 }
2758
2759 static int FAST_FUNC
2760 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2761 {
2762         int flags;
2763         const char *dir = curdir;
2764
2765         flags = cdopt();
2766         if (flags) {
2767                 if (physdir == nullstr)
2768                         setpwd(dir, 0);
2769                 dir = physdir;
2770         }
2771         out1fmt("%s\n", dir);
2772         return 0;
2773 }
2774
2775
2776 /* ============ ... */
2777
2778
2779 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2780
2781 /* Syntax classes */
2782 #define CWORD     0             /* character is nothing special */
2783 #define CNL       1             /* newline character */
2784 #define CBACK     2             /* a backslash character */
2785 #define CSQUOTE   3             /* single quote */
2786 #define CDQUOTE   4             /* double quote */
2787 #define CENDQUOTE 5             /* a terminating quote */
2788 #define CBQUOTE   6             /* backwards single quote */
2789 #define CVAR      7             /* a dollar sign */
2790 #define CENDVAR   8             /* a '}' character */
2791 #define CLP       9             /* a left paren in arithmetic */
2792 #define CRP      10             /* a right paren in arithmetic */
2793 #define CENDFILE 11             /* end of file */
2794 #define CCTL     12             /* like CWORD, except it must be escaped */
2795 #define CSPCL    13             /* these terminate a word */
2796 #define CIGN     14             /* character should be ignored */
2797
2798 #define PEOF     256
2799 #if ENABLE_ASH_ALIAS
2800 # define PEOA    257
2801 #endif
2802
2803 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2804
2805 #if ENABLE_FEATURE_SH_MATH
2806 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2807 #else
2808 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2809 #endif
2810 static const uint16_t S_I_T[] ALIGN2 = {
2811 #if ENABLE_ASH_ALIAS
2812         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2813 #endif
2814         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2815         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2816         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2817         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2818         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2819         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2820         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2821         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2822         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2823         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2824         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2825 #if !USE_SIT_FUNCTION
2826         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2827         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2828         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2829 #endif
2830 #undef SIT_ITEM
2831 };
2832 /* Constants below must match table above */
2833 enum {
2834 #if ENABLE_ASH_ALIAS
2835         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2836 #endif
2837         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2838         CNL_CNL_CNL_CNL                    , /*  2 */
2839         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2840         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2841         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2842         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2843         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2844         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2845         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2846         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2847         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2848         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2849         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2850         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2851 };
2852
2853 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2854  * caller must ensure proper cast on it if c is *char_ptr!
2855  */
2856 #if USE_SIT_FUNCTION
2857
2858 static int
2859 SIT(int c, int syntax)
2860 {
2861         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2862         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2863         /*
2864          * This causes '/' to be prepended with CTLESC in dquoted string,
2865          * making "./file"* treated incorrectly because we feed
2866          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2867          * The "homegrown" glob implementation is okay with that,
2868          * but glibc one isn't. With '/' always treated as CWORD,
2869          * both work fine.
2870          */
2871 # if ENABLE_ASH_ALIAS
2872         static const uint8_t syntax_index_table[] ALIGN1 = {
2873                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2874                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2875                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2876                 11, 3                           /* "}~" */
2877         };
2878 # else
2879         static const uint8_t syntax_index_table[] ALIGN1 = {
2880                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2881                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2882                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2883                 10, 2                           /* "}~" */
2884         };
2885 # endif
2886         const char *s;
2887         int indx;
2888
2889         if (c == PEOF)
2890                 return CENDFILE;
2891 # if ENABLE_ASH_ALIAS
2892         if (c == PEOA)
2893                 indx = 0;
2894         else
2895 # endif
2896         {
2897                 /* Cast is purely for paranoia here,
2898                  * just in case someone passed signed char to us */
2899                 if ((unsigned char)c >= CTL_FIRST
2900                  && (unsigned char)c <= CTL_LAST
2901                 ) {
2902                         return CCTL;
2903                 }
2904                 s = strchrnul(spec_symbls, c);
2905                 if (*s == '\0')
2906                         return CWORD;
2907                 indx = syntax_index_table[s - spec_symbls];
2908         }
2909         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2910 }
2911
2912 #else   /* !USE_SIT_FUNCTION */
2913
2914 static const uint8_t syntax_index_table[] ALIGN1 = {
2915         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2916         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2923         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2924         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2925         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2926         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2927         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2946         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2947         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2948         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2949         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2950         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2951         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2953         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2955         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2956         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2957         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2958         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2961         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2962         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2963 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2964         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2978         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2979         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2980         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2981         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3009         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3010         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3011         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3014         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3016         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3039         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3040         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3041         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3042         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3043         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3044         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3045         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3046         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3047         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3048         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3049         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3050         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3051         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3052         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3053         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3054         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3173         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3174 # if ENABLE_ASH_ALIAS
3175         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3176 # endif
3177 };
3178
3179 #if 1
3180 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3181 #else /* debug version, caught one signed char bug */
3182 # define SIT(c, syntax) \
3183         ({ \
3184                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3185                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3186                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3187                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3188                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3189         })
3190 #endif
3191
3192 #endif  /* !USE_SIT_FUNCTION */
3193
3194
3195 /* ============ Alias handling */
3196
3197 #if ENABLE_ASH_ALIAS
3198
3199 #define ALIASINUSE 1
3200 #define ALIASDEAD  2
3201
3202 struct alias {
3203         struct alias *next;
3204         char *name;
3205         char *val;
3206         int flag;
3207 };
3208
3209
3210 static struct alias **atab; // [ATABSIZE];
3211 #define INIT_G_alias() do { \
3212         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3213 } while (0)
3214
3215
3216 static struct alias **
3217 __lookupalias(const char *name)
3218 {
3219         unsigned int hashval;
3220         struct alias **app;
3221         const char *p;
3222         unsigned int ch;
3223
3224         p = name;
3225
3226         ch = (unsigned char)*p;
3227         hashval = ch << 4;
3228         while (ch) {
3229                 hashval += ch;
3230                 ch = (unsigned char)*++p;
3231         }
3232         app = &atab[hashval % ATABSIZE];
3233
3234         for (; *app; app = &(*app)->next) {
3235                 if (strcmp(name, (*app)->name) == 0) {
3236                         break;
3237                 }
3238         }
3239
3240         return app;
3241 }
3242
3243 static struct alias *
3244 lookupalias(const char *name, int check)
3245 {
3246         struct alias *ap = *__lookupalias(name);
3247
3248         if (check && ap && (ap->flag & ALIASINUSE))
3249                 return NULL;
3250         return ap;
3251 }
3252
3253 static struct alias *
3254 freealias(struct alias *ap)
3255 {
3256         struct alias *next;
3257
3258         if (ap->flag & ALIASINUSE) {
3259                 ap->flag |= ALIASDEAD;
3260                 return ap;
3261         }
3262
3263         next = ap->next;
3264         free(ap->name);
3265         free(ap->val);
3266         free(ap);
3267         return next;
3268 }
3269
3270 static void
3271 setalias(const char *name, const char *val)
3272 {
3273         struct alias *ap, **app;
3274
3275         app = __lookupalias(name);
3276         ap = *app;
3277         INT_OFF;
3278         if (ap) {
3279                 if (!(ap->flag & ALIASINUSE)) {
3280                         free(ap->val);
3281                 }
3282                 ap->val = ckstrdup(val);
3283                 ap->flag &= ~ALIASDEAD;
3284         } else {
3285                 /* not found */
3286                 ap = ckzalloc(sizeof(struct alias));
3287                 ap->name = ckstrdup(name);
3288                 ap->val = ckstrdup(val);
3289                 /*ap->flag = 0; - ckzalloc did it */
3290                 /*ap->next = NULL;*/
3291                 *app = ap;
3292         }
3293         INT_ON;
3294 }
3295
3296 static int
3297 unalias(const char *name)
3298 {
3299         struct alias **app;
3300
3301         app = __lookupalias(name);
3302
3303         if (*app) {
3304                 INT_OFF;
3305                 *app = freealias(*app);
3306                 INT_ON;
3307                 return 0;
3308         }
3309
3310         return 1;
3311 }
3312
3313 static void
3314 rmaliases(void)
3315 {
3316         struct alias *ap, **app;
3317         int i;
3318
3319         INT_OFF;
3320         for (i = 0; i < ATABSIZE; i++) {
3321                 app = &atab[i];
3322                 for (ap = *app; ap; ap = *app) {
3323                         *app = freealias(*app);
3324                         if (ap == *app) {
3325                                 app = &ap->next;
3326                         }
3327                 }
3328         }
3329         INT_ON;
3330 }
3331
3332 static void
3333 printalias(const struct alias *ap)
3334 {
3335         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3336 }
3337
3338 /*
3339  * TODO - sort output
3340  */
3341 static int FAST_FUNC
3342 aliascmd(int argc UNUSED_PARAM, char **argv)
3343 {
3344         char *n, *v;
3345         int ret = 0;
3346         struct alias *ap;
3347
3348         if (!argv[1]) {
3349                 int i;
3350
3351                 for (i = 0; i < ATABSIZE; i++) {
3352                         for (ap = atab[i]; ap; ap = ap->next) {
3353                                 printalias(ap);
3354                         }
3355                 }
3356                 return 0;
3357         }
3358         while ((n = *++argv) != NULL) {
3359                 v = strchr(n+1, '=');
3360                 if (v == NULL) { /* n+1: funny ksh stuff */
3361                         ap = *__lookupalias(n);
3362                         if (ap == NULL) {
3363                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3364                                 ret = 1;
3365                         } else
3366                                 printalias(ap);
3367                 } else {
3368                         *v++ = '\0';
3369                         setalias(n, v);
3370                 }
3371         }
3372
3373         return ret;
3374 }
3375
3376 static int FAST_FUNC
3377 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3378 {
3379         int i;
3380
3381         while (nextopt("a") != '\0') {
3382                 rmaliases();
3383                 return 0;
3384         }
3385         for (i = 0; *argptr; argptr++) {
3386                 if (unalias(*argptr)) {
3387                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3388                         i = 1;
3389                 }
3390         }
3391
3392         return i;
3393 }
3394
3395 #endif /* ASH_ALIAS */
3396
3397
3398 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3399 #define FORK_FG    0
3400 #define FORK_BG    1
3401 #define FORK_NOJOB 2
3402
3403 /* mode flags for showjob(s) */
3404 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3405 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3406 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3407 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3408
3409 /*
3410  * A job structure contains information about a job.  A job is either a
3411  * single process or a set of processes contained in a pipeline.  In the
3412  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3413  * array of pids.
3414  */
3415 struct procstat {
3416         pid_t   ps_pid;         /* process id */
3417         int     ps_status;      /* last process status from wait() */
3418         char    *ps_cmd;        /* text of command being run */
3419 };
3420
3421 struct job {
3422         struct procstat ps0;    /* status of process */
3423         struct procstat *ps;    /* status or processes when more than one */
3424 #if JOBS
3425         int stopstatus;         /* status of a stopped job */
3426 #endif
3427         unsigned nprocs;        /* number of processes */
3428
3429 #define JOBRUNNING      0       /* at least one proc running */
3430 #define JOBSTOPPED      1       /* all procs are stopped */
3431 #define JOBDONE         2       /* all procs are completed */
3432         unsigned
3433                 state: 8,
3434 #if JOBS
3435                 sigint: 1,      /* job was killed by SIGINT */
3436                 jobctl: 1,      /* job running under job control */
3437 #endif
3438                 waited: 1,      /* true if this entry has been waited for */
3439                 used: 1,        /* true if this entry is in used */
3440                 changed: 1;     /* true if status has changed */
3441         struct job *prev_job;   /* previous job */
3442 };
3443
3444 static struct job *makejob(/*union node *,*/ int);
3445 static int forkshell(struct job *, union node *, int);
3446 static int waitforjob(struct job *);
3447
3448 #if !JOBS
3449 enum { doing_jobctl = 0 };
3450 #define setjobctl(on) do {} while (0)
3451 #else
3452 static smallint doing_jobctl; //references:8
3453 static void setjobctl(int);
3454 #endif
3455
3456 /*
3457  * Ignore a signal.
3458  */
3459 static void
3460 ignoresig(int signo)
3461 {
3462         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3463         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3464                 /* No, need to do it */
3465                 signal(signo, SIG_IGN);
3466         }
3467         sigmode[signo - 1] = S_HARD_IGN;
3468 }
3469
3470 /*
3471  * Only one usage site - in setsignal()
3472  */
3473 static void
3474 signal_handler(int signo)
3475 {
3476         if (signo == SIGCHLD) {
3477                 got_sigchld = 1;
3478                 if (!trap[SIGCHLD])
3479                         return;
3480         }
3481
3482         gotsig[signo - 1] = 1;
3483         pending_sig = signo;
3484
3485         if (signo == SIGINT && !trap[SIGINT]) {
3486                 if (!suppress_int) {
3487                         pending_sig = 0;
3488                         raise_interrupt(); /* does not return */
3489                 }
3490                 pending_int = 1;
3491         }
3492 }
3493
3494 /*
3495  * Set the signal handler for the specified signal.  The routine figures
3496  * out what it should be set to.
3497  */
3498 static void
3499 setsignal(int signo)
3500 {
3501         char *t;
3502         char cur_act, new_act;
3503         struct sigaction act;
3504
3505         t = trap[signo];
3506         new_act = S_DFL;
3507         if (t != NULL) { /* trap for this sig is set */
3508                 new_act = S_CATCH;
3509                 if (t[0] == '\0') /* trap is "": ignore this sig */
3510                         new_act = S_IGN;
3511         }
3512
3513         if (rootshell && new_act == S_DFL) {
3514                 switch (signo) {
3515                 case SIGINT:
3516                         if (iflag || minusc || sflag == 0)
3517                                 new_act = S_CATCH;
3518                         break;
3519                 case SIGQUIT:
3520 #if DEBUG
3521                         if (debug)
3522                                 break;
3523 #endif
3524                         /* man bash:
3525                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3526                          * commands run by bash have signal handlers
3527                          * set to the values inherited by the shell
3528                          * from its parent". */
3529                         new_act = S_IGN;
3530                         break;
3531                 case SIGTERM:
3532                         if (iflag)
3533                                 new_act = S_IGN;
3534                         break;
3535 #if JOBS
3536                 case SIGTSTP:
3537                 case SIGTTOU:
3538                         if (mflag)
3539                                 new_act = S_IGN;
3540                         break;
3541 #endif
3542                 }
3543         }
3544         /* if !rootshell, we reset SIGQUIT to DFL,
3545          * whereas we have to restore it to what shell got on entry.
3546          * This is handled by the fact that if signal was IGNored on entry,
3547          * then cur_act is S_HARD_IGN and we never change its sigaction
3548          * (see code below).
3549          */
3550
3551         if (signo == SIGCHLD)
3552                 new_act = S_CATCH;
3553
3554         t = &sigmode[signo - 1];
3555         cur_act = *t;
3556         if (cur_act == 0) {
3557                 /* current setting is not yet known */
3558                 if (sigaction(signo, NULL, &act)) {
3559                         /* pretend it worked; maybe we should give a warning,
3560                          * but other shells don't. We don't alter sigmode,
3561                          * so we retry every time.
3562                          * btw, in Linux it never fails. --vda */
3563                         return;
3564                 }
3565                 if (act.sa_handler == SIG_IGN) {
3566                         cur_act = S_HARD_IGN;
3567                         if (mflag
3568                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3569                         ) {
3570                                 cur_act = S_IGN;   /* don't hard ignore these */
3571                         }
3572                 }
3573                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3574                         /* installing SIG_DFL over SIG_DFL is a no-op */
3575                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3576                         *t = S_DFL;
3577                         return;
3578                 }
3579         }
3580         if (cur_act == S_HARD_IGN || cur_act == new_act)
3581                 return;
3582
3583         *t = new_act;
3584
3585         act.sa_handler = SIG_DFL;
3586         switch (new_act) {
3587         case S_CATCH:
3588                 act.sa_handler = signal_handler;
3589                 break;
3590         case S_IGN:
3591                 act.sa_handler = SIG_IGN;
3592                 break;
3593         }
3594         /* flags and mask matter only if !DFL and !IGN, but we do it
3595          * for all cases for more deterministic behavior:
3596          */
3597         act.sa_flags = 0; //TODO: why not SA_RESTART?
3598         sigfillset(&act.sa_mask);
3599
3600         sigaction_set(signo, &act);
3601 }
3602
3603 /* mode flags for set_curjob */
3604 #define CUR_DELETE 2
3605 #define CUR_RUNNING 1
3606 #define CUR_STOPPED 0
3607
3608 #if JOBS
3609 /* pgrp of shell on invocation */
3610 static int initialpgrp; //references:2
3611 static int ttyfd = -1; //5
3612 #endif
3613 /* array of jobs */
3614 static struct job *jobtab; //5
3615 /* size of array */
3616 static unsigned njobs; //4
3617 /* current job */
3618 static struct job *curjob; //lots
3619 /* number of presumed living untracked jobs */
3620 static int jobless; //4
3621
3622 #if 0
3623 /* Bash has a feature: it restores termios after a successful wait for
3624  * a foreground job which had at least one stopped or sigkilled member.
3625  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3626  * properly restoring tty state. Should we do this too?
3627  * A reproducer: ^Z an interactive python:
3628  *
3629  * # python
3630  * Python 2.7.12 (...)
3631  * >>> ^Z
3632  *      { python leaves tty in -icanon -echo state. We do survive that... }
3633  *  [1]+  Stopped                    python
3634  *      { ...however, next program (python #2) does not survive it well: }
3635  * # python
3636  * Python 2.7.12 (...)
3637  * >>> Traceback (most recent call last):
3638  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3639  *   File "<stdin>", line 1, in <module>
3640  * NameError: name 'qwerty' is not defined
3641  *
3642  * The implementation below is modeled on bash code and seems to work.
3643  * However, I'm not sure we should do this. For one: what if I'd fg
3644  * the stopped python instead? It'll be confused by "restored" tty state.
3645  */
3646 static struct termios shell_tty_info;
3647 static void
3648 get_tty_state(void)
3649 {
3650         if (rootshell && ttyfd >= 0)
3651                 tcgetattr(ttyfd, &shell_tty_info);
3652 }
3653 static void
3654 set_tty_state(void)
3655 {
3656         /* if (rootshell) - caller ensures this */
3657         if (ttyfd >= 0)
3658                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3659 }
3660 static int
3661 job_signal_status(struct job *jp)
3662 {
3663         int status;
3664         unsigned i;
3665         struct procstat *ps = jp->ps;
3666         for (i = 0; i < jp->nprocs; i++) {
3667                 status = ps[i].ps_status;
3668                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3669                         return status;
3670         }
3671         return 0;
3672 }
3673 static void
3674 restore_tty_if_stopped_or_signaled(struct job *jp)
3675 {
3676 //TODO: check what happens if we come from waitforjob() in expbackq()
3677         if (rootshell) {
3678                 int s = job_signal_status(jp);
3679                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3680                         set_tty_state();
3681         }
3682 }
3683 #else
3684 # define get_tty_state() ((void)0)
3685 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3686 #endif
3687
3688 static void
3689 set_curjob(struct job *jp, unsigned mode)
3690 {
3691         struct job *jp1;
3692         struct job **jpp, **curp;
3693
3694         /* first remove from list */
3695         jpp = curp = &curjob;
3696         while (1) {
3697                 jp1 = *jpp;
3698                 if (jp1 == jp)
3699                         break;
3700                 jpp = &jp1->prev_job;
3701         }
3702         *jpp = jp1->prev_job;
3703
3704         /* Then re-insert in correct position */
3705         jpp = curp;
3706         switch (mode) {
3707         default:
3708 #if DEBUG
3709                 abort();
3710 #endif
3711         case CUR_DELETE:
3712                 /* job being deleted */
3713                 break;
3714         case CUR_RUNNING:
3715                 /* newly created job or backgrounded job,
3716                  * put after all stopped jobs.
3717                  */
3718                 while (1) {
3719                         jp1 = *jpp;
3720 #if JOBS
3721                         if (!jp1 || jp1->state != JOBSTOPPED)
3722 #endif
3723                                 break;
3724                         jpp = &jp1->prev_job;
3725                 }
3726                 /* FALLTHROUGH */
3727 #if JOBS
3728         case CUR_STOPPED:
3729 #endif
3730                 /* newly stopped job - becomes curjob */
3731                 jp->prev_job = *jpp;
3732                 *jpp = jp;
3733                 break;
3734         }
3735 }
3736
3737 #if JOBS || DEBUG
3738 static int
3739 jobno(const struct job *jp)
3740 {
3741         return jp - jobtab + 1;
3742 }
3743 #endif
3744
3745 /*
3746  * Convert a job name to a job structure.
3747  */
3748 #if !JOBS
3749 #define getjob(name, getctl) getjob(name)
3750 #endif
3751 static struct job *
3752 getjob(const char *name, int getctl)
3753 {
3754         struct job *jp;
3755         struct job *found;
3756         const char *err_msg = "%s: no such job";
3757         unsigned num;
3758         int c;
3759         const char *p;
3760         char *(*match)(const char *, const char *);
3761
3762         jp = curjob;
3763         p = name;
3764         if (!p)
3765                 goto currentjob;
3766
3767         if (*p != '%')
3768                 goto err;
3769
3770         c = *++p;
3771         if (!c)
3772                 goto currentjob;
3773
3774         if (!p[1]) {
3775                 if (c == '+' || c == '%') {
3776  currentjob:
3777                         err_msg = "No current job";
3778                         goto check;
3779                 }
3780                 if (c == '-') {
3781                         if (jp)
3782                                 jp = jp->prev_job;
3783                         err_msg = "No previous job";
3784  check:
3785                         if (!jp)
3786                                 goto err;
3787                         goto gotit;
3788                 }
3789         }
3790
3791         if (is_number(p)) {
3792                 num = atoi(p);
3793                 if (num > 0 && num <= njobs) {
3794                         jp = jobtab + num - 1;
3795                         if (jp->used)
3796                                 goto gotit;
3797                         goto err;
3798                 }
3799         }
3800
3801         match = prefix;
3802         if (*p == '?') {
3803                 match = strstr;
3804                 p++;
3805         }
3806
3807         found = NULL;
3808         while (jp) {
3809                 if (match(jp->ps[0].ps_cmd, p)) {
3810                         if (found)
3811                                 goto err;
3812                         found = jp;
3813                         err_msg = "%s: ambiguous";
3814                 }
3815                 jp = jp->prev_job;
3816         }
3817         if (!found)
3818                 goto err;
3819         jp = found;
3820
3821  gotit:
3822 #if JOBS
3823         err_msg = "job %s not created under job control";
3824         if (getctl && jp->jobctl == 0)
3825                 goto err;
3826 #endif
3827         return jp;
3828  err:
3829         ash_msg_and_raise_error(err_msg, name);
3830 }
3831
3832 /*
3833  * Mark a job structure as unused.
3834  */
3835 static void
3836 freejob(struct job *jp)
3837 {
3838         struct procstat *ps;
3839         int i;
3840
3841         INT_OFF;
3842         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3843                 if (ps->ps_cmd != nullstr)
3844                         free(ps->ps_cmd);
3845         }
3846         if (jp->ps != &jp->ps0)
3847                 free(jp->ps);
3848         jp->used = 0;
3849         set_curjob(jp, CUR_DELETE);
3850         INT_ON;
3851 }
3852
3853 #if JOBS
3854 static void
3855 xtcsetpgrp(int fd, pid_t pgrp)
3856 {
3857         if (tcsetpgrp(fd, pgrp))
3858                 ash_msg_and_raise_perror("can't set tty process group");
3859 }
3860
3861 /*
3862  * Turn job control on and off.
3863  *
3864  * Note:  This code assumes that the third arg to ioctl is a character
3865  * pointer, which is true on Berkeley systems but not System V.  Since
3866  * System V doesn't have job control yet, this isn't a problem now.
3867  *
3868  * Called with interrupts off.
3869  */
3870 static void
3871 setjobctl(int on)
3872 {
3873         int fd;
3874         int pgrp;
3875
3876         if (on == doing_jobctl || rootshell == 0)
3877                 return;
3878         if (on) {
3879                 int ofd;
3880                 ofd = fd = open(_PATH_TTY, O_RDWR);
3881                 if (fd < 0) {
3882         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3883          * That sometimes helps to acquire controlling tty.
3884          * Obviously, a workaround for bugs when someone
3885          * failed to provide a controlling tty to bash! :) */
3886                         fd = 2;
3887                         while (!isatty(fd))
3888                                 if (--fd < 0)
3889                                         goto out;
3890                 }
3891                 /* fd is a tty at this point */
3892                 fd = fcntl(fd, F_DUPFD, 10);
3893                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3894                         close(ofd);
3895                 if (fd < 0)
3896                         goto out; /* F_DUPFD failed */
3897                 close_on_exec_on(fd);
3898                 while (1) { /* while we are in the background */
3899                         pgrp = tcgetpgrp(fd);
3900                         if (pgrp < 0) {
3901  out:
3902                                 ash_msg("can't access tty; job control turned off");
3903                                 mflag = on = 0;
3904                                 goto close;
3905                         }
3906                         if (pgrp == getpgrp())
3907                                 break;
3908                         killpg(0, SIGTTIN);
3909                 }
3910                 initialpgrp = pgrp;
3911
3912                 setsignal(SIGTSTP);
3913                 setsignal(SIGTTOU);
3914                 setsignal(SIGTTIN);
3915                 pgrp = rootpid;
3916                 setpgid(0, pgrp);
3917                 xtcsetpgrp(fd, pgrp);
3918         } else {
3919                 /* turning job control off */
3920                 fd = ttyfd;
3921                 pgrp = initialpgrp;
3922                 /* was xtcsetpgrp, but this can make exiting ash
3923                  * loop forever if pty is already deleted */
3924                 tcsetpgrp(fd, pgrp);
3925                 setpgid(0, pgrp);
3926                 setsignal(SIGTSTP);
3927                 setsignal(SIGTTOU);
3928                 setsignal(SIGTTIN);
3929  close:
3930                 if (fd >= 0)
3931                         close(fd);
3932                 fd = -1;
3933         }
3934         ttyfd = fd;
3935         doing_jobctl = on;
3936 }
3937
3938 static int FAST_FUNC
3939 killcmd(int argc, char **argv)
3940 {
3941         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3942                 int i = 1;
3943                 do {
3944                         if (argv[i][0] == '%') {
3945                                 /*
3946                                  * "kill %N" - job kill
3947                                  * Converting to pgrp / pid kill
3948                                  */
3949                                 struct job *jp;
3950                                 char *dst;
3951                                 int j, n;
3952
3953                                 jp = getjob(argv[i], 0);
3954                                 /*
3955                                  * In jobs started under job control, we signal
3956                                  * entire process group by kill -PGRP_ID.
3957                                  * This happens, f.e., in interactive shell.
3958                                  *
3959                                  * Otherwise, we signal each child via
3960                                  * kill PID1 PID2 PID3.
3961                                  * Testcases:
3962                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3963                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3964                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3965                                  */
3966                                 n = jp->nprocs; /* can't be 0 (I hope) */
3967                                 if (jp->jobctl)
3968                                         n = 1;
3969                                 dst = alloca(n * sizeof(int)*4);
3970                                 argv[i] = dst;
3971                                 for (j = 0; j < n; j++) {
3972                                         struct procstat *ps = &jp->ps[j];
3973                                         /* Skip non-running and not-stopped members
3974                                          * (i.e. dead members) of the job
3975                                          */
3976                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3977                                                 continue;
3978                                         /*
3979                                          * kill_main has matching code to expect
3980                                          * leading space. Needed to not confuse
3981                                          * negative pids with "kill -SIGNAL_NO" syntax
3982                                          */
3983                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3984                                 }
3985                                 *dst = '\0';
3986                         }
3987                 } while (argv[++i]);
3988         }
3989         return kill_main(argc, argv);
3990 }
3991
3992 static void
3993 showpipe(struct job *jp /*, FILE *out*/)
3994 {
3995         struct procstat *ps;
3996         struct procstat *psend;
3997
3998         psend = jp->ps + jp->nprocs;
3999         for (ps = jp->ps + 1; ps < psend; ps++)
4000                 printf(" | %s", ps->ps_cmd);
4001         newline_and_flush(stdout);
4002         flush_stdout_stderr();
4003 }
4004
4005
4006 static int
4007 restartjob(struct job *jp, int mode)
4008 {
4009         struct procstat *ps;
4010         int i;
4011         int status;
4012         pid_t pgid;
4013
4014         INT_OFF;
4015         if (jp->state == JOBDONE)
4016                 goto out;
4017         jp->state = JOBRUNNING;
4018         pgid = jp->ps[0].ps_pid;
4019         if (mode == FORK_FG) {
4020                 get_tty_state();
4021                 xtcsetpgrp(ttyfd, pgid);
4022         }
4023         killpg(pgid, SIGCONT);
4024         ps = jp->ps;
4025         i = jp->nprocs;
4026         do {
4027                 if (WIFSTOPPED(ps->ps_status)) {
4028                         ps->ps_status = -1;
4029                 }
4030                 ps++;
4031         } while (--i);
4032  out:
4033         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4034         INT_ON;
4035         return status;
4036 }
4037
4038 static int FAST_FUNC
4039 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4040 {
4041         struct job *jp;
4042         int mode;
4043         int retval;
4044
4045         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4046         nextopt(nullstr);
4047         argv = argptr;
4048         do {
4049                 jp = getjob(*argv, 1);
4050                 if (mode == FORK_BG) {
4051                         set_curjob(jp, CUR_RUNNING);
4052                         printf("[%d] ", jobno(jp));
4053                 }
4054                 out1str(jp->ps[0].ps_cmd);
4055                 showpipe(jp /*, stdout*/);
4056                 retval = restartjob(jp, mode);
4057         } while (*argv && *++argv);
4058         return retval;
4059 }
4060 #endif
4061
4062 static int
4063 sprint_status48(char *s, int status, int sigonly)
4064 {
4065         int col;
4066         int st;
4067
4068         col = 0;
4069         if (!WIFEXITED(status)) {
4070 #if JOBS
4071                 if (WIFSTOPPED(status))
4072                         st = WSTOPSIG(status);
4073                 else
4074 #endif
4075                         st = WTERMSIG(status);
4076                 if (sigonly) {
4077                         if (st == SIGINT || st == SIGPIPE)
4078                                 goto out;
4079 #if JOBS
4080                         if (WIFSTOPPED(status))
4081                                 goto out;
4082 #endif
4083                 }
4084                 st &= 0x7f;
4085 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4086                 col = fmtstr(s, 32, strsignal(st));
4087                 if (WCOREDUMP(status)) {
4088                         strcpy(s + col, " (core dumped)");
4089                         col += sizeof(" (core dumped)")-1;
4090                 }
4091         } else if (!sigonly) {
4092                 st = WEXITSTATUS(status);
4093                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4094         }
4095  out:
4096         return col;
4097 }
4098
4099 static int
4100 wait_block_or_sig(int *status)
4101 {
4102         int pid;
4103
4104         do {
4105                 sigset_t mask;
4106
4107                 /* Poll all children for changes in their state */
4108                 got_sigchld = 0;
4109                 /* if job control is active, accept stopped processes too */
4110                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4111                 if (pid != 0)
4112                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4113
4114                 /* Children exist, but none are ready. Sleep until interesting signal */
4115 #if 1
4116                 sigfillset(&mask);
4117                 sigprocmask(SIG_SETMASK, &mask, &mask);
4118                 while (!got_sigchld && !pending_sig)
4119                         sigsuspend(&mask);
4120                 sigprocmask(SIG_SETMASK, &mask, NULL);
4121 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4122                 while (!got_sigchld && !pending_sig)
4123                         pause();
4124 #endif
4125
4126                 /* If it was SIGCHLD, poll children again */
4127         } while (got_sigchld);
4128
4129         return pid;
4130 }
4131
4132 #define DOWAIT_NONBLOCK 0
4133 #define DOWAIT_BLOCK    1
4134 #define DOWAIT_BLOCK_OR_SIG 2
4135
4136 static int
4137 dowait(int block, struct job *job)
4138 {
4139         int pid;
4140         int status;
4141         struct job *jp;
4142         struct job *thisjob = NULL;
4143
4144         TRACE(("dowait(0x%x) called\n", block));
4145
4146         /* It's wrong to call waitpid() outside of INT_OFF region:
4147          * signal can arrive just after syscall return and handler can
4148          * longjmp away, losing stop/exit notification processing.
4149          * Thus, for "jobs" builtin, and for waiting for a fg job,
4150          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4151          *
4152          * However, for "wait" builtin it is wrong to simply call waitpid()
4153          * in INT_OFF region: "wait" needs to wait for any running job
4154          * to change state, but should exit on any trap too.
4155          * In INT_OFF region, a signal just before syscall entry can set
4156          * pending_sig variables, but we can't check them, and we would
4157          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4158          *
4159          * Because of this, we run inside INT_OFF, but use a special routine
4160          * which combines waitpid() and sigsuspend().
4161          * This is the reason why we need to have a handler for SIGCHLD:
4162          * SIG_DFL handler does not wake sigsuspend().
4163          */
4164         INT_OFF;
4165         if (block == DOWAIT_BLOCK_OR_SIG) {
4166                 pid = wait_block_or_sig(&status);
4167         } else {
4168                 int wait_flags = 0;
4169                 if (block == DOWAIT_NONBLOCK)
4170                         wait_flags = WNOHANG;
4171                 /* if job control is active, accept stopped processes too */
4172                 if (doing_jobctl)
4173                         wait_flags |= WUNTRACED;
4174                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4175                 pid = waitpid(-1, &status, wait_flags);
4176         }
4177         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4178                                 pid, status, errno, strerror(errno)));
4179         if (pid <= 0)
4180                 goto out;
4181
4182         thisjob = NULL;
4183         for (jp = curjob; jp; jp = jp->prev_job) {
4184                 int jobstate;
4185                 struct procstat *ps;
4186                 struct procstat *psend;
4187                 if (jp->state == JOBDONE)
4188                         continue;
4189                 jobstate = JOBDONE;
4190                 ps = jp->ps;
4191                 psend = ps + jp->nprocs;
4192                 do {
4193                         if (ps->ps_pid == pid) {
4194                                 TRACE(("Job %d: changing status of proc %d "
4195                                         "from 0x%x to 0x%x\n",
4196                                         jobno(jp), pid, ps->ps_status, status));
4197                                 ps->ps_status = status;
4198                                 thisjob = jp;
4199                         }
4200                         if (ps->ps_status == -1)
4201                                 jobstate = JOBRUNNING;
4202 #if JOBS
4203                         if (jobstate == JOBRUNNING)
4204                                 continue;
4205                         if (WIFSTOPPED(ps->ps_status)) {
4206                                 jp->stopstatus = ps->ps_status;
4207                                 jobstate = JOBSTOPPED;
4208                         }
4209 #endif
4210                 } while (++ps < psend);
4211                 if (!thisjob)
4212                         continue;
4213
4214                 /* Found the job where one of its processes changed its state.
4215                  * Is there at least one live and running process in this job? */
4216                 if (jobstate != JOBRUNNING) {
4217                         /* No. All live processes in the job are stopped
4218                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4219                          */
4220                         thisjob->changed = 1;
4221                         if (thisjob->state != jobstate) {
4222                                 TRACE(("Job %d: changing state from %d to %d\n",
4223                                         jobno(thisjob), thisjob->state, jobstate));
4224                                 thisjob->state = jobstate;
4225 #if JOBS
4226                                 if (jobstate == JOBSTOPPED)
4227                                         set_curjob(thisjob, CUR_STOPPED);
4228 #endif
4229                         }
4230                 }
4231                 goto out;
4232         }
4233         /* The process wasn't found in job list */
4234 #if JOBS
4235         if (!WIFSTOPPED(status))
4236                 jobless--;
4237 #endif
4238  out:
4239         INT_ON;
4240
4241         if (thisjob && thisjob == job) {
4242                 char s[48 + 1];
4243                 int len;
4244
4245                 len = sprint_status48(s, status, 1);
4246                 if (len) {
4247                         s[len] = '\n';
4248                         s[len + 1] = '\0';
4249                         out2str(s);
4250                 }
4251         }
4252         return pid;
4253 }
4254
4255 #if JOBS
4256 static void
4257 showjob(struct job *jp, int mode)
4258 {
4259         struct procstat *ps;
4260         struct procstat *psend;
4261         int col;
4262         int indent_col;
4263         char s[16 + 16 + 48];
4264         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4265
4266         ps = jp->ps;
4267
4268         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4269                 /* just output process (group) id of pipeline */
4270                 fprintf(out, "%d\n", ps->ps_pid);
4271                 return;
4272         }
4273
4274         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4275         indent_col = col;
4276
4277         if (jp == curjob)
4278                 s[col - 3] = '+';
4279         else if (curjob && jp == curjob->prev_job)
4280                 s[col - 3] = '-';
4281
4282         if (mode & SHOW_PIDS)
4283                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4284
4285         psend = ps + jp->nprocs;
4286
4287         if (jp->state == JOBRUNNING) {
4288                 strcpy(s + col, "Running");
4289                 col += sizeof("Running") - 1;
4290         } else {
4291                 int status = psend[-1].ps_status;
4292                 if (jp->state == JOBSTOPPED)
4293                         status = jp->stopstatus;
4294                 col += sprint_status48(s + col, status, 0);
4295         }
4296         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4297
4298         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4299          * or prints several "PID             | <cmdN>" lines,
4300          * depending on SHOW_PIDS bit.
4301          * We do not print status of individual processes
4302          * between PID and <cmdN>. bash does it, but not very well:
4303          * first line shows overall job status, not process status,
4304          * making it impossible to know 1st process status.
4305          */
4306         goto start;
4307         do {
4308                 /* for each process */
4309                 s[0] = '\0';
4310                 col = 33;
4311                 if (mode & SHOW_PIDS)
4312                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4313  start:
4314                 fprintf(out, "%s%*c%s%s",
4315                                 s,
4316                                 33 - col >= 0 ? 33 - col : 0, ' ',
4317                                 ps == jp->ps ? "" : "| ",
4318                                 ps->ps_cmd
4319                 );
4320         } while (++ps != psend);
4321         newline_and_flush(out);
4322
4323         jp->changed = 0;
4324
4325         if (jp->state == JOBDONE) {
4326                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4327                 freejob(jp);
4328         }
4329 }
4330
4331 /*
4332  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4333  * statuses have changed since the last call to showjobs.
4334  */
4335 static void
4336 showjobs(int mode)
4337 {
4338         struct job *jp;
4339
4340         TRACE(("showjobs(0x%x) called\n", mode));
4341
4342         /* Handle all finished jobs */
4343         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4344                 continue;
4345
4346         for (jp = curjob; jp; jp = jp->prev_job) {
4347                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4348                         showjob(jp, mode);
4349                 }
4350         }
4351 }
4352
4353 static int FAST_FUNC
4354 jobscmd(int argc UNUSED_PARAM, char **argv)
4355 {
4356         int mode, m;
4357
4358         mode = 0;
4359         while ((m = nextopt("lp")) != '\0') {
4360                 if (m == 'l')
4361                         mode |= SHOW_PIDS;
4362                 else
4363                         mode |= SHOW_ONLY_PGID;
4364         }
4365
4366         argv = argptr;
4367         if (*argv) {
4368                 do
4369                         showjob(getjob(*argv, 0), mode);
4370                 while (*++argv);
4371         } else {
4372                 showjobs(mode);
4373         }
4374
4375         return 0;
4376 }
4377 #endif /* JOBS */
4378
4379 /* Called only on finished or stopped jobs (no members are running) */
4380 static int
4381 getstatus(struct job *job)
4382 {
4383         int status;
4384         int retval;
4385         struct procstat *ps;
4386
4387         /* Fetch last member's status */
4388         ps = job->ps + job->nprocs - 1;
4389         status = ps->ps_status;
4390         if (pipefail) {
4391                 /* "set -o pipefail" mode: use last _nonzero_ status */
4392                 while (status == 0 && --ps >= job->ps)
4393                         status = ps->ps_status;
4394         }
4395
4396         retval = WEXITSTATUS(status);
4397         if (!WIFEXITED(status)) {
4398 #if JOBS
4399                 retval = WSTOPSIG(status);
4400                 if (!WIFSTOPPED(status))
4401 #endif
4402                 {
4403                         /* XXX: limits number of signals */
4404                         retval = WTERMSIG(status);
4405 #if JOBS
4406                         if (retval == SIGINT)
4407                                 job->sigint = 1;
4408 #endif
4409                 }
4410                 retval += 128;
4411         }
4412         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4413                 jobno(job), job->nprocs, status, retval));
4414         return retval;
4415 }
4416
4417 static int FAST_FUNC
4418 waitcmd(int argc UNUSED_PARAM, char **argv)
4419 {
4420         struct job *job;
4421         int retval;
4422         struct job *jp;
4423
4424         nextopt(nullstr);
4425         retval = 0;
4426
4427         argv = argptr;
4428         if (!*argv) {
4429                 /* wait for all jobs */
4430                 for (;;) {
4431                         jp = curjob;
4432                         while (1) {
4433                                 if (!jp) /* no running procs */
4434                                         goto ret;
4435                                 if (jp->state == JOBRUNNING)
4436                                         break;
4437                                 jp->waited = 1;
4438                                 jp = jp->prev_job;
4439                         }
4440         /* man bash:
4441          * "When bash is waiting for an asynchronous command via
4442          * the wait builtin, the reception of a signal for which a trap
4443          * has been set will cause the wait builtin to return immediately
4444          * with an exit status greater than 128, immediately after which
4445          * the trap is executed."
4446          */
4447                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4448         /* if child sends us a signal *and immediately exits*,
4449          * dowait() returns pid > 0. Check this case,
4450          * not "if (dowait() < 0)"!
4451          */
4452                         if (pending_sig)
4453                                 goto sigout;
4454                 }
4455         }
4456
4457         retval = 127;
4458         do {
4459                 if (**argv != '%') {
4460                         pid_t pid = number(*argv);
4461                         job = curjob;
4462                         while (1) {
4463                                 if (!job)
4464                                         goto repeat;
4465                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4466                                         break;
4467                                 job = job->prev_job;
4468                         }
4469                 } else {
4470                         job = getjob(*argv, 0);
4471                 }
4472                 /* loop until process terminated or stopped */
4473                 while (job->state == JOBRUNNING) {
4474                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4475                         if (pending_sig)
4476                                 goto sigout;
4477                 }
4478                 job->waited = 1;
4479                 retval = getstatus(job);
4480  repeat: ;
4481         } while (*++argv);
4482
4483  ret:
4484         return retval;
4485  sigout:
4486         retval = 128 + pending_sig;
4487         return retval;
4488 }
4489
4490 static struct job *
4491 growjobtab(void)
4492 {
4493         size_t len;
4494         ptrdiff_t offset;
4495         struct job *jp, *jq;
4496
4497         len = njobs * sizeof(*jp);
4498         jq = jobtab;
4499         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4500
4501         offset = (char *)jp - (char *)jq;
4502         if (offset) {
4503                 /* Relocate pointers */
4504                 size_t l = len;
4505
4506                 jq = (struct job *)((char *)jq + l);
4507                 while (l) {
4508                         l -= sizeof(*jp);
4509                         jq--;
4510 #define joff(p) ((struct job *)((char *)(p) + l))
4511 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4512                         if (joff(jp)->ps == &jq->ps0)
4513                                 jmove(joff(jp)->ps);
4514                         if (joff(jp)->prev_job)
4515                                 jmove(joff(jp)->prev_job);
4516                 }
4517                 if (curjob)
4518                         jmove(curjob);
4519 #undef joff
4520 #undef jmove
4521         }
4522
4523         njobs += 4;
4524         jobtab = jp;
4525         jp = (struct job *)((char *)jp + len);
4526         jq = jp + 3;
4527         do {
4528                 jq->used = 0;
4529         } while (--jq >= jp);
4530         return jp;
4531 }
4532
4533 /*
4534  * Return a new job structure.
4535  * Called with interrupts off.
4536  */
4537 static struct job *
4538 makejob(/*union node *node,*/ int nprocs)
4539 {
4540         int i;
4541         struct job *jp;
4542
4543         for (i = njobs, jp = jobtab; ; jp++) {
4544                 if (--i < 0) {
4545                         jp = growjobtab();
4546                         break;
4547                 }
4548                 if (jp->used == 0)
4549                         break;
4550                 if (jp->state != JOBDONE || !jp->waited)
4551                         continue;
4552 #if JOBS
4553                 if (doing_jobctl)
4554                         continue;
4555 #endif
4556                 freejob(jp);
4557                 break;
4558         }
4559         memset(jp, 0, sizeof(*jp));
4560 #if JOBS
4561         /* jp->jobctl is a bitfield.
4562          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4563         if (doing_jobctl)
4564                 jp->jobctl = 1;
4565 #endif
4566         jp->prev_job = curjob;
4567         curjob = jp;
4568         jp->used = 1;
4569         jp->ps = &jp->ps0;
4570         if (nprocs > 1) {
4571                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4572         }
4573         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4574                                 jobno(jp)));
4575         return jp;
4576 }
4577
4578 #if JOBS
4579 /*
4580  * Return a string identifying a command (to be printed by the
4581  * jobs command).
4582  */
4583 static char *cmdnextc;
4584
4585 static void
4586 cmdputs(const char *s)
4587 {
4588         static const char vstype[VSTYPE + 1][3] = {
4589                 "", "}", "-", "+", "?", "=",
4590                 "%", "%%", "#", "##"
4591                 IF_BASH_SUBSTR(, ":")
4592                 IF_BASH_PATTERN_SUBST(, "/", "//")
4593         };
4594
4595         const char *p, *str;
4596         char cc[2];
4597         char *nextc;
4598         unsigned char c;
4599         unsigned char subtype = 0;
4600         int quoted = 0;
4601
4602         cc[1] = '\0';
4603         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4604         p = s;
4605         while ((c = *p++) != '\0') {
4606                 str = NULL;
4607                 switch (c) {
4608                 case CTLESC:
4609                         c = *p++;
4610                         break;
4611                 case CTLVAR:
4612                         subtype = *p++;
4613                         if ((subtype & VSTYPE) == VSLENGTH)
4614                                 str = "${#";
4615                         else
4616                                 str = "${";
4617                         goto dostr;
4618                 case CTLENDVAR:
4619                         str = "\"}" + !(quoted & 1);
4620                         quoted >>= 1;
4621                         subtype = 0;
4622                         goto dostr;
4623                 case CTLBACKQ:
4624                         str = "$(...)";
4625                         goto dostr;
4626 #if ENABLE_FEATURE_SH_MATH
4627                 case CTLARI:
4628                         str = "$((";
4629                         goto dostr;
4630                 case CTLENDARI:
4631                         str = "))";
4632                         goto dostr;
4633 #endif
4634                 case CTLQUOTEMARK:
4635                         quoted ^= 1;
4636                         c = '"';
4637                         break;
4638                 case '=':
4639                         if (subtype == 0)
4640                                 break;
4641                         if ((subtype & VSTYPE) != VSNORMAL)
4642                                 quoted <<= 1;
4643                         str = vstype[subtype & VSTYPE];
4644                         if (subtype & VSNUL)
4645                                 c = ':';
4646                         else
4647                                 goto checkstr;
4648                         break;
4649                 case '\'':
4650                 case '\\':
4651                 case '"':
4652                 case '$':
4653                         /* These can only happen inside quotes */
4654                         cc[0] = c;
4655                         str = cc;
4656 //FIXME:
4657 // $ true $$ &
4658 // $ <cr>
4659 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4660                         c = '\\';
4661                         break;
4662                 default:
4663                         break;
4664                 }
4665                 USTPUTC(c, nextc);
4666  checkstr:
4667                 if (!str)
4668                         continue;
4669  dostr:
4670                 while ((c = *str++) != '\0') {
4671                         USTPUTC(c, nextc);
4672                 }
4673         } /* while *p++ not NUL */
4674
4675         if (quoted & 1) {
4676                 USTPUTC('"', nextc);
4677         }
4678         *nextc = 0;
4679         cmdnextc = nextc;
4680 }
4681
4682 /* cmdtxt() and cmdlist() call each other */
4683 static void cmdtxt(union node *n);
4684
4685 static void
4686 cmdlist(union node *np, int sep)
4687 {
4688         for (; np; np = np->narg.next) {
4689                 if (!sep)
4690                         cmdputs(" ");
4691                 cmdtxt(np);
4692                 if (sep && np->narg.next)
4693                         cmdputs(" ");
4694         }
4695 }
4696
4697 static void
4698 cmdtxt(union node *n)
4699 {
4700         union node *np;
4701         struct nodelist *lp;
4702         const char *p;
4703
4704         if (!n)
4705                 return;
4706         switch (n->type) {
4707         default:
4708 #if DEBUG
4709                 abort();
4710 #endif
4711         case NPIPE:
4712                 lp = n->npipe.cmdlist;
4713                 for (;;) {
4714                         cmdtxt(lp->n);
4715                         lp = lp->next;
4716                         if (!lp)
4717                                 break;
4718                         cmdputs(" | ");
4719                 }
4720                 break;
4721         case NSEMI:
4722                 p = "; ";
4723                 goto binop;
4724         case NAND:
4725                 p = " && ";
4726                 goto binop;
4727         case NOR:
4728                 p = " || ";
4729  binop:
4730                 cmdtxt(n->nbinary.ch1);
4731                 cmdputs(p);
4732                 n = n->nbinary.ch2;
4733                 goto donode;
4734         case NREDIR:
4735         case NBACKGND:
4736                 n = n->nredir.n;
4737                 goto donode;
4738         case NNOT:
4739                 cmdputs("!");
4740                 n = n->nnot.com;
4741  donode:
4742                 cmdtxt(n);
4743                 break;
4744         case NIF:
4745                 cmdputs("if ");
4746                 cmdtxt(n->nif.test);
4747                 cmdputs("; then ");
4748                 if (n->nif.elsepart) {
4749                         cmdtxt(n->nif.ifpart);
4750                         cmdputs("; else ");
4751                         n = n->nif.elsepart;
4752                 } else {
4753                         n = n->nif.ifpart;
4754                 }
4755                 p = "; fi";
4756                 goto dotail;
4757         case NSUBSHELL:
4758                 cmdputs("(");
4759                 n = n->nredir.n;
4760                 p = ")";
4761                 goto dotail;
4762         case NWHILE:
4763                 p = "while ";
4764                 goto until;
4765         case NUNTIL:
4766                 p = "until ";
4767  until:
4768                 cmdputs(p);
4769                 cmdtxt(n->nbinary.ch1);
4770                 n = n->nbinary.ch2;
4771                 p = "; done";
4772  dodo:
4773                 cmdputs("; do ");
4774  dotail:
4775                 cmdtxt(n);
4776                 goto dotail2;
4777         case NFOR:
4778                 cmdputs("for ");
4779                 cmdputs(n->nfor.var);
4780                 cmdputs(" in ");
4781                 cmdlist(n->nfor.args, 1);
4782                 n = n->nfor.body;
4783                 p = "; done";
4784                 goto dodo;
4785         case NDEFUN:
4786                 cmdputs(n->narg.text);
4787                 p = "() { ... }";
4788                 goto dotail2;
4789         case NCMD:
4790                 cmdlist(n->ncmd.args, 1);
4791                 cmdlist(n->ncmd.redirect, 0);
4792                 break;
4793         case NARG:
4794                 p = n->narg.text;
4795  dotail2:
4796                 cmdputs(p);
4797                 break;
4798         case NHERE:
4799         case NXHERE:
4800                 p = "<<...";
4801                 goto dotail2;
4802         case NCASE:
4803                 cmdputs("case ");
4804                 cmdputs(n->ncase.expr->narg.text);
4805                 cmdputs(" in ");
4806                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4807                         cmdtxt(np->nclist.pattern);
4808                         cmdputs(") ");
4809                         cmdtxt(np->nclist.body);
4810                         cmdputs(";; ");
4811                 }
4812                 p = "esac";
4813                 goto dotail2;
4814         case NTO:
4815                 p = ">";
4816                 goto redir;
4817         case NCLOBBER:
4818                 p = ">|";
4819                 goto redir;
4820         case NAPPEND:
4821                 p = ">>";
4822                 goto redir;
4823 #if BASH_REDIR_OUTPUT
4824         case NTO2:
4825 #endif
4826         case NTOFD:
4827                 p = ">&";
4828                 goto redir;
4829         case NFROM:
4830                 p = "<";
4831                 goto redir;
4832         case NFROMFD:
4833                 p = "<&";
4834                 goto redir;
4835         case NFROMTO:
4836                 p = "<>";
4837  redir:
4838                 cmdputs(utoa(n->nfile.fd));
4839                 cmdputs(p);
4840                 if (n->type == NTOFD || n->type == NFROMFD) {
4841                         if (n->ndup.dupfd >= 0)
4842                                 cmdputs(utoa(n->ndup.dupfd));
4843                         else
4844                                 cmdputs("-");
4845                         break;
4846                 }
4847                 n = n->nfile.fname;
4848                 goto donode;
4849         }
4850 }
4851
4852 static char *
4853 commandtext(union node *n)
4854 {
4855         char *name;
4856
4857         STARTSTACKSTR(cmdnextc);
4858         cmdtxt(n);
4859         name = stackblock();
4860         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4861         return ckstrdup(name);
4862 }
4863 #endif /* JOBS */
4864
4865 /*
4866  * Fork off a subshell.  If we are doing job control, give the subshell its
4867  * own process group.  Jp is a job structure that the job is to be added to.
4868  * N is the command that will be evaluated by the child.  Both jp and n may
4869  * be NULL.  The mode parameter can be one of the following:
4870  *      FORK_FG - Fork off a foreground process.
4871  *      FORK_BG - Fork off a background process.
4872  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4873  *                   process group even if job control is on.
4874  *
4875  * When job control is turned off, background processes have their standard
4876  * input redirected to /dev/null (except for the second and later processes
4877  * in a pipeline).
4878  *
4879  * Called with interrupts off.
4880  */
4881 /*
4882  * Clear traps on a fork.
4883  */
4884 static void
4885 clear_traps(void)
4886 {
4887         char **tp;
4888
4889         INT_OFF;
4890         for (tp = trap; tp < &trap[NSIG]; tp++) {
4891                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4892                         if (trap_ptr == trap)
4893                                 free(*tp);
4894                         /* else: it "belongs" to trap_ptr vector, don't free */
4895                         *tp = NULL;
4896                         if ((tp - trap) != 0)
4897                                 setsignal(tp - trap);
4898                 }
4899         }
4900         may_have_traps = 0;
4901         INT_ON;
4902 }
4903
4904 /* Lives far away from here, needed for forkchild */
4905 static void closescript(void);
4906
4907 /* Called after fork(), in child */
4908 /* jp and n are NULL when called by openhere() for heredoc support */
4909 static NOINLINE void
4910 forkchild(struct job *jp, union node *n, int mode)
4911 {
4912         int oldlvl;
4913
4914         TRACE(("Child shell %d\n", getpid()));
4915         oldlvl = shlvl;
4916         shlvl++;
4917
4918         /* man bash: "Non-builtin commands run by bash have signal handlers
4919          * set to the values inherited by the shell from its parent".
4920          * Do we do it correctly? */
4921
4922         closescript();
4923
4924         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4925          && n && n->type == NCMD        /* is it single cmd? */
4926         /* && n->ncmd.args->type == NARG - always true? */
4927          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4928          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4929         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4930         ) {
4931                 TRACE(("Trap hack\n"));
4932                 /* Awful hack for `trap` or $(trap).
4933                  *
4934                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4935                  * contains an example where "trap" is executed in a subshell:
4936                  *
4937                  * save_traps=$(trap)
4938                  * ...
4939                  * eval "$save_traps"
4940                  *
4941                  * Standard does not say that "trap" in subshell shall print
4942                  * parent shell's traps. It only says that its output
4943                  * must have suitable form, but then, in the above example
4944                  * (which is not supposed to be normative), it implies that.
4945                  *
4946                  * bash (and probably other shell) does implement it
4947                  * (traps are reset to defaults, but "trap" still shows them),
4948                  * but as a result, "trap" logic is hopelessly messed up:
4949                  *
4950                  * # trap
4951                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4952                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4953                  * # true | trap   <--- trap is in subshell - no output (ditto)
4954                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4955                  * trap -- 'echo Ho' SIGWINCH
4956                  * # echo `(trap)`         <--- in subshell in subshell - output
4957                  * trap -- 'echo Ho' SIGWINCH
4958                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4959                  * trap -- 'echo Ho' SIGWINCH
4960                  *
4961                  * The rules when to forget and when to not forget traps
4962                  * get really complex and nonsensical.
4963                  *
4964                  * Our solution: ONLY bare $(trap) or `trap` is special.
4965                  */
4966                 /* Save trap handler strings for trap builtin to print */
4967                 trap_ptr = xmemdup(trap, sizeof(trap));
4968                 /* Fall through into clearing traps */
4969         }
4970         clear_traps();
4971 #if JOBS
4972         /* do job control only in root shell */
4973         doing_jobctl = 0;
4974         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4975                 pid_t pgrp;
4976
4977                 if (jp->nprocs == 0)
4978                         pgrp = getpid();
4979                 else
4980                         pgrp = jp->ps[0].ps_pid;
4981                 /* this can fail because we are doing it in the parent also */
4982                 setpgid(0, pgrp);
4983                 if (mode == FORK_FG)
4984                         xtcsetpgrp(ttyfd, pgrp);
4985                 setsignal(SIGTSTP);
4986                 setsignal(SIGTTOU);
4987         } else
4988 #endif
4989         if (mode == FORK_BG) {
4990                 /* man bash: "When job control is not in effect,
4991                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4992                 ignoresig(SIGINT);
4993                 ignoresig(SIGQUIT);
4994                 if (jp->nprocs == 0) {
4995                         close(0);
4996                         if (open(bb_dev_null, O_RDONLY) != 0)
4997                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4998                 }
4999         }
5000         if (oldlvl == 0) {
5001                 if (iflag) { /* why if iflag only? */
5002                         setsignal(SIGINT);
5003                         setsignal(SIGTERM);
5004                 }
5005                 /* man bash:
5006                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5007                  * commands run by bash have signal handlers
5008                  * set to the values inherited by the shell
5009                  * from its parent".
5010                  * Take care of the second rule: */
5011                 setsignal(SIGQUIT);
5012         }
5013 #if JOBS
5014         if (n && n->type == NCMD
5015          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5016         ) {
5017                 TRACE(("Job hack\n"));
5018                 /* "jobs": we do not want to clear job list for it,
5019                  * instead we remove only _its_ own_ job from job list.
5020                  * This makes "jobs .... | cat" more useful.
5021                  */
5022                 freejob(curjob);
5023                 return;
5024         }
5025 #endif
5026         for (jp = curjob; jp; jp = jp->prev_job)
5027                 freejob(jp);
5028         jobless = 0;
5029 }
5030
5031 /* Called after fork(), in parent */
5032 #if !JOBS
5033 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5034 #endif
5035 static void
5036 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5037 {
5038         TRACE(("In parent shell: child = %d\n", pid));
5039         if (!jp) {
5040                 /* jp is NULL when called by openhere() for heredoc support */
5041                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5042                         continue;
5043                 jobless++;
5044                 return;
5045         }
5046 #if JOBS
5047         if (mode != FORK_NOJOB && jp->jobctl) {
5048                 int pgrp;
5049
5050                 if (jp->nprocs == 0)
5051                         pgrp = pid;
5052                 else
5053                         pgrp = jp->ps[0].ps_pid;
5054                 /* This can fail because we are doing it in the child also */
5055                 setpgid(pid, pgrp);
5056         }
5057 #endif
5058         if (mode == FORK_BG) {
5059                 backgndpid = pid;               /* set $! */
5060                 set_curjob(jp, CUR_RUNNING);
5061         }
5062         if (jp) {
5063                 struct procstat *ps = &jp->ps[jp->nprocs++];
5064                 ps->ps_pid = pid;
5065                 ps->ps_status = -1;
5066                 ps->ps_cmd = nullstr;
5067 #if JOBS
5068                 if (doing_jobctl && n)
5069                         ps->ps_cmd = commandtext(n);
5070 #endif
5071         }
5072 }
5073
5074 /* jp and n are NULL when called by openhere() for heredoc support */
5075 static int
5076 forkshell(struct job *jp, union node *n, int mode)
5077 {
5078         int pid;
5079
5080         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5081         pid = fork();
5082         if (pid < 0) {
5083                 TRACE(("Fork failed, errno=%d", errno));
5084                 if (jp)
5085                         freejob(jp);
5086                 ash_msg_and_raise_error("can't fork");
5087         }
5088         if (pid == 0) {
5089                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5090                 forkchild(jp, n, mode);
5091         } else {
5092                 forkparent(jp, n, mode, pid);
5093         }
5094         return pid;
5095 }
5096
5097 /*
5098  * Wait for job to finish.
5099  *
5100  * Under job control we have the problem that while a child process
5101  * is running interrupts generated by the user are sent to the child
5102  * but not to the shell.  This means that an infinite loop started by
5103  * an interactive user may be hard to kill.  With job control turned off,
5104  * an interactive user may place an interactive program inside a loop.
5105  * If the interactive program catches interrupts, the user doesn't want
5106  * these interrupts to also abort the loop.  The approach we take here
5107  * is to have the shell ignore interrupt signals while waiting for a
5108  * foreground process to terminate, and then send itself an interrupt
5109  * signal if the child process was terminated by an interrupt signal.
5110  * Unfortunately, some programs want to do a bit of cleanup and then
5111  * exit on interrupt; unless these processes terminate themselves by
5112  * sending a signal to themselves (instead of calling exit) they will
5113  * confuse this approach.
5114  *
5115  * Called with interrupts off.
5116  */
5117 static int
5118 waitforjob(struct job *jp)
5119 {
5120         int st;
5121
5122         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5123
5124         INT_OFF;
5125         while (jp->state == JOBRUNNING) {
5126                 /* In non-interactive shells, we _can_ get
5127                  * a keyboard signal here and be EINTRed,
5128                  * but we just loop back, waiting for command to complete.
5129                  *
5130                  * man bash:
5131                  * "If bash is waiting for a command to complete and receives
5132                  * a signal for which a trap has been set, the trap
5133                  * will not be executed until the command completes."
5134                  *
5135                  * Reality is that even if trap is not set, bash
5136                  * will not act on the signal until command completes.
5137                  * Try this. sleep5intoff.c:
5138                  * #include <signal.h>
5139                  * #include <unistd.h>
5140                  * int main() {
5141                  *         sigset_t set;
5142                  *         sigemptyset(&set);
5143                  *         sigaddset(&set, SIGINT);
5144                  *         sigaddset(&set, SIGQUIT);
5145                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5146                  *         sleep(5);
5147                  *         return 0;
5148                  * }
5149                  * $ bash -c './sleep5intoff; echo hi'
5150                  * ^C^C^C^C <--- pressing ^C once a second
5151                  * $ _
5152                  * $ bash -c './sleep5intoff; echo hi'
5153                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5154                  * $ _
5155                  */
5156                 dowait(DOWAIT_BLOCK, jp);
5157         }
5158         INT_ON;
5159
5160         st = getstatus(jp);
5161 #if JOBS
5162         if (jp->jobctl) {
5163                 xtcsetpgrp(ttyfd, rootpid);
5164                 restore_tty_if_stopped_or_signaled(jp);
5165
5166                 /*
5167                  * This is truly gross.
5168                  * If we're doing job control, then we did a TIOCSPGRP which
5169                  * caused us (the shell) to no longer be in the controlling
5170                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5171                  * intuit from the subprocess exit status whether a SIGINT
5172                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5173                  */
5174                 if (jp->sigint) /* TODO: do the same with all signals */
5175                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5176         }
5177         if (jp->state == JOBDONE)
5178 #endif
5179                 freejob(jp);
5180         return st;
5181 }
5182
5183 /*
5184  * return 1 if there are stopped jobs, otherwise 0
5185  */
5186 static int
5187 stoppedjobs(void)
5188 {
5189         struct job *jp;
5190         int retval;
5191
5192         retval = 0;
5193         if (job_warning)
5194                 goto out;
5195         jp = curjob;
5196         if (jp && jp->state == JOBSTOPPED) {
5197                 out2str("You have stopped jobs.\n");
5198                 job_warning = 2;
5199                 retval++;
5200         }
5201  out:
5202         return retval;
5203 }
5204
5205
5206 /*
5207  * Code for dealing with input/output redirection.
5208  */
5209
5210 #undef EMPTY
5211 #undef CLOSED
5212 #define EMPTY -2                /* marks an unused slot in redirtab */
5213 #define CLOSED -1               /* marks a slot of previously-closed fd */
5214
5215 /*
5216  * Handle here documents.  Normally we fork off a process to write the
5217  * data to a pipe.  If the document is short, we can stuff the data in
5218  * the pipe without forking.
5219  */
5220 /* openhere needs this forward reference */
5221 static void expandhere(union node *arg, int fd);
5222 static int
5223 openhere(union node *redir)
5224 {
5225         int pip[2];
5226         size_t len = 0;
5227
5228         if (pipe(pip) < 0)
5229                 ash_msg_and_raise_error("pipe call failed");
5230         if (redir->type == NHERE) {
5231                 len = strlen(redir->nhere.doc->narg.text);
5232                 if (len <= PIPE_BUF) {
5233                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5234                         goto out;
5235                 }
5236         }
5237         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5238                 /* child */
5239                 close(pip[0]);
5240                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5241                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5242                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5243                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5244                 signal(SIGPIPE, SIG_DFL);
5245                 if (redir->type == NHERE)
5246                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5247                 else /* NXHERE */
5248                         expandhere(redir->nhere.doc, pip[1]);
5249                 _exit(EXIT_SUCCESS);
5250         }
5251  out:
5252         close(pip[1]);
5253         return pip[0];
5254 }
5255
5256 static int
5257 openredirect(union node *redir)
5258 {
5259         struct stat sb;
5260         char *fname;
5261         int f;
5262
5263         switch (redir->nfile.type) {
5264 /* Can't happen, our single caller does this itself */
5265 //      case NTOFD:
5266 //      case NFROMFD:
5267 //              return -1;
5268         case NHERE:
5269         case NXHERE:
5270                 return openhere(redir);
5271         }
5272
5273         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5274          * allocated space. Do it only when we know it is safe.
5275          */
5276         fname = redir->nfile.expfname;
5277
5278         switch (redir->nfile.type) {
5279         default:
5280 #if DEBUG
5281                 abort();
5282 #endif
5283         case NFROM:
5284                 f = open(fname, O_RDONLY);
5285                 if (f < 0)
5286                         goto eopen;
5287                 break;
5288         case NFROMTO:
5289                 f = open(fname, O_RDWR|O_CREAT, 0666);
5290                 if (f < 0)
5291                         goto ecreate;
5292                 break;
5293         case NTO:
5294 #if BASH_REDIR_OUTPUT
5295         case NTO2:
5296 #endif
5297                 /* Take care of noclobber mode. */
5298                 if (Cflag) {
5299                         if (stat(fname, &sb) < 0) {
5300                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5301                                 if (f < 0)
5302                                         goto ecreate;
5303                         } else if (!S_ISREG(sb.st_mode)) {
5304                                 f = open(fname, O_WRONLY, 0666);
5305                                 if (f < 0)
5306                                         goto ecreate;
5307                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5308                                         close(f);
5309                                         errno = EEXIST;
5310                                         goto ecreate;
5311                                 }
5312                         } else {
5313                                 errno = EEXIST;
5314                                 goto ecreate;
5315                         }
5316                         break;
5317                 }
5318                 /* FALLTHROUGH */
5319         case NCLOBBER:
5320                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5321                 if (f < 0)
5322                         goto ecreate;
5323                 break;
5324         case NAPPEND:
5325                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5326                 if (f < 0)
5327                         goto ecreate;
5328                 break;
5329         }
5330
5331         return f;
5332  ecreate:
5333         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5334  eopen:
5335         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5336 }
5337
5338 /*
5339  * Copy a file descriptor to be >= 10. Throws exception on error.
5340  */
5341 static int
5342 savefd(int from)
5343 {
5344         int newfd;
5345         int err;
5346
5347         newfd = fcntl(from, F_DUPFD, 10);
5348         err = newfd < 0 ? errno : 0;
5349         if (err != EBADF) {
5350                 if (err)
5351                         ash_msg_and_raise_perror("%d", from);
5352                 close(from);
5353                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5354         }
5355
5356         return newfd;
5357 }
5358 static int
5359 dup2_or_raise(int from, int to)
5360 {
5361         int newfd;
5362
5363         newfd = (from != to) ? dup2(from, to) : to;
5364         if (newfd < 0) {
5365                 /* Happens when source fd is not open: try "echo >&99" */
5366                 ash_msg_and_raise_perror("%d", from);
5367         }
5368         return newfd;
5369 }
5370 static int
5371 fcntl_F_DUPFD(int fd, int avoid_fd)
5372 {
5373         int newfd;
5374  repeat:
5375         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5376         if (newfd < 0) {
5377                 if (errno == EBUSY)
5378                         goto repeat;
5379                 if (errno == EINTR)
5380                         goto repeat;
5381         }
5382         return newfd;
5383 }
5384 static int
5385 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5386 {
5387         int newfd;
5388  repeat:
5389         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5390         if (newfd < 0) {
5391                 if (errno == EBUSY)
5392                         goto repeat;
5393                 if (errno == EINTR)
5394                         goto repeat;
5395                 /* fd was not open? */
5396                 if (errno == EBADF)
5397                         return fd;
5398                 ash_msg_and_raise_perror("%d", newfd);
5399         }
5400         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5401         close(fd);
5402         return newfd;
5403 }
5404
5405 /* Struct def and variable are moved down to the first usage site */
5406 struct squirrel {
5407         int orig_fd;
5408         int moved_to;
5409 };
5410 struct redirtab {
5411         struct redirtab *next;
5412         int pair_count;
5413         struct squirrel two_fd[];
5414 };
5415 #define redirlist (G_var.redirlist)
5416
5417 static void
5418 add_squirrel_closed(struct redirtab *sq, int fd)
5419 {
5420         int i;
5421
5422         if (!sq)
5423                 return;
5424
5425         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5426                 /* If we collide with an already moved fd... */
5427                 if (fd == sq->two_fd[i].orig_fd) {
5428                         /* Examples:
5429                          * "echo 3>FILE 3>&- 3>FILE"
5430                          * "echo 3>&- 3>FILE"
5431                          * No need for last redirect to insert
5432                          * another "need to close 3" indicator.
5433                          */
5434                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5435                         return;
5436                 }
5437         }
5438         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5439         sq->two_fd[i].orig_fd = fd;
5440         sq->two_fd[i].moved_to = CLOSED;
5441 }
5442
5443 static int
5444 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5445 {
5446         int i, new_fd;
5447
5448         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5449                 avoid_fd = 9;
5450
5451 #if JOBS
5452         if (fd == ttyfd) {
5453                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5454                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5455                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5456                 return 1; /* "we closed fd" */
5457         }
5458 #endif
5459         /* Are we called from redirect(0)? E.g. redirect
5460          * in a forked child. No need to save fds,
5461          * we aren't going to use them anymore, ok to trash.
5462          */
5463         if (!sq)
5464                 return 0;
5465
5466         /* If this one of script's fds? */
5467         if (fd != 0) {
5468                 struct parsefile *pf = g_parsefile;
5469                 while (pf) {
5470                         /* We skip fd == 0 case because of the following:
5471                          * $ ash  # running ash interactively
5472                          * $ . ./script.sh
5473                          * and in script.sh: "exec 9>&0".
5474                          * Even though top-level pf_fd _is_ 0,
5475                          * it's still ok to use it: "read" builtin uses it,
5476                          * why should we cripple "exec" builtin?
5477                          */
5478                         if (fd == pf->pf_fd) {
5479                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5480                                 return 1; /* "we closed fd" */
5481                         }
5482                         pf = pf->prev;
5483                 }
5484         }
5485
5486         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5487
5488         /* First: do we collide with some already moved fds? */
5489         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5490                 /* If we collide with an already moved fd... */
5491                 if (fd == sq->two_fd[i].moved_to) {
5492                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5493                         sq->two_fd[i].moved_to = new_fd;
5494                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5495                         if (new_fd < 0) /* what? */
5496                                 xfunc_die();
5497                         return 0; /* "we did not close fd" */
5498                 }
5499                 if (fd == sq->two_fd[i].orig_fd) {
5500                         /* Example: echo Hello >/dev/null 1>&2 */
5501                         TRACE(("redirect_fd %d: already moved\n", fd));
5502                         return 0; /* "we did not close fd" */
5503                 }
5504         }
5505
5506         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5507         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5508         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5509         if (new_fd < 0) {
5510                 if (errno != EBADF)
5511                         xfunc_die();
5512                 /* new_fd = CLOSED; - already is -1 */
5513         }
5514         sq->two_fd[i].moved_to = new_fd;
5515         sq->two_fd[i].orig_fd = fd;
5516
5517         /* if we move stderr, let "set -x" code know */
5518         if (fd == preverrout_fd)
5519                 preverrout_fd = new_fd;
5520
5521         return 0; /* "we did not close fd" */
5522 }
5523
5524 static int
5525 internally_opened_fd(int fd, struct redirtab *sq)
5526 {
5527         int i;
5528 #if JOBS
5529         if (fd == ttyfd)
5530                 return 1;
5531 #endif
5532         /* If this one of script's fds? */
5533         if (fd != 0) {
5534                 struct parsefile *pf = g_parsefile;
5535                 while (pf) {
5536                         if (fd == pf->pf_fd)
5537                                 return 1;
5538                         pf = pf->prev;
5539                 }
5540         }
5541
5542         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5543                 if (fd == sq->two_fd[i].moved_to)
5544                         return 1;
5545         }
5546         return 0;
5547 }
5548
5549 /*
5550  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5551  * old file descriptors are stashed away so that the redirection can be
5552  * undone by calling popredir.
5553  */
5554 /* flags passed to redirect */
5555 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5556 static void
5557 redirect(union node *redir, int flags)
5558 {
5559         struct redirtab *sv;
5560
5561         if (!redir)
5562                 return;
5563
5564         sv = NULL;
5565         INT_OFF;
5566         if (flags & REDIR_PUSH)
5567                 sv = redirlist;
5568         do {
5569                 int fd;
5570                 int newfd;
5571                 int close_fd;
5572                 int closed;
5573
5574                 fd = redir->nfile.fd;
5575                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5576                         //bb_error_msg("doing %d > %d", fd, newfd);
5577                         newfd = redir->ndup.dupfd;
5578                         close_fd = -1;
5579                 } else {
5580                         newfd = openredirect(redir); /* always >= 0 */
5581                         if (fd == newfd) {
5582                                 /* open() gave us precisely the fd we wanted.
5583                                  * This means that this fd was not busy
5584                                  * (not opened to anywhere).
5585                                  * Remember to close it on restore:
5586                                  */
5587                                 add_squirrel_closed(sv, fd);
5588                                 continue;
5589                         }
5590                         close_fd = newfd;
5591                 }
5592
5593                 if (fd == newfd)
5594                         continue;
5595
5596                 /* if "N>FILE": move newfd to fd */
5597                 /* if "N>&M": dup newfd to fd */
5598                 /* if "N>&-": close fd (newfd is -1) */
5599
5600  IF_BASH_REDIR_OUTPUT(redirect_more:)
5601
5602                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5603                 if (newfd == -1) {
5604                         /* "N>&-" means "close me" */
5605                         if (!closed) {
5606                                 /* ^^^ optimization: saving may already
5607                                  * have closed it. If not... */
5608                                 close(fd);
5609                         }
5610                 } else {
5611                         /* if newfd is a script fd or saved fd, simulate EBADF */
5612                         if (internally_opened_fd(newfd, sv)) {
5613                                 errno = EBADF;
5614                                 ash_msg_and_raise_perror("%d", newfd);
5615                         }
5616                         dup2_or_raise(newfd, fd);
5617                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5618                                 close(close_fd);
5619 #if BASH_REDIR_OUTPUT
5620                         if (redir->nfile.type == NTO2 && fd == 1) {
5621                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5622                                 fd = 2;
5623                                 newfd = 1;
5624                                 close_fd = -1;
5625                                 goto redirect_more;
5626                         }
5627 #endif
5628                 }
5629         } while ((redir = redir->nfile.next) != NULL);
5630         INT_ON;
5631
5632 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5633 #define REDIR_SAVEFD2 0
5634         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5635         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5636         // not only for calls with flags containing REDIR_SAVEFD2.
5637         // We do this unconditionally (see save_fd_on_redirect()).
5638         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5639         //      preverrout_fd = copied_fd2;
5640 }
5641
5642 static int
5643 redirectsafe(union node *redir, int flags)
5644 {
5645         int err;
5646         volatile int saveint;
5647         struct jmploc *volatile savehandler = exception_handler;
5648         struct jmploc jmploc;
5649
5650         SAVE_INT(saveint);
5651         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5652         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5653         if (!err) {
5654                 exception_handler = &jmploc;
5655                 redirect(redir, flags);
5656         }
5657         exception_handler = savehandler;
5658         if (err && exception_type != EXERROR)
5659                 longjmp(exception_handler->loc, 1);
5660         RESTORE_INT(saveint);
5661         return err;
5662 }
5663
5664 static struct redirtab*
5665 pushredir(union node *redir)
5666 {
5667         struct redirtab *sv;
5668         int i;
5669
5670         if (!redir)
5671                 return redirlist;
5672
5673         i = 0;
5674         do {
5675                 i++;
5676 #if BASH_REDIR_OUTPUT
5677                 if (redir->nfile.type == NTO2)
5678                         i++;
5679 #endif
5680                 redir = redir->nfile.next;
5681         } while (redir);
5682
5683         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5684         sv->pair_count = i;
5685         while (--i >= 0)
5686                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5687         sv->next = redirlist;
5688         redirlist = sv;
5689         return sv->next;
5690 }
5691
5692 /*
5693  * Undo the effects of the last redirection.
5694  */
5695 static void
5696 popredir(int drop)
5697 {
5698         struct redirtab *rp;
5699         int i;
5700
5701         if (redirlist == NULL)
5702                 return;
5703         INT_OFF;
5704         rp = redirlist;
5705         for (i = 0; i < rp->pair_count; i++) {
5706                 int fd = rp->two_fd[i].orig_fd;
5707                 int copy = rp->two_fd[i].moved_to;
5708                 if (copy == CLOSED) {
5709                         if (!drop)
5710                                 close(fd);
5711                         continue;
5712                 }
5713                 if (copy != EMPTY) {
5714                         if (!drop) {
5715                                 /*close(fd);*/
5716                                 dup2_or_raise(copy, fd);
5717                         }
5718                         close(copy);
5719                 }
5720         }
5721         redirlist = rp->next;
5722         free(rp);
5723         INT_ON;
5724 }
5725
5726 static void
5727 unwindredir(struct redirtab *stop)
5728 {
5729         while (redirlist != stop)
5730                 popredir(/*drop:*/ 0);
5731 }
5732
5733
5734 /* ============ Routines to expand arguments to commands
5735  *
5736  * We have to deal with backquotes, shell variables, and file metacharacters.
5737  */
5738
5739 #if ENABLE_FEATURE_SH_MATH
5740 static arith_t
5741 ash_arith(const char *s)
5742 {
5743         arith_state_t math_state;
5744         arith_t result;
5745
5746         math_state.lookupvar = lookupvar;
5747         math_state.setvar    = setvar0;
5748         //math_state.endofname = endofname;
5749
5750         INT_OFF;
5751         result = arith(&math_state, s);
5752         if (math_state.errmsg)
5753                 ash_msg_and_raise_error(math_state.errmsg);
5754         INT_ON;
5755
5756         return result;
5757 }
5758 #endif
5759
5760 /*
5761  * expandarg flags
5762  */
5763 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5764 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5765 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5766 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5767 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5768  * POSIX says for this case:
5769  *  Pathname expansion shall not be performed on the word by a
5770  *  non-interactive shell; an interactive shell may perform it, but shall
5771  *  do so only when the expansion would result in one word.
5772  * Currently, our code complies to the above rule by never globbing
5773  * redirection filenames.
5774  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5775  * (this means that on a typical Linux distro, bash almost always
5776  * performs globbing, and thus diverges from what we do).
5777  */
5778 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5779 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5780 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5781 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5782 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5783 /*
5784  * rmescape() flags
5785  */
5786 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5787 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5788 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5789 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5790 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5791
5792 /* Add CTLESC when necessary. */
5793 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5794 /* Do not skip NUL characters. */
5795 #define QUOTES_KEEPNUL EXP_TILDE
5796
5797 /*
5798  * Structure specifying which parts of the string should be searched
5799  * for IFS characters.
5800  */
5801 struct ifsregion {
5802         struct ifsregion *next; /* next region in list */
5803         int begoff;             /* offset of start of region */
5804         int endoff;             /* offset of end of region */
5805         int nulonly;            /* search for nul bytes only */
5806 };
5807
5808 struct arglist {
5809         struct strlist *list;
5810         struct strlist **lastp;
5811 };
5812
5813 /* output of current string */
5814 static char *expdest;
5815 /* list of back quote expressions */
5816 static struct nodelist *argbackq;
5817 /* first struct in list of ifs regions */
5818 static struct ifsregion ifsfirst;
5819 /* last struct in list */
5820 static struct ifsregion *ifslastp;
5821 /* holds expanded arg list */
5822 static struct arglist exparg;
5823
5824 /*
5825  * Our own itoa().
5826  * cvtnum() is used even if math support is off (to prepare $? values and such).
5827  */
5828 static int
5829 cvtnum(arith_t num)
5830 {
5831         int len;
5832
5833         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5834         len = sizeof(arith_t) * 3;
5835         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5836         if (sizeof(arith_t) < 4) len += 2;
5837
5838         expdest = makestrspace(len, expdest);
5839         len = fmtstr(expdest, len, ARITH_FMT, num);
5840         STADJUST(len, expdest);
5841         return len;
5842 }
5843
5844 /*
5845  * Break the argument string into pieces based upon IFS and add the
5846  * strings to the argument list.  The regions of the string to be
5847  * searched for IFS characters have been stored by recordregion.
5848  */
5849 static void
5850 ifsbreakup(char *string, struct arglist *arglist)
5851 {
5852         struct ifsregion *ifsp;
5853         struct strlist *sp;
5854         char *start;
5855         char *p;
5856         char *q;
5857         const char *ifs, *realifs;
5858         int ifsspc;
5859         int nulonly;
5860
5861         start = string;
5862         if (ifslastp != NULL) {
5863                 ifsspc = 0;
5864                 nulonly = 0;
5865                 realifs = ifsset() ? ifsval() : defifs;
5866                 ifsp = &ifsfirst;
5867                 do {
5868                         p = string + ifsp->begoff;
5869                         nulonly = ifsp->nulonly;
5870                         ifs = nulonly ? nullstr : realifs;
5871                         ifsspc = 0;
5872                         while (p < string + ifsp->endoff) {
5873                                 q = p;
5874                                 if ((unsigned char)*p == CTLESC)
5875                                         p++;
5876                                 if (!strchr(ifs, *p)) {
5877                                         p++;
5878                                         continue;
5879                                 }
5880                                 if (!nulonly)
5881                                         ifsspc = (strchr(defifs, *p) != NULL);
5882                                 /* Ignore IFS whitespace at start */
5883                                 if (q == start && ifsspc) {
5884                                         p++;
5885                                         start = p;
5886                                         continue;
5887                                 }
5888                                 *q = '\0';
5889                                 sp = stzalloc(sizeof(*sp));
5890                                 sp->text = start;
5891                                 *arglist->lastp = sp;
5892                                 arglist->lastp = &sp->next;
5893                                 p++;
5894                                 if (!nulonly) {
5895                                         for (;;) {
5896                                                 if (p >= string + ifsp->endoff) {
5897                                                         break;
5898                                                 }
5899                                                 q = p;
5900                                                 if ((unsigned char)*p == CTLESC)
5901                                                         p++;
5902                                                 if (strchr(ifs, *p) == NULL) {
5903                                                         p = q;
5904                                                         break;
5905                                                 }
5906                                                 if (strchr(defifs, *p) == NULL) {
5907                                                         if (ifsspc) {
5908                                                                 p++;
5909                                                                 ifsspc = 0;
5910                                                         } else {
5911                                                                 p = q;
5912                                                                 break;
5913                                                         }
5914                                                 } else
5915                                                         p++;
5916                                         }
5917                                 }
5918                                 start = p;
5919                         } /* while */
5920                         ifsp = ifsp->next;
5921                 } while (ifsp != NULL);
5922                 if (nulonly)
5923                         goto add;
5924         }
5925
5926         if (!*start)
5927                 return;
5928
5929  add:
5930         sp = stzalloc(sizeof(*sp));
5931         sp->text = start;
5932         *arglist->lastp = sp;
5933         arglist->lastp = &sp->next;
5934 }
5935
5936 static void
5937 ifsfree(void)
5938 {
5939         struct ifsregion *p = ifsfirst.next;
5940
5941         if (!p)
5942                 goto out;
5943
5944         INT_OFF;
5945         do {
5946                 struct ifsregion *ifsp;
5947                 ifsp = p->next;
5948                 free(p);
5949                 p = ifsp;
5950         } while (p);
5951         ifsfirst.next = NULL;
5952         INT_ON;
5953  out:
5954         ifslastp = NULL;
5955 }
5956
5957 static size_t
5958 esclen(const char *start, const char *p)
5959 {
5960         size_t esc = 0;
5961
5962         while (p > start && (unsigned char)*--p == CTLESC) {
5963                 esc++;
5964         }
5965         return esc;
5966 }
5967
5968 /*
5969  * Remove any CTLESC characters from a string.
5970  */
5971 static char *
5972 rmescapes(char *str, int flag)
5973 {
5974         static const char qchars[] ALIGN1 = {
5975                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5976
5977         char *p, *q, *r;
5978         unsigned inquotes;
5979         unsigned protect_against_glob;
5980         unsigned globbing;
5981         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5982
5983         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5984         if (!p)
5985                 return str;
5986
5987         q = p;
5988         r = str;
5989         if (flag & RMESCAPE_ALLOC) {
5990                 size_t len = p - str;
5991                 size_t fulllen = len + strlen(p) + 1;
5992
5993                 if (flag & RMESCAPE_GROW) {
5994                         int strloc = str - (char *)stackblock();
5995                         r = makestrspace(fulllen, expdest);
5996                         /* p and str may be invalidated by makestrspace */
5997                         str = (char *)stackblock() + strloc;
5998                         p = str + len;
5999                 } else if (flag & RMESCAPE_HEAP) {
6000                         r = ckmalloc(fulllen);
6001                 } else {
6002                         r = stalloc(fulllen);
6003                 }
6004                 q = r;
6005                 if (len > 0) {
6006                         q = (char *)mempcpy(q, str, len);
6007                 }
6008         }
6009
6010         inquotes = 0;
6011         globbing = flag & RMESCAPE_GLOB;
6012         protect_against_glob = globbing;
6013         while (*p) {
6014                 if ((unsigned char)*p == CTLQUOTEMARK) {
6015 // Note: both inquotes and protect_against_glob only affect whether
6016 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6017                         inquotes = ~inquotes;
6018                         p++;
6019                         protect_against_glob = globbing;
6020                         continue;
6021                 }
6022                 if ((unsigned char)*p == CTLESC) {
6023                         p++;
6024 #if DEBUG
6025                         if (*p == '\0')
6026                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6027 #endif
6028                         if (protect_against_glob) {
6029                                 /*
6030                                  * We used to trust glob() and fnmatch() to eat
6031                                  * superfluous escapes (\z where z has no
6032                                  * special meaning anyway). But this causes
6033                                  * bugs such as string of one greek letter rho
6034                                  * (unicode-encoded as two bytes "cf,81")
6035                                  * getting encoded as "cf,CTLESC,81"
6036                                  * and here, converted to "cf,\,81" -
6037                                  * which does not go well with some flavors
6038                                  * of fnmatch() in unicode locales
6039                                  * (for example, glibc <= 2.22).
6040                                  *
6041                                  * Lets add "\" only on the chars which need it.
6042                                  * Testcases for less obvious chars are shown.
6043                                  */
6044                                 if (*p == '*'
6045                                  || *p == '?'
6046                                  || *p == '['
6047                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6048                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6049                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6050                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6051                                 /* Some libc support [^negate], that's why "^" also needs love */
6052                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6053                                 ) {
6054                                         *q++ = '\\';
6055                                 }
6056                         }
6057                 } else if (*p == '\\' && !inquotes) {
6058                         /* naked back slash */
6059                         protect_against_glob = 0;
6060                         goto copy;
6061                 }
6062 #if BASH_PATTERN_SUBST
6063                 else if (*p == '/' && slash) {
6064                         /* stop handling globbing and mark location of slash */
6065                         globbing = slash = 0;
6066                         *p = CTLESC;
6067                 }
6068 #endif
6069                 protect_against_glob = globbing;
6070  copy:
6071                 *q++ = *p++;
6072         }
6073         *q = '\0';
6074         if (flag & RMESCAPE_GROW) {
6075                 expdest = r;
6076                 STADJUST(q - r + 1, expdest);
6077         }
6078         return r;
6079 }
6080 #define pmatch(a, b) !fnmatch((a), (b), 0)
6081
6082 /*
6083  * Prepare a pattern for a expmeta (internal glob(3)) call.
6084  *
6085  * Returns an stalloced string.
6086  */
6087 static char *
6088 preglob(const char *pattern, int flag)
6089 {
6090         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6091 }
6092
6093 /*
6094  * Put a string on the stack.
6095  */
6096 static void
6097 memtodest(const char *p, size_t len, int syntax, int quotes)
6098 {
6099         char *q;
6100
6101         if (!len)
6102                 return;
6103
6104         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6105
6106         do {
6107                 unsigned char c = *p++;
6108                 if (c) {
6109                         if (quotes & QUOTES_ESC) {
6110                                 int n = SIT(c, syntax);
6111                                 if (n == CCTL
6112                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6113                                      && n == CBACK
6114                                     )
6115                                 ) {
6116                                         USTPUTC(CTLESC, q);
6117                                 }
6118                         }
6119                 } else if (!(quotes & QUOTES_KEEPNUL))
6120                         continue;
6121                 USTPUTC(c, q);
6122         } while (--len);
6123
6124         expdest = q;
6125 }
6126
6127 static size_t
6128 strtodest(const char *p, int syntax, int quotes)
6129 {
6130         size_t len = strlen(p);
6131         memtodest(p, len, syntax, quotes);
6132         return len;
6133 }
6134
6135 /*
6136  * Record the fact that we have to scan this region of the
6137  * string for IFS characters.
6138  */
6139 static void
6140 recordregion(int start, int end, int nulonly)
6141 {
6142         struct ifsregion *ifsp;
6143
6144         if (ifslastp == NULL) {
6145                 ifsp = &ifsfirst;
6146         } else {
6147                 INT_OFF;
6148                 ifsp = ckzalloc(sizeof(*ifsp));
6149                 /*ifsp->next = NULL; - ckzalloc did it */
6150                 ifslastp->next = ifsp;
6151                 INT_ON;
6152         }
6153         ifslastp = ifsp;
6154         ifslastp->begoff = start;
6155         ifslastp->endoff = end;
6156         ifslastp->nulonly = nulonly;
6157 }
6158
6159 static void
6160 removerecordregions(int endoff)
6161 {
6162         if (ifslastp == NULL)
6163                 return;
6164
6165         if (ifsfirst.endoff > endoff) {
6166                 while (ifsfirst.next) {
6167                         struct ifsregion *ifsp;
6168                         INT_OFF;
6169                         ifsp = ifsfirst.next->next;
6170                         free(ifsfirst.next);
6171                         ifsfirst.next = ifsp;
6172                         INT_ON;
6173                 }
6174                 if (ifsfirst.begoff > endoff) {
6175                         ifslastp = NULL;
6176                 } else {
6177                         ifslastp = &ifsfirst;
6178                         ifsfirst.endoff = endoff;
6179                 }
6180                 return;
6181         }
6182
6183         ifslastp = &ifsfirst;
6184         while (ifslastp->next && ifslastp->next->begoff < endoff)
6185                 ifslastp = ifslastp->next;
6186         while (ifslastp->next) {
6187                 struct ifsregion *ifsp;
6188                 INT_OFF;
6189                 ifsp = ifslastp->next->next;
6190                 free(ifslastp->next);
6191                 ifslastp->next = ifsp;
6192                 INT_ON;
6193         }
6194         if (ifslastp->endoff > endoff)
6195                 ifslastp->endoff = endoff;
6196 }
6197
6198 static char *
6199 exptilde(char *startp, char *p, int flags)
6200 {
6201         unsigned char c;
6202         char *name;
6203         struct passwd *pw;
6204         const char *home;
6205         int quotes = flags & QUOTES_ESC;
6206
6207         name = p + 1;
6208
6209         while ((c = *++p) != '\0') {
6210                 switch (c) {
6211                 case CTLESC:
6212                         return startp;
6213                 case CTLQUOTEMARK:
6214                         return startp;
6215                 case ':':
6216                         if (flags & EXP_VARTILDE)
6217                                 goto done;
6218                         break;
6219                 case '/':
6220                 case CTLENDVAR:
6221                         goto done;
6222                 }
6223         }
6224  done:
6225         *p = '\0';
6226         if (*name == '\0') {
6227                 home = lookupvar("HOME");
6228         } else {
6229                 pw = getpwnam(name);
6230                 if (pw == NULL)
6231                         goto lose;
6232                 home = pw->pw_dir;
6233         }
6234         if (!home || !*home)
6235                 goto lose;
6236         *p = c;
6237         strtodest(home, SQSYNTAX, quotes);
6238         return p;
6239  lose:
6240         *p = c;
6241         return startp;
6242 }
6243
6244 /*
6245  * Execute a command inside back quotes.  If it's a builtin command, we
6246  * want to save its output in a block obtained from malloc.  Otherwise
6247  * we fork off a subprocess and get the output of the command via a pipe.
6248  * Should be called with interrupts off.
6249  */
6250 struct backcmd {                /* result of evalbackcmd */
6251         int fd;                 /* file descriptor to read from */
6252         int nleft;              /* number of chars in buffer */
6253         char *buf;              /* buffer */
6254         struct job *jp;         /* job structure for command */
6255 };
6256
6257 /* These forward decls are needed to use "eval" code for backticks handling: */
6258 /* flags in argument to evaltree */
6259 #define EV_EXIT    01           /* exit after evaluating tree */
6260 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6261 static int evaltree(union node *, int);
6262
6263 /* An evaltree() which is known to never return.
6264  * Used to use an alias:
6265  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6266  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6267  */
6268 static ALWAYS_INLINE NORETURN void
6269 evaltreenr(union node *n, int flags)
6270 {
6271         evaltree(n, flags);
6272         bb_unreachable(abort());
6273         /* NOTREACHED */
6274 }
6275
6276 static void FAST_FUNC
6277 evalbackcmd(union node *n, struct backcmd *result)
6278 {
6279         int pip[2];
6280         struct job *jp;
6281
6282         result->fd = -1;
6283         result->buf = NULL;
6284         result->nleft = 0;
6285         result->jp = NULL;
6286         if (n == NULL) {
6287                 goto out;
6288         }
6289
6290         if (pipe(pip) < 0)
6291                 ash_msg_and_raise_error("pipe call failed");
6292         jp = makejob(/*n,*/ 1);
6293         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6294                 /* child */
6295                 FORCE_INT_ON;
6296                 close(pip[0]);
6297                 if (pip[1] != 1) {
6298                         /*close(1);*/
6299                         dup2_or_raise(pip[1], 1);
6300                         close(pip[1]);
6301                 }
6302 /* TODO: eflag clearing makes the following not abort:
6303  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6304  * which is what bash does (unless it is in POSIX mode).
6305  * dash deleted "eflag = 0" line in the commit
6306  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6307  *  [EVAL] Don't clear eflag in evalbackcmd
6308  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6309  */
6310                 eflag = 0;
6311                 ifsfree();
6312                 evaltreenr(n, EV_EXIT);
6313                 /* NOTREACHED */
6314         }
6315         /* parent */
6316         close(pip[1]);
6317         result->fd = pip[0];
6318         result->jp = jp;
6319
6320  out:
6321         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6322                 result->fd, result->buf, result->nleft, result->jp));
6323 }
6324
6325 /*
6326  * Expand stuff in backwards quotes.
6327  */
6328 static void
6329 expbackq(union node *cmd, int flag)
6330 {
6331         struct backcmd in;
6332         int i;
6333         char buf[128];
6334         char *p;
6335         char *dest;
6336         int startloc;
6337         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6338         struct stackmark smark;
6339
6340         INT_OFF;
6341         startloc = expdest - (char *)stackblock();
6342         pushstackmark(&smark, startloc);
6343         evalbackcmd(cmd, &in);
6344         popstackmark(&smark);
6345
6346         p = in.buf;
6347         i = in.nleft;
6348         if (i == 0)
6349                 goto read;
6350         for (;;) {
6351                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6352  read:
6353                 if (in.fd < 0)
6354                         break;
6355                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6356                 TRACE(("expbackq: read returns %d\n", i));
6357                 if (i <= 0)
6358                         break;
6359                 p = buf;
6360         }
6361
6362         free(in.buf);
6363         if (in.fd >= 0) {
6364                 close(in.fd);
6365                 back_exitstatus = waitforjob(in.jp);
6366         }
6367         INT_ON;
6368
6369         /* Eat all trailing newlines */
6370         dest = expdest;
6371         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6372                 STUNPUTC(dest);
6373         expdest = dest;
6374
6375         if (!(flag & EXP_QUOTED))
6376                 recordregion(startloc, dest - (char *)stackblock(), 0);
6377         TRACE(("evalbackq: size:%d:'%.*s'\n",
6378                 (int)((dest - (char *)stackblock()) - startloc),
6379                 (int)((dest - (char *)stackblock()) - startloc),
6380                 stackblock() + startloc));
6381 }
6382
6383 #if ENABLE_FEATURE_SH_MATH
6384 /*
6385  * Expand arithmetic expression.  Backup to start of expression,
6386  * evaluate, place result in (backed up) result, adjust string position.
6387  */
6388 static void
6389 expari(int flag)
6390 {
6391         char *p, *start;
6392         int begoff;
6393         int len;
6394
6395         /* ifsfree(); */
6396
6397         /*
6398          * This routine is slightly over-complicated for
6399          * efficiency.  Next we scan backwards looking for the
6400          * start of arithmetic.
6401          */
6402         start = stackblock();
6403         p = expdest - 1;
6404         *p = '\0';
6405         p--;
6406         while (1) {
6407                 int esc;
6408
6409                 while ((unsigned char)*p != CTLARI) {
6410                         p--;
6411 #if DEBUG
6412                         if (p < start) {
6413                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6414                         }
6415 #endif
6416                 }
6417
6418                 esc = esclen(start, p);
6419                 if (!(esc % 2)) {
6420                         break;
6421                 }
6422
6423                 p -= esc + 1;
6424         }
6425
6426         begoff = p - start;
6427
6428         removerecordregions(begoff);
6429
6430         expdest = p;
6431
6432         if (flag & QUOTES_ESC)
6433                 rmescapes(p + 1, 0);
6434
6435         len = cvtnum(ash_arith(p + 1));
6436
6437         if (!(flag & EXP_QUOTED))
6438                 recordregion(begoff, begoff + len, 0);
6439 }
6440 #endif
6441
6442 /* argstr needs it */
6443 static char *evalvar(char *p, int flags);
6444
6445 /*
6446  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6447  * characters to allow for further processing.  Otherwise treat
6448  * $@ like $* since no splitting will be performed.
6449  */
6450 static void
6451 argstr(char *p, int flags)
6452 {
6453         static const char spclchars[] ALIGN1 = {
6454                 '=',
6455                 ':',
6456                 CTLQUOTEMARK,
6457                 CTLENDVAR,
6458                 CTLESC,
6459                 CTLVAR,
6460                 CTLBACKQ,
6461 #if ENABLE_FEATURE_SH_MATH
6462                 CTLENDARI,
6463 #endif
6464                 '\0'
6465         };
6466         const char *reject = spclchars;
6467         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6468         int inquotes;
6469         size_t length;
6470         int startloc;
6471
6472         if (!(flags & EXP_VARTILDE)) {
6473                 reject += 2;
6474         } else if (flags & EXP_VARTILDE2) {
6475                 reject++;
6476         }
6477         inquotes = 0;
6478         length = 0;
6479         if (flags & EXP_TILDE) {
6480                 char *q;
6481
6482                 flags &= ~EXP_TILDE;
6483  tilde:
6484                 q = p;
6485                 if (*q == '~')
6486                         p = exptilde(p, q, flags);
6487         }
6488  start:
6489         startloc = expdest - (char *)stackblock();
6490         for (;;) {
6491                 unsigned char c;
6492
6493                 length += strcspn(p + length, reject);
6494                 c = p[length];
6495                 if (c) {
6496                         if (!(c & 0x80)
6497                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6498                         ) {
6499                                 /* c == '=' || c == ':' || c == CTLENDARI */
6500                                 length++;
6501                         }
6502                 }
6503                 if (length > 0) {
6504                         int newloc;
6505                         expdest = stack_nputstr(p, length, expdest);
6506                         newloc = expdest - (char *)stackblock();
6507                         if (breakall && !inquotes && newloc > startloc) {
6508                                 recordregion(startloc, newloc, 0);
6509                         }
6510                         startloc = newloc;
6511                 }
6512                 p += length + 1;
6513                 length = 0;
6514
6515                 switch (c) {
6516                 case '\0':
6517                         goto breakloop;
6518                 case '=':
6519                         if (flags & EXP_VARTILDE2) {
6520                                 p--;
6521                                 continue;
6522                         }
6523                         flags |= EXP_VARTILDE2;
6524                         reject++;
6525                         /* fall through */
6526                 case ':':
6527                         /*
6528                          * sort of a hack - expand tildes in variable
6529                          * assignments (after the first '=' and after ':'s).
6530                          */
6531                         if (*--p == '~') {
6532                                 goto tilde;
6533                         }
6534                         continue;
6535                 }
6536
6537                 switch (c) {
6538                 case CTLENDVAR: /* ??? */
6539                         goto breakloop;
6540                 case CTLQUOTEMARK:
6541                         inquotes ^= EXP_QUOTED;
6542                         /* "$@" syntax adherence hack */
6543                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6544                                 p = evalvar(p + 1, flags | inquotes) + 1;
6545                                 goto start;
6546                         }
6547  addquote:
6548                         if (flags & QUOTES_ESC) {
6549                                 p--;
6550                                 length++;
6551                                 startloc++;
6552                         }
6553                         break;
6554                 case CTLESC:
6555                         startloc++;
6556                         length++;
6557
6558                         /*
6559                          * Quoted parameter expansion pattern: remove quote
6560                          * unless inside inner quotes or we have a literal
6561                          * backslash.
6562                          */
6563                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6564                             EXP_QPAT && *p != '\\')
6565                                 break;
6566
6567                         goto addquote;
6568                 case CTLVAR:
6569                         TRACE(("argstr: evalvar('%s')\n", p));
6570                         p = evalvar(p, flags | inquotes);
6571                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6572                         goto start;
6573                 case CTLBACKQ:
6574                         expbackq(argbackq->n, flags | inquotes);
6575                         argbackq = argbackq->next;
6576                         goto start;
6577 #if ENABLE_FEATURE_SH_MATH
6578                 case CTLENDARI:
6579                         p--;
6580                         expari(flags | inquotes);
6581                         goto start;
6582 #endif
6583                 }
6584         }
6585  breakloop: ;
6586 }
6587
6588 static char *
6589 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6590                 char *pattern, int quotes, int zero)
6591 {
6592         char *loc, *loc2;
6593         char c;
6594
6595         loc = startp;
6596         loc2 = rmesc;
6597         do {
6598                 int match;
6599                 const char *s = loc2;
6600
6601                 c = *loc2;
6602                 if (zero) {
6603                         *loc2 = '\0';
6604                         s = rmesc;
6605                 }
6606                 match = pmatch(pattern, s);
6607
6608                 *loc2 = c;
6609                 if (match)
6610                         return loc;
6611                 if (quotes && (unsigned char)*loc == CTLESC)
6612                         loc++;
6613                 loc++;
6614                 loc2++;
6615         } while (c);
6616         return NULL;
6617 }
6618
6619 static char *
6620 scanright(char *startp, char *rmesc, char *rmescend,
6621                 char *pattern, int quotes, int match_at_start)
6622 {
6623 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6624         int try2optimize = match_at_start;
6625 #endif
6626         int esc = 0;
6627         char *loc;
6628         char *loc2;
6629
6630         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6631          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6632          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6633          * Logic:
6634          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6635          * and on each iteration they go back two/one char until they reach the beginning.
6636          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6637          */
6638         /* TODO: document in what other circumstances we are called. */
6639
6640         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6641                 int match;
6642                 char c = *loc2;
6643                 const char *s = loc2;
6644                 if (match_at_start) {
6645                         *loc2 = '\0';
6646                         s = rmesc;
6647                 }
6648                 match = pmatch(pattern, s);
6649                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6650                 *loc2 = c;
6651                 if (match)
6652                         return loc;
6653 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6654                 if (try2optimize) {
6655                         /* Maybe we can optimize this:
6656                          * if pattern ends with unescaped *, we can avoid checking
6657                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6658                          * it won't match truncated "raw_value_of_" strings too.
6659                          */
6660                         unsigned plen = strlen(pattern);
6661                         /* Does it end with "*"? */
6662                         if (plen != 0 && pattern[--plen] == '*') {
6663                                 /* "xxxx*" is not escaped */
6664                                 /* "xxx\*" is escaped */
6665                                 /* "xx\\*" is not escaped */
6666                                 /* "x\\\*" is escaped */
6667                                 int slashes = 0;
6668                                 while (plen != 0 && pattern[--plen] == '\\')
6669                                         slashes++;
6670                                 if (!(slashes & 1))
6671                                         break; /* ends with unescaped "*" */
6672                         }
6673                         try2optimize = 0;
6674                 }
6675 #endif
6676                 loc--;
6677                 if (quotes) {
6678                         if (--esc < 0) {
6679                                 esc = esclen(startp, loc);
6680                         }
6681                         if (esc % 2) {
6682                                 esc--;
6683                                 loc--;
6684                         }
6685                 }
6686         }
6687         return NULL;
6688 }
6689
6690 static void varunset(const char *, const char *, const char *, int) NORETURN;
6691 static void
6692 varunset(const char *end, const char *var, const char *umsg, int varflags)
6693 {
6694         const char *msg;
6695         const char *tail;
6696
6697         tail = nullstr;
6698         msg = "parameter not set";
6699         if (umsg) {
6700                 if ((unsigned char)*end == CTLENDVAR) {
6701                         if (varflags & VSNUL)
6702                                 tail = " or null";
6703                 } else {
6704                         msg = umsg;
6705                 }
6706         }
6707         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6708 }
6709
6710 static const char *
6711 subevalvar(char *p, char *varname, int strloc, int subtype,
6712                 int startloc, int varflags, int flag)
6713 {
6714         struct nodelist *saveargbackq = argbackq;
6715         int quotes = flag & QUOTES_ESC;
6716         char *startp;
6717         char *loc;
6718         char *rmesc, *rmescend;
6719         char *str;
6720         int amount, resetloc;
6721         IF_BASH_PATTERN_SUBST(int workloc;)
6722         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6723         int zero;
6724         char *(*scan)(char*, char*, char*, char*, int, int);
6725
6726         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6727         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6728
6729         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6730                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6731         );
6732         STPUTC('\0', expdest);
6733         argbackq = saveargbackq;
6734         startp = (char *)stackblock() + startloc;
6735
6736         switch (subtype) {
6737         case VSASSIGN:
6738                 setvar0(varname, startp);
6739                 amount = startp - expdest;
6740                 STADJUST(amount, expdest);
6741                 return startp;
6742
6743         case VSQUESTION:
6744                 varunset(p, varname, startp, varflags);
6745                 /* NOTREACHED */
6746
6747 #if BASH_SUBSTR
6748         case VSSUBSTR: {
6749                 int pos, len, orig_len;
6750                 char *colon;
6751
6752                 loc = str = stackblock() + strloc;
6753
6754 # if !ENABLE_FEATURE_SH_MATH
6755 #  define ash_arith number
6756 # endif
6757                 /* Read POS in ${var:POS:LEN} */
6758                 colon = strchr(loc, ':');
6759                 if (colon) *colon = '\0';
6760                 pos = ash_arith(loc);
6761                 if (colon) *colon = ':';
6762
6763                 /* Read LEN in ${var:POS:LEN} */
6764                 len = str - startp - 1;
6765                 /* *loc != '\0', guaranteed by parser */
6766                 if (quotes) {
6767                         char *ptr;
6768
6769                         /* Adjust the length by the number of escapes */
6770                         for (ptr = startp; ptr < (str - 1); ptr++) {
6771                                 if ((unsigned char)*ptr == CTLESC) {
6772                                         len--;
6773                                         ptr++;
6774                                 }
6775                         }
6776                 }
6777                 orig_len = len;
6778                 if (*loc++ == ':') {
6779                         /* ${var::LEN} */
6780                         len = ash_arith(loc);
6781                 } else {
6782                         /* Skip POS in ${var:POS:LEN} */
6783                         len = orig_len;
6784                         while (*loc && *loc != ':') {
6785                                 loc++;
6786                         }
6787                         if (*loc++ == ':') {
6788                                 len = ash_arith(loc);
6789                         }
6790                 }
6791 #  undef ash_arith
6792
6793                 if (pos < 0) {
6794                         /* ${VAR:$((-n)):l} starts n chars from the end */
6795                         pos = orig_len + pos;
6796                 }
6797                 if ((unsigned)pos >= orig_len) {
6798                         /* apart from obvious ${VAR:999999:l},
6799                          * covers ${VAR:$((-9999999)):l} - result is ""
6800                          * (bash compat)
6801                          */
6802                         pos = 0;
6803                         len = 0;
6804                 }
6805                 if (len < 0) {
6806                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6807                         len = (orig_len - pos) + len;
6808                 }
6809                 if ((unsigned)len > (orig_len - pos))
6810                         len = orig_len - pos;
6811
6812                 for (str = startp; pos; str++, pos--) {
6813                         if (quotes && (unsigned char)*str == CTLESC)
6814                                 str++;
6815                 }
6816                 for (loc = startp; len; len--) {
6817                         if (quotes && (unsigned char)*str == CTLESC)
6818                                 *loc++ = *str++;
6819                         *loc++ = *str++;
6820                 }
6821                 *loc = '\0';
6822                 amount = loc - expdest;
6823                 STADJUST(amount, expdest);
6824                 return loc;
6825         }
6826 #endif /* BASH_SUBSTR */
6827         }
6828
6829         resetloc = expdest - (char *)stackblock();
6830
6831 #if BASH_PATTERN_SUBST
6832         /* We'll comeback here if we grow the stack while handling
6833          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6834          * stack will need rebasing, and we'll need to remove our work
6835          * areas each time
6836          */
6837  restart:
6838 #endif
6839
6840         amount = expdest - ((char *)stackblock() + resetloc);
6841         STADJUST(-amount, expdest);
6842         startp = (char *)stackblock() + startloc;
6843
6844         rmesc = startp;
6845         rmescend = (char *)stackblock() + strloc;
6846         if (quotes) {
6847                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6848                 if (rmesc != startp) {
6849                         rmescend = expdest;
6850                         startp = (char *)stackblock() + startloc;
6851                 }
6852         }
6853         rmescend--;
6854         str = (char *)stackblock() + strloc;
6855         /*
6856          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6857          * The result is a_\_z_c (not a\_\_z_c)!
6858          *
6859          * The search pattern and replace string treat backslashes differently!
6860          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6861          * and string.  It's only used on the first call.
6862          */
6863         preglob(str, IF_BASH_PATTERN_SUBST(
6864                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6865                         RMESCAPE_SLASH : ) 0);
6866
6867 #if BASH_PATTERN_SUBST
6868         workloc = expdest - (char *)stackblock();
6869         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6870                 int len;
6871                 char *idx, *end;
6872
6873                 if (!repl) {
6874                         repl = strchr(str, CTLESC);
6875                         if (repl)
6876                                 *repl++ = '\0';
6877                         else
6878                                 repl = nullstr;
6879                 }
6880                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6881
6882                 /* If there's no pattern to match, return the expansion unmolested */
6883                 if (str[0] == '\0')
6884                         return NULL;
6885
6886                 len = 0;
6887                 idx = startp;
6888                 end = str - 1;
6889                 while (idx < end) {
6890  try_to_match:
6891                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6892                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6893                         if (!loc) {
6894                                 /* No match, advance */
6895                                 char *restart_detect = stackblock();
6896  skip_matching:
6897                                 STPUTC(*idx, expdest);
6898                                 if (quotes && (unsigned char)*idx == CTLESC) {
6899                                         idx++;
6900                                         len++;
6901                                         STPUTC(*idx, expdest);
6902                                 }
6903                                 if (stackblock() != restart_detect)
6904                                         goto restart;
6905                                 idx++;
6906                                 len++;
6907                                 rmesc++;
6908                                 /* continue; - prone to quadratic behavior, smarter code: */
6909                                 if (idx >= end)
6910                                         break;
6911                                 if (str[0] == '*') {
6912                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6913                                          * it would never match "ong_string" etc, no point in trying.
6914                                          */
6915                                         goto skip_matching;
6916                                 }
6917                                 goto try_to_match;
6918                         }
6919
6920                         if (subtype == VSREPLACEALL) {
6921                                 while (idx < loc) {
6922                                         if (quotes && (unsigned char)*idx == CTLESC)
6923                                                 idx++;
6924                                         idx++;
6925                                         rmesc++;
6926                                 }
6927                         } else {
6928                                 idx = loc;
6929                         }
6930
6931                         //bb_error_msg("repl:'%s'", repl);
6932                         for (loc = (char*)repl; *loc; loc++) {
6933                                 char *restart_detect = stackblock();
6934                                 if (quotes && *loc == '\\') {
6935                                         STPUTC(CTLESC, expdest);
6936                                         len++;
6937                                 }
6938                                 STPUTC(*loc, expdest);
6939                                 if (stackblock() != restart_detect)
6940                                         goto restart;
6941                                 len++;
6942                         }
6943
6944                         if (subtype == VSREPLACE) {
6945                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6946                                 while (*idx) {
6947                                         char *restart_detect = stackblock();
6948                                         STPUTC(*idx, expdest);
6949                                         if (stackblock() != restart_detect)
6950                                                 goto restart;
6951                                         len++;
6952                                         idx++;
6953                                 }
6954                                 break;
6955                         }
6956                 }
6957
6958                 /* We've put the replaced text into a buffer at workloc, now
6959                  * move it to the right place and adjust the stack.
6960                  */
6961                 STPUTC('\0', expdest);
6962                 startp = (char *)stackblock() + startloc;
6963                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6964                 //bb_error_msg("startp:'%s'", startp);
6965                 amount = expdest - (startp + len);
6966                 STADJUST(-amount, expdest);
6967                 return startp;
6968         }
6969 #endif /* BASH_PATTERN_SUBST */
6970
6971         subtype -= VSTRIMRIGHT;
6972 #if DEBUG
6973         if (subtype < 0 || subtype > 7)
6974                 abort();
6975 #endif
6976         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6977         zero = subtype >> 1;
6978         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6979         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6980
6981         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6982         if (loc) {
6983                 if (zero) {
6984                         memmove(startp, loc, str - loc);
6985                         loc = startp + (str - loc) - 1;
6986                 }
6987                 *loc = '\0';
6988                 amount = loc - expdest;
6989                 STADJUST(amount, expdest);
6990         }
6991         return loc;
6992 }
6993
6994 /*
6995  * Add the value of a specialized variable to the stack string.
6996  * name parameter (examples):
6997  * ash -c 'echo $1'      name:'1='
6998  * ash -c 'echo $qwe'    name:'qwe='
6999  * ash -c 'echo $$'      name:'$='
7000  * ash -c 'echo ${$}'    name:'$='
7001  * ash -c 'echo ${$##q}' name:'$=q'
7002  * ash -c 'echo ${#$}'   name:'$='
7003  * note: examples with bad shell syntax:
7004  * ash -c 'echo ${#$1}'  name:'$=1'
7005  * ash -c 'echo ${#1#}'  name:'1=#'
7006  */
7007 static NOINLINE ssize_t
7008 varvalue(char *name, int varflags, int flags, int *quotedp)
7009 {
7010         const char *p;
7011         int num;
7012         int i;
7013         ssize_t len = 0;
7014         int sep;
7015         int quoted = *quotedp;
7016         int subtype = varflags & VSTYPE;
7017         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7018         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7019         int syntax;
7020
7021         sep = (flags & EXP_FULL) << CHAR_BIT;
7022         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7023
7024         switch (*name) {
7025         case '$':
7026                 num = rootpid;
7027                 goto numvar;
7028         case '?':
7029                 num = exitstatus;
7030                 goto numvar;
7031         case '#':
7032                 num = shellparam.nparam;
7033                 goto numvar;
7034         case '!':
7035                 num = backgndpid;
7036                 if (num == 0)
7037                         return -1;
7038  numvar:
7039                 len = cvtnum(num);
7040                 goto check_1char_name;
7041         case '-':
7042                 expdest = makestrspace(NOPTS, expdest);
7043                 for (i = NOPTS - 1; i >= 0; i--) {
7044                         if (optlist[i]) {
7045                                 USTPUTC(optletters(i), expdest);
7046                                 len++;
7047                         }
7048                 }
7049  check_1char_name:
7050 #if 0
7051                 /* handles cases similar to ${#$1} */
7052                 if (name[2] != '\0')
7053                         raise_error_syntax("bad substitution");
7054 #endif
7055                 break;
7056         case '@':
7057                 if (quoted && sep)
7058                         goto param;
7059                 /* fall through */
7060         case '*': {
7061                 char **ap;
7062                 char sepc;
7063
7064                 if (quoted)
7065                         sep = 0;
7066                 sep |= ifsset() ? ifsval()[0] : ' ';
7067  param:
7068                 sepc = sep;
7069                 *quotedp = !sepc;
7070                 ap = shellparam.p;
7071                 if (!ap)
7072                         return -1;
7073                 while ((p = *ap++) != NULL) {
7074                         len += strtodest(p, syntax, quotes);
7075
7076                         if (*ap && sep) {
7077                                 len++;
7078                                 memtodest(&sepc, 1, syntax, quotes);
7079                         }
7080                 }
7081                 break;
7082         } /* case '*' */
7083         case '0':
7084         case '1':
7085         case '2':
7086         case '3':
7087         case '4':
7088         case '5':
7089         case '6':
7090         case '7':
7091         case '8':
7092         case '9':
7093                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7094                 if (num < 0 || num > shellparam.nparam)
7095                         return -1;
7096                 p = num ? shellparam.p[num - 1] : arg0;
7097                 goto value;
7098         default:
7099                 /* NB: name has form "VAR=..." */
7100                 p = lookupvar(name);
7101  value:
7102                 if (!p)
7103                         return -1;
7104
7105                 len = strtodest(p, syntax, quotes);
7106 #if ENABLE_UNICODE_SUPPORT
7107                 if (subtype == VSLENGTH && len > 0) {
7108                         reinit_unicode_for_ash();
7109                         if (unicode_status == UNICODE_ON) {
7110                                 STADJUST(-len, expdest);
7111                                 discard = 0;
7112                                 len = unicode_strlen(p);
7113                         }
7114                 }
7115 #endif
7116                 break;
7117         }
7118
7119         if (discard)
7120                 STADJUST(-len, expdest);
7121         return len;
7122 }
7123
7124 /*
7125  * Expand a variable, and return a pointer to the next character in the
7126  * input string.
7127  */
7128 static char *
7129 evalvar(char *p, int flag)
7130 {
7131         char varflags;
7132         char subtype;
7133         int quoted;
7134         char easy;
7135         char *var;
7136         int patloc;
7137         int startloc;
7138         ssize_t varlen;
7139
7140         varflags = (unsigned char) *p++;
7141         subtype = varflags & VSTYPE;
7142
7143         if (!subtype)
7144                 raise_error_syntax("bad substitution");
7145
7146         quoted = flag & EXP_QUOTED;
7147         var = p;
7148         easy = (!quoted || (*var == '@' && shellparam.nparam));
7149         startloc = expdest - (char *)stackblock();
7150         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7151
7152  again:
7153         varlen = varvalue(var, varflags, flag, &quoted);
7154         if (varflags & VSNUL)
7155                 varlen--;
7156
7157         if (subtype == VSPLUS) {
7158                 varlen = -1 - varlen;
7159                 goto vsplus;
7160         }
7161
7162         if (subtype == VSMINUS) {
7163  vsplus:
7164                 if (varlen < 0) {
7165                         argstr(
7166                                 p,
7167                                 flag | EXP_TILDE | EXP_WORD
7168                         );
7169                         goto end;
7170                 }
7171                 goto record;
7172         }
7173
7174         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7175                 if (varlen >= 0)
7176                         goto record;
7177
7178                 subevalvar(p, var, 0, subtype, startloc, varflags,
7179                            flag & ~QUOTES_ESC);
7180                 varflags &= ~VSNUL;
7181                 /*
7182                  * Remove any recorded regions beyond
7183                  * start of variable
7184                  */
7185                 removerecordregions(startloc);
7186                 goto again;
7187         }
7188
7189         if (varlen < 0 && uflag)
7190                 varunset(p, var, 0, 0);
7191
7192         if (subtype == VSLENGTH) {
7193                 cvtnum(varlen > 0 ? varlen : 0);
7194                 goto record;
7195         }
7196
7197         if (subtype == VSNORMAL) {
7198  record:
7199                 if (!easy)
7200                         goto end;
7201                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7202                 goto end;
7203         }
7204
7205 #if DEBUG
7206         switch (subtype) {
7207         case VSTRIMLEFT:
7208         case VSTRIMLEFTMAX:
7209         case VSTRIMRIGHT:
7210         case VSTRIMRIGHTMAX:
7211 #if BASH_SUBSTR
7212         case VSSUBSTR:
7213 #endif
7214 #if BASH_PATTERN_SUBST
7215         case VSREPLACE:
7216         case VSREPLACEALL:
7217 #endif
7218                 break;
7219         default:
7220                 abort();
7221         }
7222 #endif
7223
7224         if (varlen >= 0) {
7225                 /*
7226                  * Terminate the string and start recording the pattern
7227                  * right after it
7228                  */
7229                 STPUTC('\0', expdest);
7230                 patloc = expdest - (char *)stackblock();
7231                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7232                                 startloc, varflags, flag)) {
7233                         int amount = expdest - (
7234                                 (char *)stackblock() + patloc - 1
7235                         );
7236                         STADJUST(-amount, expdest);
7237                 }
7238                 /* Remove any recorded regions beyond start of variable */
7239                 removerecordregions(startloc);
7240                 goto record;
7241         }
7242
7243  end:
7244         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7245                 int nesting = 1;
7246                 for (;;) {
7247                         unsigned char c = *p++;
7248                         if (c == CTLESC)
7249                                 p++;
7250                         else if (c == CTLBACKQ) {
7251                                 if (varlen >= 0)
7252                                         argbackq = argbackq->next;
7253                         } else if (c == CTLVAR) {
7254                                 if ((*p++ & VSTYPE) != VSNORMAL)
7255                                         nesting++;
7256                         } else if (c == CTLENDVAR) {
7257                                 if (--nesting == 0)
7258                                         break;
7259                         }
7260                 }
7261         }
7262         return p;
7263 }
7264
7265 /*
7266  * Add a file name to the list.
7267  */
7268 static void
7269 addfname(const char *name)
7270 {
7271         struct strlist *sp;
7272
7273         sp = stzalloc(sizeof(*sp));
7274         sp->text = sstrdup(name);
7275         *exparg.lastp = sp;
7276         exparg.lastp = &sp->next;
7277 }
7278
7279 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7280 static int
7281 hasmeta(const char *p)
7282 {
7283         static const char chars[] ALIGN1 = {
7284                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7285         };
7286
7287         for (;;) {
7288                 p = strpbrk(p, chars);
7289                 if (!p)
7290                         break;
7291                 switch ((unsigned char) *p) {
7292                 case CTLQUOTEMARK:
7293                         for (;;) {
7294                                 p++;
7295                                 if (*p == CTLQUOTEMARK)
7296                                         break;
7297                                 if (*p == CTLESC)
7298                                         p++;
7299                                 if (*p == '\0') /* huh? */
7300                                         return 0;
7301                         }
7302                         break;
7303                 case '\\':
7304                 case CTLESC:
7305                         p++;
7306                         if (*p == '\0')
7307                                 return 0;
7308                         break;
7309                 case '[':
7310                         if (!strchr(p + 1, ']')) {
7311                                 /* It's not a properly closed [] pattern,
7312                                  * but other metas may follow. Continue checking.
7313                                  * my[file* _is_ globbed by bash
7314                                  * and matches filenames like "my[file1".
7315                                  */
7316                                 break;
7317                         }
7318                         /* fallthrough */
7319                 default:
7320                 /* case '*': */
7321                 /* case '?': */
7322                         return 1;
7323                 }
7324                 p++;
7325         }
7326
7327         return 0;
7328 }
7329
7330 /* If we want to use glob() from libc... */
7331 #if !ENABLE_ASH_INTERNAL_GLOB
7332
7333 /* Add the result of glob() to the list */
7334 static void
7335 addglob(const glob_t *pglob)
7336 {
7337         char **p = pglob->gl_pathv;
7338
7339         do {
7340                 addfname(*p);
7341         } while (*++p);
7342 }
7343 static void
7344 expandmeta(struct strlist *str /*, int flag*/)
7345 {
7346         /* TODO - EXP_REDIR */
7347
7348         while (str) {
7349                 char *p;
7350                 glob_t pglob;
7351                 int i;
7352
7353                 if (fflag)
7354                         goto nometa;
7355
7356                 if (!hasmeta(str->text))
7357                         goto nometa;
7358
7359                 INT_OFF;
7360                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7361 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7362 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7363 //
7364 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7365 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7366 // Which means you need to unescape the string, right? Not so fast:
7367 // if there _is_ a file named "file\?" (with backslash), it is returned
7368 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7369 // You DON'T KNOW by looking at the result whether you need to unescape it.
7370 //
7371 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7372 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7373 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7374 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7375 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7376 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7377                 i = glob(p, 0, NULL, &pglob);
7378                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7379                 if (p != str->text)
7380                         free(p);
7381                 switch (i) {
7382                 case 0:
7383 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7384                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7385                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7386                                 goto nometa2;
7387 #endif
7388                         addglob(&pglob);
7389                         globfree(&pglob);
7390                         INT_ON;
7391                         break;
7392                 case GLOB_NOMATCH:
7393  //nometa2:
7394                         globfree(&pglob);
7395                         INT_ON;
7396  nometa:
7397                         *exparg.lastp = str;
7398                         rmescapes(str->text, 0);
7399                         exparg.lastp = &str->next;
7400                         break;
7401                 default:        /* GLOB_NOSPACE */
7402                         globfree(&pglob);
7403                         INT_ON;
7404                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7405                 }
7406                 str = str->next;
7407         }
7408 }
7409
7410 #else
7411 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7412
7413 /*
7414  * Do metacharacter (i.e. *, ?, [...]) expansion.
7415  */
7416 static void
7417 expmeta(char *expdir, char *enddir, char *name)
7418 {
7419         char *p;
7420         const char *cp;
7421         char *start;
7422         char *endname;
7423         int metaflag;
7424         struct stat statb;
7425         DIR *dirp;
7426         struct dirent *dp;
7427         int atend;
7428         int matchdot;
7429         int esc;
7430
7431         metaflag = 0;
7432         start = name;
7433         for (p = name; esc = 0, *p; p += esc + 1) {
7434                 if (*p == '*' || *p == '?')
7435                         metaflag = 1;
7436                 else if (*p == '[') {
7437                         char *q = p + 1;
7438                         if (*q == '!')
7439                                 q++;
7440                         for (;;) {
7441                                 if (*q == '\\')
7442                                         q++;
7443                                 if (*q == '/' || *q == '\0')
7444                                         break;
7445                                 if (*++q == ']') {
7446                                         metaflag = 1;
7447                                         break;
7448                                 }
7449                         }
7450                 } else {
7451                         if (*p == '\\')
7452                                 esc++;
7453                         if (p[esc] == '/') {
7454                                 if (metaflag)
7455                                         break;
7456                                 start = p + esc + 1;
7457                         }
7458                 }
7459         }
7460         if (metaflag == 0) {    /* we've reached the end of the file name */
7461                 if (enddir != expdir)
7462                         metaflag++;
7463                 p = name;
7464                 do {
7465                         if (*p == '\\')
7466                                 p++;
7467                         *enddir++ = *p;
7468                 } while (*p++);
7469                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7470                         addfname(expdir);
7471                 return;
7472         }
7473         endname = p;
7474         if (name < start) {
7475                 p = name;
7476                 do {
7477                         if (*p == '\\')
7478                                 p++;
7479                         *enddir++ = *p++;
7480                 } while (p < start);
7481         }
7482         if (enddir == expdir) {
7483                 cp = ".";
7484         } else if (enddir == expdir + 1 && *expdir == '/') {
7485                 cp = "/";
7486         } else {
7487                 cp = expdir;
7488                 enddir[-1] = '\0';
7489         }
7490         dirp = opendir(cp);
7491         if (dirp == NULL)
7492                 return;
7493         if (enddir != expdir)
7494                 enddir[-1] = '/';
7495         if (*endname == 0) {
7496                 atend = 1;
7497         } else {
7498                 atend = 0;
7499                 *endname = '\0';
7500                 endname += esc + 1;
7501         }
7502         matchdot = 0;
7503         p = start;
7504         if (*p == '\\')
7505                 p++;
7506         if (*p == '.')
7507                 matchdot++;
7508         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7509                 if (dp->d_name[0] == '.' && !matchdot)
7510                         continue;
7511                 if (pmatch(start, dp->d_name)) {
7512                         if (atend) {
7513                                 strcpy(enddir, dp->d_name);
7514                                 addfname(expdir);
7515                         } else {
7516                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7517                                         continue;
7518                                 p[-1] = '/';
7519                                 expmeta(expdir, p, endname);
7520                         }
7521                 }
7522         }
7523         closedir(dirp);
7524         if (!atend)
7525                 endname[-esc - 1] = esc ? '\\' : '/';
7526 }
7527
7528 static struct strlist *
7529 msort(struct strlist *list, int len)
7530 {
7531         struct strlist *p, *q = NULL;
7532         struct strlist **lpp;
7533         int half;
7534         int n;
7535
7536         if (len <= 1)
7537                 return list;
7538         half = len >> 1;
7539         p = list;
7540         for (n = half; --n >= 0;) {
7541                 q = p;
7542                 p = p->next;
7543         }
7544         q->next = NULL;                 /* terminate first half of list */
7545         q = msort(list, half);          /* sort first half of list */
7546         p = msort(p, len - half);               /* sort second half */
7547         lpp = &list;
7548         for (;;) {
7549 #if ENABLE_LOCALE_SUPPORT
7550                 if (strcoll(p->text, q->text) < 0)
7551 #else
7552                 if (strcmp(p->text, q->text) < 0)
7553 #endif
7554                                                 {
7555                         *lpp = p;
7556                         lpp = &p->next;
7557                         p = *lpp;
7558                         if (p == NULL) {
7559                                 *lpp = q;
7560                                 break;
7561                         }
7562                 } else {
7563                         *lpp = q;
7564                         lpp = &q->next;
7565                         q = *lpp;
7566                         if (q == NULL) {
7567                                 *lpp = p;
7568                                 break;
7569                         }
7570                 }
7571         }
7572         return list;
7573 }
7574
7575 /*
7576  * Sort the results of file name expansion.  It calculates the number of
7577  * strings to sort and then calls msort (short for merge sort) to do the
7578  * work.
7579  */
7580 static struct strlist *
7581 expsort(struct strlist *str)
7582 {
7583         int len;
7584         struct strlist *sp;
7585
7586         len = 0;
7587         for (sp = str; sp; sp = sp->next)
7588                 len++;
7589         return msort(str, len);
7590 }
7591
7592 static void
7593 expandmeta(struct strlist *str /*, int flag*/)
7594 {
7595         /* TODO - EXP_REDIR */
7596
7597         while (str) {
7598                 char *expdir;
7599                 struct strlist **savelastp;
7600                 struct strlist *sp;
7601                 char *p;
7602
7603                 if (fflag)
7604                         goto nometa;
7605                 if (!hasmeta(str->text))
7606                         goto nometa;
7607                 savelastp = exparg.lastp;
7608
7609                 INT_OFF;
7610                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7611                 {
7612                         int i = strlen(str->text);
7613 //BUGGY estimation of how long expanded name can be
7614                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7615                 }
7616                 expmeta(expdir, expdir, p);
7617                 free(expdir);
7618                 if (p != str->text)
7619                         free(p);
7620                 INT_ON;
7621                 if (exparg.lastp == savelastp) {
7622                         /*
7623                          * no matches
7624                          */
7625  nometa:
7626                         *exparg.lastp = str;
7627                         rmescapes(str->text, 0);
7628                         exparg.lastp = &str->next;
7629                 } else {
7630                         *exparg.lastp = NULL;
7631                         *savelastp = sp = expsort(*savelastp);
7632                         while (sp->next != NULL)
7633                                 sp = sp->next;
7634                         exparg.lastp = &sp->next;
7635                 }
7636                 str = str->next;
7637         }
7638 }
7639 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7640
7641 /*
7642  * Perform variable substitution and command substitution on an argument,
7643  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7644  * perform splitting and file name expansion.  When arglist is NULL, perform
7645  * here document expansion.
7646  */
7647 static void
7648 expandarg(union node *arg, struct arglist *arglist, int flag)
7649 {
7650         struct strlist *sp;
7651         char *p;
7652
7653         argbackq = arg->narg.backquote;
7654         STARTSTACKSTR(expdest);
7655         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7656         argstr(arg->narg.text, flag);
7657         p = _STPUTC('\0', expdest);
7658         expdest = p - 1;
7659         if (arglist == NULL) {
7660                 /* here document expanded */
7661                 goto out;
7662         }
7663         p = grabstackstr(p);
7664         TRACE(("expandarg: p:'%s'\n", p));
7665         exparg.lastp = &exparg.list;
7666         /*
7667          * TODO - EXP_REDIR
7668          */
7669         if (flag & EXP_FULL) {
7670                 ifsbreakup(p, &exparg);
7671                 *exparg.lastp = NULL;
7672                 exparg.lastp = &exparg.list;
7673                 expandmeta(exparg.list /*, flag*/);
7674         } else {
7675                 sp = stzalloc(sizeof(*sp));
7676                 sp->text = p;
7677                 *exparg.lastp = sp;
7678                 exparg.lastp = &sp->next;
7679         }
7680         *exparg.lastp = NULL;
7681         if (exparg.list) {
7682                 *arglist->lastp = exparg.list;
7683                 arglist->lastp = exparg.lastp;
7684         }
7685
7686  out:
7687         ifsfree();
7688 }
7689
7690 /*
7691  * Expand shell variables and backquotes inside a here document.
7692  */
7693 static void
7694 expandhere(union node *arg, int fd)
7695 {
7696         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7697         full_write(fd, stackblock(), expdest - (char *)stackblock());
7698 }
7699
7700 /*
7701  * Returns true if the pattern matches the string.
7702  */
7703 static int
7704 patmatch(char *pattern, const char *string)
7705 {
7706         char *p = preglob(pattern, 0);
7707         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7708         return pmatch(p, string);
7709 }
7710
7711 /*
7712  * See if a pattern matches in a case statement.
7713  */
7714 static int
7715 casematch(union node *pattern, char *val)
7716 {
7717         struct stackmark smark;
7718         int result;
7719
7720         setstackmark(&smark);
7721         argbackq = pattern->narg.backquote;
7722         STARTSTACKSTR(expdest);
7723         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7724         STACKSTRNUL(expdest);
7725         ifsfree();
7726         result = patmatch(stackblock(), val);
7727         popstackmark(&smark);
7728         return result;
7729 }
7730
7731
7732 /* ============ find_command */
7733
7734 struct builtincmd {
7735         const char *name;
7736         int (*builtin)(int, char **) FAST_FUNC;
7737         /* unsigned flags; */
7738 };
7739 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7740 /* "regular" builtins always take precedence over commands,
7741  * regardless of PATH=....%builtin... position */
7742 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7743 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7744
7745 struct cmdentry {
7746         smallint cmdtype;       /* CMDxxx */
7747         union param {
7748                 int index;
7749                 /* index >= 0 for commands without path (slashes) */
7750                 /* (TODO: what exactly does the value mean? PATH position?) */
7751                 /* index == -1 for commands with slashes */
7752                 /* index == (-2 - applet_no) for NOFORK applets */
7753                 const struct builtincmd *cmd;
7754                 struct funcnode *func;
7755         } u;
7756 };
7757 /* values of cmdtype */
7758 #define CMDUNKNOWN      -1      /* no entry in table for command */
7759 #define CMDNORMAL       0       /* command is an executable program */
7760 #define CMDFUNCTION     1       /* command is a shell function */
7761 #define CMDBUILTIN      2       /* command is a shell builtin */
7762
7763 /* action to find_command() */
7764 #define DO_ERR          0x01    /* prints errors */
7765 #define DO_ABS          0x02    /* checks absolute paths */
7766 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7767 #define DO_ALTPATH      0x08    /* using alternate path */
7768 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7769
7770 static void find_command(char *, struct cmdentry *, int, const char *);
7771
7772
7773 /* ============ Hashing commands */
7774
7775 /*
7776  * When commands are first encountered, they are entered in a hash table.
7777  * This ensures that a full path search will not have to be done for them
7778  * on each invocation.
7779  *
7780  * We should investigate converting to a linear search, even though that
7781  * would make the command name "hash" a misnomer.
7782  */
7783
7784 struct tblentry {
7785         struct tblentry *next;  /* next entry in hash chain */
7786         union param param;      /* definition of builtin function */
7787         smallint cmdtype;       /* CMDxxx */
7788         char rehash;            /* if set, cd done since entry created */
7789         char cmdname[1];        /* name of command */
7790 };
7791
7792 static struct tblentry **cmdtable;
7793 #define INIT_G_cmdtable() do { \
7794         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7795 } while (0)
7796
7797 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7798
7799
7800 static void
7801 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7802 {
7803 #if ENABLE_FEATURE_SH_STANDALONE
7804         if (applet_no >= 0) {
7805                 if (APPLET_IS_NOEXEC(applet_no)) {
7806                         clearenv();
7807                         while (*envp)
7808                                 putenv(*envp++);
7809                         popredir(/*drop:*/ 1);
7810                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7811                 }
7812                 /* re-exec ourselves with the new arguments */
7813                 execve(bb_busybox_exec_path, argv, envp);
7814                 /* If they called chroot or otherwise made the binary no longer
7815                  * executable, fall through */
7816         }
7817 #endif
7818
7819  repeat:
7820 #ifdef SYSV
7821         do {
7822                 execve(cmd, argv, envp);
7823         } while (errno == EINTR);
7824 #else
7825         execve(cmd, argv, envp);
7826 #endif
7827         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7828                 /* Run "cmd" as a shell script:
7829                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7830                  * "If the execve() function fails with ENOEXEC, the shell
7831                  * shall execute a command equivalent to having a shell invoked
7832                  * with the command name as its first operand,
7833                  * with any remaining arguments passed to the new shell"
7834                  *
7835                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7836                  * just call ourselves.
7837                  *
7838                  * Note that bash reads ~80 chars of the file, and if it sees
7839                  * a zero byte before it sees newline, it doesn't try to
7840                  * interpret it, but fails with "cannot execute binary file"
7841                  * message and exit code 126. For one, this prevents attempts
7842                  * to interpret foreign ELF binaries as shell scripts.
7843                  */
7844                 argv[0] = (char*) cmd;
7845                 cmd = bb_busybox_exec_path;
7846                 /* NB: this is only possible because all callers of shellexec()
7847                  * ensure that the argv[-1] slot exists!
7848                  */
7849                 argv--;
7850                 argv[0] = (char*) "ash";
7851                 goto repeat;
7852         }
7853 }
7854
7855 /*
7856  * Exec a program.  Never returns.  If you change this routine, you may
7857  * have to change the find_command routine as well.
7858  * argv[-1] must exist and be writable! See tryexec() for why.
7859  */
7860 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7861 static void shellexec(char *prog, char **argv, const char *path, int idx)
7862 {
7863         char *cmdname;
7864         int e;
7865         char **envp;
7866         int exerrno;
7867         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7868
7869         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7870         if (strchr(prog, '/') != NULL
7871 #if ENABLE_FEATURE_SH_STANDALONE
7872          || (applet_no = find_applet_by_name(prog)) >= 0
7873 #endif
7874         ) {
7875                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7876                 if (applet_no >= 0) {
7877                         /* We tried execing ourself, but it didn't work.
7878                          * Maybe /proc/self/exe doesn't exist?
7879                          * Try $PATH search.
7880                          */
7881                         goto try_PATH;
7882                 }
7883                 e = errno;
7884         } else {
7885  try_PATH:
7886                 e = ENOENT;
7887                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7888                         if (--idx < 0 && pathopt == NULL) {
7889                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7890                                 if (errno != ENOENT && errno != ENOTDIR)
7891                                         e = errno;
7892                         }
7893                         stunalloc(cmdname);
7894                 }
7895         }
7896
7897         /* Map to POSIX errors */
7898         switch (e) {
7899         case EACCES:
7900                 exerrno = 126;
7901                 break;
7902         case ENOENT:
7903                 exerrno = 127;
7904                 break;
7905         default:
7906                 exerrno = 2;
7907                 break;
7908         }
7909         exitstatus = exerrno;
7910         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7911                 prog, e, suppress_int));
7912         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7913         /* NOTREACHED */
7914 }
7915
7916 static void
7917 printentry(struct tblentry *cmdp)
7918 {
7919         int idx;
7920         const char *path;
7921         char *name;
7922
7923         idx = cmdp->param.index;
7924         path = pathval();
7925         do {
7926                 name = path_advance(&path, cmdp->cmdname);
7927                 stunalloc(name);
7928         } while (--idx >= 0);
7929         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7930 }
7931
7932 /*
7933  * Clear out command entries.  The argument specifies the first entry in
7934  * PATH which has changed.
7935  */
7936 static void
7937 clearcmdentry(int firstchange)
7938 {
7939         struct tblentry **tblp;
7940         struct tblentry **pp;
7941         struct tblentry *cmdp;
7942
7943         INT_OFF;
7944         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7945                 pp = tblp;
7946                 while ((cmdp = *pp) != NULL) {
7947                         if ((cmdp->cmdtype == CMDNORMAL &&
7948                              cmdp->param.index >= firstchange)
7949                          || (cmdp->cmdtype == CMDBUILTIN &&
7950                              builtinloc >= firstchange)
7951                         ) {
7952                                 *pp = cmdp->next;
7953                                 free(cmdp);
7954                         } else {
7955                                 pp = &cmdp->next;
7956                         }
7957                 }
7958         }
7959         INT_ON;
7960 }
7961
7962 /*
7963  * Locate a command in the command hash table.  If "add" is nonzero,
7964  * add the command to the table if it is not already present.  The
7965  * variable "lastcmdentry" is set to point to the address of the link
7966  * pointing to the entry, so that delete_cmd_entry can delete the
7967  * entry.
7968  *
7969  * Interrupts must be off if called with add != 0.
7970  */
7971 static struct tblentry **lastcmdentry;
7972
7973 static struct tblentry *
7974 cmdlookup(const char *name, int add)
7975 {
7976         unsigned int hashval;
7977         const char *p;
7978         struct tblentry *cmdp;
7979         struct tblentry **pp;
7980
7981         p = name;
7982         hashval = (unsigned char)*p << 4;
7983         while (*p)
7984                 hashval += (unsigned char)*p++;
7985         hashval &= 0x7FFF;
7986         pp = &cmdtable[hashval % CMDTABLESIZE];
7987         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7988                 if (strcmp(cmdp->cmdname, name) == 0)
7989                         break;
7990                 pp = &cmdp->next;
7991         }
7992         if (add && cmdp == NULL) {
7993                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7994                                 + strlen(name)
7995                                 /* + 1 - already done because
7996                                  * tblentry::cmdname is char[1] */);
7997                 /*cmdp->next = NULL; - ckzalloc did it */
7998                 cmdp->cmdtype = CMDUNKNOWN;
7999                 strcpy(cmdp->cmdname, name);
8000         }
8001         lastcmdentry = pp;
8002         return cmdp;
8003 }
8004
8005 /*
8006  * Delete the command entry returned on the last lookup.
8007  */
8008 static void
8009 delete_cmd_entry(void)
8010 {
8011         struct tblentry *cmdp;
8012
8013         INT_OFF;
8014         cmdp = *lastcmdentry;
8015         *lastcmdentry = cmdp->next;
8016         if (cmdp->cmdtype == CMDFUNCTION)
8017                 freefunc(cmdp->param.func);
8018         free(cmdp);
8019         INT_ON;
8020 }
8021
8022 /*
8023  * Add a new command entry, replacing any existing command entry for
8024  * the same name - except special builtins.
8025  */
8026 static void
8027 addcmdentry(char *name, struct cmdentry *entry)
8028 {
8029         struct tblentry *cmdp;
8030
8031         cmdp = cmdlookup(name, 1);
8032         if (cmdp->cmdtype == CMDFUNCTION) {
8033                 freefunc(cmdp->param.func);
8034         }
8035         cmdp->cmdtype = entry->cmdtype;
8036         cmdp->param = entry->u;
8037         cmdp->rehash = 0;
8038 }
8039
8040 static int FAST_FUNC
8041 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8042 {
8043         struct tblentry **pp;
8044         struct tblentry *cmdp;
8045         int c;
8046         struct cmdentry entry;
8047         char *name;
8048
8049         if (nextopt("r") != '\0') {
8050                 clearcmdentry(0);
8051                 return 0;
8052         }
8053
8054         if (*argptr == NULL) {
8055                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8056                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8057                                 if (cmdp->cmdtype == CMDNORMAL)
8058                                         printentry(cmdp);
8059                         }
8060                 }
8061                 return 0;
8062         }
8063
8064         c = 0;
8065         while ((name = *argptr) != NULL) {
8066                 cmdp = cmdlookup(name, 0);
8067                 if (cmdp != NULL
8068                  && (cmdp->cmdtype == CMDNORMAL
8069                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8070                 ) {
8071                         delete_cmd_entry();
8072                 }
8073                 find_command(name, &entry, DO_ERR, pathval());
8074                 if (entry.cmdtype == CMDUNKNOWN)
8075                         c = 1;
8076                 argptr++;
8077         }
8078         return c;
8079 }
8080
8081 /*
8082  * Called when a cd is done.  Marks all commands so the next time they
8083  * are executed they will be rehashed.
8084  */
8085 static void
8086 hashcd(void)
8087 {
8088         struct tblentry **pp;
8089         struct tblentry *cmdp;
8090
8091         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8092                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8093                         if (cmdp->cmdtype == CMDNORMAL
8094                          || (cmdp->cmdtype == CMDBUILTIN
8095                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8096                              && builtinloc > 0)
8097                         ) {
8098                                 cmdp->rehash = 1;
8099                         }
8100                 }
8101         }
8102 }
8103
8104 /*
8105  * Fix command hash table when PATH changed.
8106  * Called before PATH is changed.  The argument is the new value of PATH;
8107  * pathval() still returns the old value at this point.
8108  * Called with interrupts off.
8109  */
8110 static void FAST_FUNC
8111 changepath(const char *new)
8112 {
8113         const char *old;
8114         int firstchange;
8115         int idx;
8116         int idx_bltin;
8117
8118         old = pathval();
8119         firstchange = 9999;     /* assume no change */
8120         idx = 0;
8121         idx_bltin = -1;
8122         for (;;) {
8123                 if (*old != *new) {
8124                         firstchange = idx;
8125                         if ((*old == '\0' && *new == ':')
8126                          || (*old == ':' && *new == '\0')
8127                         ) {
8128                                 firstchange++;
8129                         }
8130                         old = new;      /* ignore subsequent differences */
8131                 }
8132                 if (*new == '\0')
8133                         break;
8134                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8135                         idx_bltin = idx;
8136                 if (*new == ':')
8137                         idx++;
8138                 new++;
8139                 old++;
8140         }
8141         if (builtinloc < 0 && idx_bltin >= 0)
8142                 builtinloc = idx_bltin;             /* zap builtins */
8143         if (builtinloc >= 0 && idx_bltin < 0)
8144                 firstchange = 0;
8145         clearcmdentry(firstchange);
8146         builtinloc = idx_bltin;
8147 }
8148 enum {
8149         TEOF,
8150         TNL,
8151         TREDIR,
8152         TWORD,
8153         TSEMI,
8154         TBACKGND,
8155         TAND,
8156         TOR,
8157         TPIPE,
8158         TLP,
8159         TRP,
8160         TENDCASE,
8161         TENDBQUOTE,
8162         TNOT,
8163         TCASE,
8164         TDO,
8165         TDONE,
8166         TELIF,
8167         TELSE,
8168         TESAC,
8169         TFI,
8170         TFOR,
8171 #if BASH_FUNCTION
8172         TFUNCTION,
8173 #endif
8174         TIF,
8175         TIN,
8176         TTHEN,
8177         TUNTIL,
8178         TWHILE,
8179         TBEGIN,
8180         TEND
8181 };
8182 typedef smallint token_id_t;
8183
8184 /* Nth bit indicates if token marks the end of a list */
8185 enum {
8186         tokendlist = 0
8187         /*  0 */ | (1u << TEOF)
8188         /*  1 */ | (0u << TNL)
8189         /*  2 */ | (0u << TREDIR)
8190         /*  3 */ | (0u << TWORD)
8191         /*  4 */ | (0u << TSEMI)
8192         /*  5 */ | (0u << TBACKGND)
8193         /*  6 */ | (0u << TAND)
8194         /*  7 */ | (0u << TOR)
8195         /*  8 */ | (0u << TPIPE)
8196         /*  9 */ | (0u << TLP)
8197         /* 10 */ | (1u << TRP)
8198         /* 11 */ | (1u << TENDCASE)
8199         /* 12 */ | (1u << TENDBQUOTE)
8200         /* 13 */ | (0u << TNOT)
8201         /* 14 */ | (0u << TCASE)
8202         /* 15 */ | (1u << TDO)
8203         /* 16 */ | (1u << TDONE)
8204         /* 17 */ | (1u << TELIF)
8205         /* 18 */ | (1u << TELSE)
8206         /* 19 */ | (1u << TESAC)
8207         /* 20 */ | (1u << TFI)
8208         /* 21 */ | (0u << TFOR)
8209 #if BASH_FUNCTION
8210         /* 22 */ | (0u << TFUNCTION)
8211 #endif
8212         /* 23 */ | (0u << TIF)
8213         /* 24 */ | (0u << TIN)
8214         /* 25 */ | (1u << TTHEN)
8215         /* 26 */ | (0u << TUNTIL)
8216         /* 27 */ | (0u << TWHILE)
8217         /* 28 */ | (0u << TBEGIN)
8218         /* 29 */ | (1u << TEND)
8219         , /* thus far 29 bits used */
8220 };
8221
8222 static const char *const tokname_array[] = {
8223         "end of file",
8224         "newline",
8225         "redirection",
8226         "word",
8227         ";",
8228         "&",
8229         "&&",
8230         "||",
8231         "|",
8232         "(",
8233         ")",
8234         ";;",
8235         "`",
8236 #define KWDOFFSET 13
8237         /* the following are keywords */
8238         "!",
8239         "case",
8240         "do",
8241         "done",
8242         "elif",
8243         "else",
8244         "esac",
8245         "fi",
8246         "for",
8247 #if BASH_FUNCTION
8248         "function",
8249 #endif
8250         "if",
8251         "in",
8252         "then",
8253         "until",
8254         "while",
8255         "{",
8256         "}",
8257 };
8258
8259 /* Wrapper around strcmp for qsort/bsearch/... */
8260 static int
8261 pstrcmp(const void *a, const void *b)
8262 {
8263         return strcmp((char*)a, *(char**)b);
8264 }
8265
8266 static const char *const *
8267 findkwd(const char *s)
8268 {
8269         return bsearch(s, tokname_array + KWDOFFSET,
8270                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8271                         sizeof(tokname_array[0]), pstrcmp);
8272 }
8273
8274 /*
8275  * Locate and print what a word is...
8276  */
8277 static int
8278 describe_command(char *command, const char *path, int describe_command_verbose)
8279 {
8280         struct cmdentry entry;
8281 #if ENABLE_ASH_ALIAS
8282         const struct alias *ap;
8283 #endif
8284
8285         path = path ? path : pathval();
8286
8287         if (describe_command_verbose) {
8288                 out1str(command);
8289         }
8290
8291         /* First look at the keywords */
8292         if (findkwd(command)) {
8293                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8294                 goto out;
8295         }
8296
8297 #if ENABLE_ASH_ALIAS
8298         /* Then look at the aliases */
8299         ap = lookupalias(command, 0);
8300         if (ap != NULL) {
8301                 if (!describe_command_verbose) {
8302                         out1str("alias ");
8303                         printalias(ap);
8304                         return 0;
8305                 }
8306                 out1fmt(" is an alias for %s", ap->val);
8307                 goto out;
8308         }
8309 #endif
8310         /* Brute force */
8311         find_command(command, &entry, DO_ABS, path);
8312
8313         switch (entry.cmdtype) {
8314         case CMDNORMAL: {
8315                 int j = entry.u.index;
8316                 char *p;
8317                 if (j < 0) {
8318                         p = command;
8319                 } else {
8320                         do {
8321                                 p = path_advance(&path, command);
8322                                 stunalloc(p);
8323                         } while (--j >= 0);
8324                 }
8325                 if (describe_command_verbose) {
8326                         out1fmt(" is %s", p);
8327                 } else {
8328                         out1str(p);
8329                 }
8330                 break;
8331         }
8332
8333         case CMDFUNCTION:
8334                 if (describe_command_verbose) {
8335                         out1str(" is a shell function");
8336                 } else {
8337                         out1str(command);
8338                 }
8339                 break;
8340
8341         case CMDBUILTIN:
8342                 if (describe_command_verbose) {
8343                         out1fmt(" is a %sshell builtin",
8344                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8345                                         "special " : nullstr
8346                         );
8347                 } else {
8348                         out1str(command);
8349                 }
8350                 break;
8351
8352         default:
8353                 if (describe_command_verbose) {
8354                         out1str(": not found\n");
8355                 }
8356                 return 127;
8357         }
8358  out:
8359         out1str("\n");
8360         return 0;
8361 }
8362
8363 static int FAST_FUNC
8364 typecmd(int argc UNUSED_PARAM, char **argv)
8365 {
8366         int i = 1;
8367         int err = 0;
8368         int verbose = 1;
8369
8370         /* type -p ... ? (we don't bother checking for 'p') */
8371         if (argv[1] && argv[1][0] == '-') {
8372                 i++;
8373                 verbose = 0;
8374         }
8375         while (argv[i]) {
8376                 err |= describe_command(argv[i++], NULL, verbose);
8377         }
8378         return err;
8379 }
8380
8381 #if ENABLE_ASH_CMDCMD
8382 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8383 static char **
8384 parse_command_args(char **argv, const char **path)
8385 {
8386         char *cp, c;
8387
8388         for (;;) {
8389                 cp = *++argv;
8390                 if (!cp)
8391                         return NULL;
8392                 if (*cp++ != '-')
8393                         break;
8394                 c = *cp++;
8395                 if (!c)
8396                         break;
8397                 if (c == '-' && !*cp) {
8398                         if (!*++argv)
8399                                 return NULL;
8400                         break;
8401                 }
8402                 do {
8403                         switch (c) {
8404                         case 'p':
8405                                 *path = bb_default_path;
8406                                 break;
8407                         default:
8408                                 /* run 'typecmd' for other options */
8409                                 return NULL;
8410                         }
8411                         c = *cp++;
8412                 } while (c);
8413         }
8414         return argv;
8415 }
8416
8417 static int FAST_FUNC
8418 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8419 {
8420         char *cmd;
8421         int c;
8422         enum {
8423                 VERIFY_BRIEF = 1,
8424                 VERIFY_VERBOSE = 2,
8425         } verify = 0;
8426         const char *path = NULL;
8427
8428         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8429          * never reaches this function.
8430          */
8431
8432         while ((c = nextopt("pvV")) != '\0')
8433                 if (c == 'V')
8434                         verify |= VERIFY_VERBOSE;
8435                 else if (c == 'v')
8436                         /*verify |= VERIFY_BRIEF*/;
8437 #if DEBUG
8438                 else if (c != 'p')
8439                         abort();
8440 #endif
8441                 else
8442                         path = bb_default_path;
8443
8444         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8445         cmd = *argptr;
8446         if (/*verify && */ cmd)
8447                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8448
8449         return 0;
8450 }
8451 #endif
8452
8453
8454 /*static int funcblocksize;     // size of structures in function */
8455 /*static int funcstringsize;    // size of strings in node */
8456 static void *funcblock;         /* block to allocate function from */
8457 static char *funcstring_end;    /* end of block to allocate strings from */
8458
8459 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8460         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8461         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8462         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8463         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8464         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8465         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8466         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8467         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8468         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8469         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8470         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8471         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8472         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8473         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8474         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8475         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8476         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8477 #if BASH_REDIR_OUTPUT
8478         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8479 #endif
8480         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8481         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8482         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8483         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8484         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8485         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8486         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8487         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8488         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8489 };
8490
8491 static int calcsize(int funcblocksize, union node *n);
8492
8493 static int
8494 sizenodelist(int funcblocksize, struct nodelist *lp)
8495 {
8496         while (lp) {
8497                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8498                 funcblocksize = calcsize(funcblocksize, lp->n);
8499                 lp = lp->next;
8500         }
8501         return funcblocksize;
8502 }
8503
8504 static int
8505 calcsize(int funcblocksize, union node *n)
8506 {
8507         if (n == NULL)
8508                 return funcblocksize;
8509         funcblocksize += nodesize[n->type];
8510         switch (n->type) {
8511         case NCMD:
8512                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8513                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8514                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8515                 break;
8516         case NPIPE:
8517                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8518                 break;
8519         case NREDIR:
8520         case NBACKGND:
8521         case NSUBSHELL:
8522                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8523                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8524                 break;
8525         case NAND:
8526         case NOR:
8527         case NSEMI:
8528         case NWHILE:
8529         case NUNTIL:
8530                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8531                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8532                 break;
8533         case NIF:
8534                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8535                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8536                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8537                 break;
8538         case NFOR:
8539                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8540                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8541                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8542                 break;
8543         case NCASE:
8544                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8545                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8546                 break;
8547         case NCLIST:
8548                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8549                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8550                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8551                 break;
8552         case NDEFUN:
8553         case NARG:
8554                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8555                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8556                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8557                 break;
8558         case NTO:
8559 #if BASH_REDIR_OUTPUT
8560         case NTO2:
8561 #endif
8562         case NCLOBBER:
8563         case NFROM:
8564         case NFROMTO:
8565         case NAPPEND:
8566                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8567                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8568                 break;
8569         case NTOFD:
8570         case NFROMFD:
8571                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8572                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8573         break;
8574         case NHERE:
8575         case NXHERE:
8576                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8577                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8578                 break;
8579         case NNOT:
8580                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8581                 break;
8582         };
8583         return funcblocksize;
8584 }
8585
8586 static char *
8587 nodeckstrdup(char *s)
8588 {
8589         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8590         return strcpy(funcstring_end, s);
8591 }
8592
8593 static union node *copynode(union node *);
8594
8595 static struct nodelist *
8596 copynodelist(struct nodelist *lp)
8597 {
8598         struct nodelist *start;
8599         struct nodelist **lpp;
8600
8601         lpp = &start;
8602         while (lp) {
8603                 *lpp = funcblock;
8604                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8605                 (*lpp)->n = copynode(lp->n);
8606                 lp = lp->next;
8607                 lpp = &(*lpp)->next;
8608         }
8609         *lpp = NULL;
8610         return start;
8611 }
8612
8613 static union node *
8614 copynode(union node *n)
8615 {
8616         union node *new;
8617
8618         if (n == NULL)
8619                 return NULL;
8620         new = funcblock;
8621         funcblock = (char *) funcblock + nodesize[n->type];
8622
8623         switch (n->type) {
8624         case NCMD:
8625                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8626                 new->ncmd.args = copynode(n->ncmd.args);
8627                 new->ncmd.assign = copynode(n->ncmd.assign);
8628                 break;
8629         case NPIPE:
8630                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8631                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8632                 break;
8633         case NREDIR:
8634         case NBACKGND:
8635         case NSUBSHELL:
8636                 new->nredir.redirect = copynode(n->nredir.redirect);
8637                 new->nredir.n = copynode(n->nredir.n);
8638                 break;
8639         case NAND:
8640         case NOR:
8641         case NSEMI:
8642         case NWHILE:
8643         case NUNTIL:
8644                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8645                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8646                 break;
8647         case NIF:
8648                 new->nif.elsepart = copynode(n->nif.elsepart);
8649                 new->nif.ifpart = copynode(n->nif.ifpart);
8650                 new->nif.test = copynode(n->nif.test);
8651                 break;
8652         case NFOR:
8653                 new->nfor.var = nodeckstrdup(n->nfor.var);
8654                 new->nfor.body = copynode(n->nfor.body);
8655                 new->nfor.args = copynode(n->nfor.args);
8656                 break;
8657         case NCASE:
8658                 new->ncase.cases = copynode(n->ncase.cases);
8659                 new->ncase.expr = copynode(n->ncase.expr);
8660                 break;
8661         case NCLIST:
8662                 new->nclist.body = copynode(n->nclist.body);
8663                 new->nclist.pattern = copynode(n->nclist.pattern);
8664                 new->nclist.next = copynode(n->nclist.next);
8665                 break;
8666         case NDEFUN:
8667         case NARG:
8668                 new->narg.backquote = copynodelist(n->narg.backquote);
8669                 new->narg.text = nodeckstrdup(n->narg.text);
8670                 new->narg.next = copynode(n->narg.next);
8671                 break;
8672         case NTO:
8673 #if BASH_REDIR_OUTPUT
8674         case NTO2:
8675 #endif
8676         case NCLOBBER:
8677         case NFROM:
8678         case NFROMTO:
8679         case NAPPEND:
8680                 new->nfile.fname = copynode(n->nfile.fname);
8681                 new->nfile.fd = n->nfile.fd;
8682                 new->nfile.next = copynode(n->nfile.next);
8683                 break;
8684         case NTOFD:
8685         case NFROMFD:
8686                 new->ndup.vname = copynode(n->ndup.vname);
8687                 new->ndup.dupfd = n->ndup.dupfd;
8688                 new->ndup.fd = n->ndup.fd;
8689                 new->ndup.next = copynode(n->ndup.next);
8690                 break;
8691         case NHERE:
8692         case NXHERE:
8693                 new->nhere.doc = copynode(n->nhere.doc);
8694                 new->nhere.fd = n->nhere.fd;
8695                 new->nhere.next = copynode(n->nhere.next);
8696                 break;
8697         case NNOT:
8698                 new->nnot.com = copynode(n->nnot.com);
8699                 break;
8700         };
8701         new->type = n->type;
8702         return new;
8703 }
8704
8705 /*
8706  * Make a copy of a parse tree.
8707  */
8708 static struct funcnode *
8709 copyfunc(union node *n)
8710 {
8711         struct funcnode *f;
8712         size_t blocksize;
8713
8714         /*funcstringsize = 0;*/
8715         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8716         f = ckzalloc(blocksize /* + funcstringsize */);
8717         funcblock = (char *) f + offsetof(struct funcnode, n);
8718         funcstring_end = (char *) f + blocksize;
8719         copynode(n);
8720         /* f->count = 0; - ckzalloc did it */
8721         return f;
8722 }
8723
8724 /*
8725  * Define a shell function.
8726  */
8727 static void
8728 defun(union node *func)
8729 {
8730         struct cmdentry entry;
8731
8732         INT_OFF;
8733         entry.cmdtype = CMDFUNCTION;
8734         entry.u.func = copyfunc(func);
8735         addcmdentry(func->narg.text, &entry);
8736         INT_ON;
8737 }
8738
8739 /* Reasons for skipping commands (see comment on breakcmd routine) */
8740 #define SKIPBREAK      (1 << 0)
8741 #define SKIPCONT       (1 << 1)
8742 #define SKIPFUNC       (1 << 2)
8743 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8744 static int skipcount;           /* number of levels to skip */
8745 static int funcnest;            /* depth of function calls */
8746 static int loopnest;            /* current loop nesting level */
8747
8748 /* Forward decl way out to parsing code - dotrap needs it */
8749 static int evalstring(char *s, int flags);
8750
8751 /* Called to execute a trap.
8752  * Single callsite - at the end of evaltree().
8753  * If we return non-zero, evaltree raises EXEXIT exception.
8754  *
8755  * Perhaps we should avoid entering new trap handlers
8756  * while we are executing a trap handler. [is it a TODO?]
8757  */
8758 static void
8759 dotrap(void)
8760 {
8761         uint8_t *g;
8762         int sig;
8763         uint8_t last_status;
8764
8765         if (!pending_sig)
8766                 return;
8767
8768         last_status = exitstatus;
8769         pending_sig = 0;
8770         barrier();
8771
8772         TRACE(("dotrap entered\n"));
8773         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8774                 char *p;
8775
8776                 if (!*g)
8777                         continue;
8778
8779                 if (evalskip) {
8780                         pending_sig = sig;
8781                         break;
8782                 }
8783
8784                 p = trap[sig];
8785                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8786                  * don't upset it by resetting gotsig[SIGINT-1] */
8787                 if (sig == SIGINT && !p)
8788                         continue;
8789
8790                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8791                 *g = 0;
8792                 if (!p)
8793                         continue;
8794                 evalstring(p, 0);
8795         }
8796         exitstatus = last_status;
8797         TRACE(("dotrap returns\n"));
8798 }
8799
8800 /* forward declarations - evaluation is fairly recursive business... */
8801 static int evalloop(union node *, int);
8802 static int evalfor(union node *, int);
8803 static int evalcase(union node *, int);
8804 static int evalsubshell(union node *, int);
8805 static void expredir(union node *);
8806 static int evalpipe(union node *, int);
8807 static int evalcommand(union node *, int);
8808 static int evalbltin(const struct builtincmd *, int, char **, int);
8809 static void prehash(union node *);
8810
8811 /*
8812  * Evaluate a parse tree.  The value is left in the global variable
8813  * exitstatus.
8814  */
8815 static int
8816 evaltree(union node *n, int flags)
8817 {
8818         int checkexit = 0;
8819         int (*evalfn)(union node *, int);
8820         int status = 0;
8821
8822         if (n == NULL) {
8823                 TRACE(("evaltree(NULL) called\n"));
8824                 goto out;
8825         }
8826         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8827
8828         dotrap();
8829
8830         switch (n->type) {
8831         default:
8832 #if DEBUG
8833                 out1fmt("Node type = %d\n", n->type);
8834                 fflush_all();
8835                 break;
8836 #endif
8837         case NNOT:
8838                 status = !evaltree(n->nnot.com, EV_TESTED);
8839                 goto setstatus;
8840         case NREDIR:
8841                 expredir(n->nredir.redirect);
8842                 pushredir(n->nredir.redirect);
8843                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8844                 if (!status) {
8845                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8846                 }
8847                 if (n->nredir.redirect)
8848                         popredir(/*drop:*/ 0);
8849                 goto setstatus;
8850         case NCMD:
8851                 evalfn = evalcommand;
8852  checkexit:
8853                 if (eflag && !(flags & EV_TESTED))
8854                         checkexit = ~0;
8855                 goto calleval;
8856         case NFOR:
8857                 evalfn = evalfor;
8858                 goto calleval;
8859         case NWHILE:
8860         case NUNTIL:
8861                 evalfn = evalloop;
8862                 goto calleval;
8863         case NSUBSHELL:
8864         case NBACKGND:
8865                 evalfn = evalsubshell;
8866                 goto checkexit;
8867         case NPIPE:
8868                 evalfn = evalpipe;
8869                 goto checkexit;
8870         case NCASE:
8871                 evalfn = evalcase;
8872                 goto calleval;
8873         case NAND:
8874         case NOR:
8875         case NSEMI: {
8876
8877 #if NAND + 1 != NOR
8878 #error NAND + 1 != NOR
8879 #endif
8880 #if NOR + 1 != NSEMI
8881 #error NOR + 1 != NSEMI
8882 #endif
8883                 unsigned is_or = n->type - NAND;
8884                 status = evaltree(
8885                         n->nbinary.ch1,
8886                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8887                 );
8888                 if ((!status) == is_or || evalskip)
8889                         break;
8890                 n = n->nbinary.ch2;
8891  evaln:
8892                 evalfn = evaltree;
8893  calleval:
8894                 status = evalfn(n, flags);
8895                 goto setstatus;
8896         }
8897         case NIF:
8898                 status = evaltree(n->nif.test, EV_TESTED);
8899                 if (evalskip)
8900                         break;
8901                 if (!status) {
8902                         n = n->nif.ifpart;
8903                         goto evaln;
8904                 }
8905                 if (n->nif.elsepart) {
8906                         n = n->nif.elsepart;
8907                         goto evaln;
8908                 }
8909                 status = 0;
8910                 goto setstatus;
8911         case NDEFUN:
8912                 defun(n);
8913                 /* Not necessary. To test it:
8914                  * "false; f() { qwerty; }; echo $?" should print 0.
8915                  */
8916                 /* status = 0; */
8917  setstatus:
8918                 exitstatus = status;
8919                 break;
8920         }
8921  out:
8922         /* Order of checks below is important:
8923          * signal handlers trigger before exit caused by "set -e".
8924          */
8925         dotrap();
8926
8927         if (checkexit & status)
8928                 raise_exception(EXEXIT);
8929         if (flags & EV_EXIT)
8930                 raise_exception(EXEXIT);
8931
8932         TRACE(("leaving evaltree (no interrupts)\n"));
8933         return exitstatus;
8934 }
8935
8936 static int
8937 skiploop(void)
8938 {
8939         int skip = evalskip;
8940
8941         switch (skip) {
8942         case 0:
8943                 break;
8944         case SKIPBREAK:
8945         case SKIPCONT:
8946                 if (--skipcount <= 0) {
8947                         evalskip = 0;
8948                         break;
8949                 }
8950                 skip = SKIPBREAK;
8951                 break;
8952         }
8953         return skip;
8954 }
8955
8956 static int
8957 evalloop(union node *n, int flags)
8958 {
8959         int skip;
8960         int status;
8961
8962         loopnest++;
8963         status = 0;
8964         flags &= EV_TESTED;
8965         do {
8966                 int i;
8967
8968                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8969                 skip = skiploop();
8970                 if (skip == SKIPFUNC)
8971                         status = i;
8972                 if (skip)
8973                         continue;
8974                 if (n->type != NWHILE)
8975                         i = !i;
8976                 if (i != 0)
8977                         break;
8978                 status = evaltree(n->nbinary.ch2, flags);
8979                 skip = skiploop();
8980         } while (!(skip & ~SKIPCONT));
8981         loopnest--;
8982
8983         return status;
8984 }
8985
8986 static int
8987 evalfor(union node *n, int flags)
8988 {
8989         struct arglist arglist;
8990         union node *argp;
8991         struct strlist *sp;
8992         struct stackmark smark;
8993         int status = 0;
8994
8995         setstackmark(&smark);
8996         arglist.list = NULL;
8997         arglist.lastp = &arglist.list;
8998         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8999                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9000         }
9001         *arglist.lastp = NULL;
9002
9003         loopnest++;
9004         flags &= EV_TESTED;
9005         for (sp = arglist.list; sp; sp = sp->next) {
9006                 setvar0(n->nfor.var, sp->text);
9007                 status = evaltree(n->nfor.body, flags);
9008                 if (skiploop() & ~SKIPCONT)
9009                         break;
9010         }
9011         loopnest--;
9012         popstackmark(&smark);
9013
9014         return status;
9015 }
9016
9017 static int
9018 evalcase(union node *n, int flags)
9019 {
9020         union node *cp;
9021         union node *patp;
9022         struct arglist arglist;
9023         struct stackmark smark;
9024         int status = 0;
9025
9026         setstackmark(&smark);
9027         arglist.list = NULL;
9028         arglist.lastp = &arglist.list;
9029         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9030         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9031                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9032                         if (casematch(patp, arglist.list->text)) {
9033                                 /* Ensure body is non-empty as otherwise
9034                                  * EV_EXIT may prevent us from setting the
9035                                  * exit status.
9036                                  */
9037                                 if (evalskip == 0 && cp->nclist.body) {
9038                                         status = evaltree(cp->nclist.body, flags);
9039                                 }
9040                                 goto out;
9041                         }
9042                 }
9043         }
9044  out:
9045         popstackmark(&smark);
9046
9047         return status;
9048 }
9049
9050 /*
9051  * Kick off a subshell to evaluate a tree.
9052  */
9053 static int
9054 evalsubshell(union node *n, int flags)
9055 {
9056         struct job *jp;
9057         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9058         int status;
9059
9060         expredir(n->nredir.redirect);
9061         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9062                 goto nofork;
9063         INT_OFF;
9064         if (backgnd == FORK_FG)
9065                 get_tty_state();
9066         jp = makejob(/*n,*/ 1);
9067         if (forkshell(jp, n, backgnd) == 0) {
9068                 /* child */
9069                 INT_ON;
9070                 flags |= EV_EXIT;
9071                 if (backgnd)
9072                         flags &= ~EV_TESTED;
9073  nofork:
9074                 redirect(n->nredir.redirect, 0);
9075                 evaltreenr(n->nredir.n, flags);
9076                 /* never returns */
9077         }
9078         /* parent */
9079         status = 0;
9080         if (backgnd == FORK_FG)
9081                 status = waitforjob(jp);
9082         INT_ON;
9083         return status;
9084 }
9085
9086 /*
9087  * Compute the names of the files in a redirection list.
9088  */
9089 static void fixredir(union node *, const char *, int);
9090 static void
9091 expredir(union node *n)
9092 {
9093         union node *redir;
9094
9095         for (redir = n; redir; redir = redir->nfile.next) {
9096                 struct arglist fn;
9097
9098                 fn.list = NULL;
9099                 fn.lastp = &fn.list;
9100                 switch (redir->type) {
9101                 case NFROMTO:
9102                 case NFROM:
9103                 case NTO:
9104 #if BASH_REDIR_OUTPUT
9105                 case NTO2:
9106 #endif
9107                 case NCLOBBER:
9108                 case NAPPEND:
9109                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9110                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9111 #if BASH_REDIR_OUTPUT
9112  store_expfname:
9113 #endif
9114 #if 0
9115 // By the design of stack allocator, the loop of this kind:
9116 //      while true; do while true; do break; done </dev/null; done
9117 // will look like a memory leak: ash plans to free expfname's
9118 // of "/dev/null" as soon as it finishes running the loop
9119 // (in this case, never).
9120 // This "fix" is wrong:
9121                         if (redir->nfile.expfname)
9122                                 stunalloc(redir->nfile.expfname);
9123 // It results in corrupted state of stacked allocations.
9124 #endif
9125                         redir->nfile.expfname = fn.list->text;
9126                         break;
9127                 case NFROMFD:
9128                 case NTOFD: /* >& */
9129                         if (redir->ndup.vname) {
9130                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9131                                 if (fn.list == NULL)
9132                                         ash_msg_and_raise_error("redir error");
9133 #if BASH_REDIR_OUTPUT
9134 //FIXME: we used expandarg with different args!
9135                                 if (!isdigit_str9(fn.list->text)) {
9136                                         /* >&file, not >&fd */
9137                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9138                                                 ash_msg_and_raise_error("redir error");
9139                                         redir->type = NTO2;
9140                                         goto store_expfname;
9141                                 }
9142 #endif
9143                                 fixredir(redir, fn.list->text, 1);
9144                         }
9145                         break;
9146                 }
9147         }
9148 }
9149
9150 /*
9151  * Evaluate a pipeline.  All the processes in the pipeline are children
9152  * of the process creating the pipeline.  (This differs from some versions
9153  * of the shell, which make the last process in a pipeline the parent
9154  * of all the rest.)
9155  */
9156 static int
9157 evalpipe(union node *n, int flags)
9158 {
9159         struct job *jp;
9160         struct nodelist *lp;
9161         int pipelen;
9162         int prevfd;
9163         int pip[2];
9164         int status = 0;
9165
9166         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9167         pipelen = 0;
9168         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9169                 pipelen++;
9170         flags |= EV_EXIT;
9171         INT_OFF;
9172         if (n->npipe.pipe_backgnd == 0)
9173                 get_tty_state();
9174         jp = makejob(/*n,*/ pipelen);
9175         prevfd = -1;
9176         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9177                 prehash(lp->n);
9178                 pip[1] = -1;
9179                 if (lp->next) {
9180                         if (pipe(pip) < 0) {
9181                                 close(prevfd);
9182                                 ash_msg_and_raise_error("pipe call failed");
9183                         }
9184                 }
9185                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9186                         /* child */
9187                         INT_ON;
9188                         if (pip[1] >= 0) {
9189                                 close(pip[0]);
9190                         }
9191                         if (prevfd > 0) {
9192                                 dup2(prevfd, 0);
9193                                 close(prevfd);
9194                         }
9195                         if (pip[1] > 1) {
9196                                 dup2(pip[1], 1);
9197                                 close(pip[1]);
9198                         }
9199                         evaltreenr(lp->n, flags);
9200                         /* never returns */
9201                 }
9202                 /* parent */
9203                 if (prevfd >= 0)
9204                         close(prevfd);
9205                 prevfd = pip[0];
9206                 /* Don't want to trigger debugging */
9207                 if (pip[1] != -1)
9208                         close(pip[1]);
9209         }
9210         if (n->npipe.pipe_backgnd == 0) {
9211                 status = waitforjob(jp);
9212                 TRACE(("evalpipe:  job done exit status %d\n", status));
9213         }
9214         INT_ON;
9215
9216         return status;
9217 }
9218
9219 /*
9220  * Controls whether the shell is interactive or not.
9221  */
9222 static void
9223 setinteractive(int on)
9224 {
9225         static smallint is_interactive;
9226
9227         if (++on == is_interactive)
9228                 return;
9229         is_interactive = on;
9230         setsignal(SIGINT);
9231         setsignal(SIGQUIT);
9232         setsignal(SIGTERM);
9233 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9234         if (is_interactive > 1) {
9235                 /* Looks like they want an interactive shell */
9236                 static smallint did_banner;
9237
9238                 if (!did_banner) {
9239                         /* note: ash and hush share this string */
9240                         out1fmt("\n\n%s %s\n"
9241                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9242                                 "\n",
9243                                 bb_banner,
9244                                 "built-in shell (ash)"
9245                         );
9246                         did_banner = 1;
9247                 }
9248         }
9249 #endif
9250 }
9251
9252 static void
9253 optschanged(void)
9254 {
9255 #if DEBUG
9256         opentrace();
9257 #endif
9258         setinteractive(iflag);
9259         setjobctl(mflag);
9260 #if ENABLE_FEATURE_EDITING_VI
9261         if (viflag)
9262                 line_input_state->flags |= VI_MODE;
9263         else
9264                 line_input_state->flags &= ~VI_MODE;
9265 #else
9266         viflag = 0; /* forcibly keep the option off */
9267 #endif
9268 }
9269
9270 struct localvar_list {
9271         struct localvar_list *next;
9272         struct localvar *lv;
9273 };
9274
9275 static struct localvar_list *localvar_stack;
9276
9277 /*
9278  * Called after a function returns.
9279  * Interrupts must be off.
9280  */
9281 static void
9282 poplocalvars(int keep)
9283 {
9284         struct localvar_list *ll;
9285         struct localvar *lvp, *next;
9286         struct var *vp;
9287
9288         INT_OFF;
9289         ll = localvar_stack;
9290         localvar_stack = ll->next;
9291
9292         next = ll->lv;
9293         free(ll);
9294
9295         while ((lvp = next) != NULL) {
9296                 next = lvp->next;
9297                 vp = lvp->vp;
9298                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9299                 if (keep) {
9300                         int bits = VSTRFIXED;
9301
9302                         if (lvp->flags != VUNSET) {
9303                                 if (vp->var_text == lvp->text)
9304                                         bits |= VTEXTFIXED;
9305                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9306                                         free((char*)lvp->text);
9307                         }
9308
9309                         vp->flags &= ~bits;
9310                         vp->flags |= (lvp->flags & bits);
9311
9312                         if ((vp->flags &
9313                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9314                                 unsetvar(vp->var_text);
9315                 } else if (vp == NULL) {        /* $- saved */
9316                         memcpy(optlist, lvp->text, sizeof(optlist));
9317                         free((char*)lvp->text);
9318                         optschanged();
9319                 } else if (lvp->flags == VUNSET) {
9320                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9321                         unsetvar(vp->var_text);
9322                 } else {
9323                         if (vp->var_func)
9324                                 vp->var_func(var_end(lvp->text));
9325                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9326                                 free((char*)vp->var_text);
9327                         vp->flags = lvp->flags;
9328                         vp->var_text = lvp->text;
9329                 }
9330                 free(lvp);
9331         }
9332         INT_ON;
9333 }
9334
9335 /*
9336  * Create a new localvar environment.
9337  */
9338 static struct localvar_list *
9339 pushlocalvars(void)
9340 {
9341         struct localvar_list *ll;
9342
9343         INT_OFF;
9344         ll = ckzalloc(sizeof(*ll));
9345         /*ll->lv = NULL; - zalloc did it */
9346         ll->next = localvar_stack;
9347         localvar_stack = ll;
9348         INT_ON;
9349
9350         return ll->next;
9351 }
9352
9353 static void
9354 unwindlocalvars(struct localvar_list *stop)
9355 {
9356         while (localvar_stack != stop)
9357                 poplocalvars(0);
9358 }
9359
9360 static int
9361 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9362 {
9363         volatile struct shparam saveparam;
9364         struct jmploc *volatile savehandler;
9365         struct jmploc jmploc;
9366         int e;
9367
9368         saveparam = shellparam;
9369         savehandler = exception_handler;
9370         e = setjmp(jmploc.loc);
9371         if (e) {
9372                 goto funcdone;
9373         }
9374         INT_OFF;
9375         exception_handler = &jmploc;
9376         shellparam.malloced = 0;
9377         func->count++;
9378         funcnest++;
9379         INT_ON;
9380         shellparam.nparam = argc - 1;
9381         shellparam.p = argv + 1;
9382 #if ENABLE_ASH_GETOPTS
9383         shellparam.optind = 1;
9384         shellparam.optoff = -1;
9385 #endif
9386         pushlocalvars();
9387         evaltree(func->n.narg.next, flags & EV_TESTED);
9388         poplocalvars(0);
9389  funcdone:
9390         INT_OFF;
9391         funcnest--;
9392         freefunc(func);
9393         freeparam(&shellparam);
9394         shellparam = saveparam;
9395         exception_handler = savehandler;
9396         INT_ON;
9397         evalskip &= ~SKIPFUNC;
9398         return e;
9399 }
9400
9401 /*
9402  * Make a variable a local variable.  When a variable is made local, it's
9403  * value and flags are saved in a localvar structure.  The saved values
9404  * will be restored when the shell function returns.  We handle the name
9405  * "-" as a special case: it makes changes to "set +-options" local
9406  * (options will be restored on return from the function).
9407  */
9408 static void
9409 mklocal(char *name)
9410 {
9411         struct localvar *lvp;
9412         struct var **vpp;
9413         struct var *vp;
9414         char *eq = strchr(name, '=');
9415
9416         INT_OFF;
9417         /* Cater for duplicate "local". Examples:
9418          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9419          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9420          */
9421         lvp = localvar_stack->lv;
9422         while (lvp) {
9423                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9424                         if (eq)
9425                                 setvareq(name, 0);
9426                         /* else:
9427                          * it's a duplicate "local VAR" declaration, do nothing
9428                          */
9429                         goto ret;
9430                 }
9431                 lvp = lvp->next;
9432         }
9433
9434         lvp = ckzalloc(sizeof(*lvp));
9435         if (LONE_DASH(name)) {
9436                 char *p;
9437                 p = ckmalloc(sizeof(optlist));
9438                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9439                 vp = NULL;
9440         } else {
9441                 vpp = hashvar(name);
9442                 vp = *findvar(vpp, name);
9443                 if (vp == NULL) {
9444                         /* variable did not exist yet */
9445                         if (eq)
9446                                 vp = setvareq(name, VSTRFIXED);
9447                         else
9448                                 vp = setvar(name, NULL, VSTRFIXED);
9449                         lvp->flags = VUNSET;
9450                 } else {
9451                         lvp->text = vp->var_text;
9452                         lvp->flags = vp->flags;
9453                         /* make sure neither "struct var" nor string gets freed
9454                          * during (un)setting:
9455                          */
9456                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9457                         if (eq)
9458                                 setvareq(name, 0);
9459                         else
9460                                 /* "local VAR" unsets VAR: */
9461                                 setvar0(name, NULL);
9462                 }
9463         }
9464         lvp->vp = vp;
9465         lvp->next = localvar_stack->lv;
9466         localvar_stack->lv = lvp;
9467  ret:
9468         INT_ON;
9469 }
9470
9471 /*
9472  * The "local" command.
9473  */
9474 static int FAST_FUNC
9475 localcmd(int argc UNUSED_PARAM, char **argv)
9476 {
9477         char *name;
9478
9479         if (!localvar_stack)
9480                 ash_msg_and_raise_error("not in a function");
9481
9482         argv = argptr;
9483         while ((name = *argv++) != NULL) {
9484                 mklocal(name);
9485         }
9486         return 0;
9487 }
9488
9489 static int FAST_FUNC
9490 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9491 {
9492         return 1;
9493 }
9494
9495 static int FAST_FUNC
9496 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9497 {
9498         return 0;
9499 }
9500
9501 static int FAST_FUNC
9502 execcmd(int argc UNUSED_PARAM, char **argv)
9503 {
9504         optionarg = NULL;
9505         while (nextopt("a:") != '\0')
9506                 /* nextopt() sets optionarg to "-a ARGV0" */;
9507
9508         argv = argptr;
9509         if (argv[0]) {
9510                 char *prog;
9511
9512                 iflag = 0;              /* exit on error */
9513                 mflag = 0;
9514                 optschanged();
9515                 /* We should set up signals for "exec CMD"
9516                  * the same way as for "CMD" without "exec".
9517                  * But optschanged->setinteractive->setsignal
9518                  * still thought we are a root shell. Therefore, for example,
9519                  * SIGQUIT is still set to IGN. Fix it:
9520                  */
9521                 shlvl++;
9522                 setsignal(SIGQUIT);
9523                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9524                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9525                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9526
9527                 prog = argv[0];
9528                 if (optionarg)
9529                         argv[0] = optionarg;
9530                 shellexec(prog, argv, pathval(), 0);
9531                 /* NOTREACHED */
9532         }
9533         return 0;
9534 }
9535
9536 /*
9537  * The return command.
9538  */
9539 static int FAST_FUNC
9540 returncmd(int argc UNUSED_PARAM, char **argv)
9541 {
9542         /*
9543          * If called outside a function, do what ksh does;
9544          * skip the rest of the file.
9545          */
9546         evalskip = SKIPFUNC;
9547         return argv[1] ? number(argv[1]) : exitstatus;
9548 }
9549
9550 /* Forward declarations for builtintab[] */
9551 static int breakcmd(int, char **) FAST_FUNC;
9552 static int dotcmd(int, char **) FAST_FUNC;
9553 static int evalcmd(int, char **, int) FAST_FUNC;
9554 static int exitcmd(int, char **) FAST_FUNC;
9555 static int exportcmd(int, char **) FAST_FUNC;
9556 #if ENABLE_ASH_GETOPTS
9557 static int getoptscmd(int, char **) FAST_FUNC;
9558 #endif
9559 #if ENABLE_ASH_HELP
9560 static int helpcmd(int, char **) FAST_FUNC;
9561 #endif
9562 #if MAX_HISTORY
9563 static int historycmd(int, char **) FAST_FUNC;
9564 #endif
9565 #if ENABLE_FEATURE_SH_MATH
9566 static int letcmd(int, char **) FAST_FUNC;
9567 #endif
9568 static int readcmd(int, char **) FAST_FUNC;
9569 static int setcmd(int, char **) FAST_FUNC;
9570 static int shiftcmd(int, char **) FAST_FUNC;
9571 static int timescmd(int, char **) FAST_FUNC;
9572 static int trapcmd(int, char **) FAST_FUNC;
9573 static int umaskcmd(int, char **) FAST_FUNC;
9574 static int unsetcmd(int, char **) FAST_FUNC;
9575 static int ulimitcmd(int, char **) FAST_FUNC;
9576
9577 #define BUILTIN_NOSPEC          "0"
9578 #define BUILTIN_SPECIAL         "1"
9579 #define BUILTIN_REGULAR         "2"
9580 #define BUILTIN_SPEC_REG        "3"
9581 #define BUILTIN_ASSIGN          "4"
9582 #define BUILTIN_SPEC_ASSG       "5"
9583 #define BUILTIN_REG_ASSG        "6"
9584 #define BUILTIN_SPEC_REG_ASSG   "7"
9585
9586 /* Stubs for calling non-FAST_FUNC's */
9587 #if ENABLE_ASH_ECHO
9588 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9589 #endif
9590 #if ENABLE_ASH_PRINTF
9591 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9592 #endif
9593 #if ENABLE_ASH_TEST || BASH_TEST2
9594 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9595 #endif
9596
9597 /* Keep these in proper order since it is searched via bsearch() */
9598 static const struct builtincmd builtintab[] = {
9599         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9600         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9601 #if ENABLE_ASH_TEST
9602         { BUILTIN_REGULAR       "["       , testcmd    },
9603 #endif
9604 #if BASH_TEST2
9605         { BUILTIN_REGULAR       "[["      , testcmd    },
9606 #endif
9607 #if ENABLE_ASH_ALIAS
9608         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9609 #endif
9610 #if JOBS
9611         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9612 #endif
9613         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9614         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9615         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9616 #if ENABLE_ASH_CMDCMD
9617         { BUILTIN_REGULAR       "command" , commandcmd },
9618 #endif
9619         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9620 #if ENABLE_ASH_ECHO
9621         { BUILTIN_REGULAR       "echo"    , echocmd    },
9622 #endif
9623         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9624         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9625         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9626         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9627         { BUILTIN_REGULAR       "false"   , falsecmd   },
9628 #if JOBS
9629         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9630 #endif
9631 #if ENABLE_ASH_GETOPTS
9632         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9633 #endif
9634         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9635 #if ENABLE_ASH_HELP
9636         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9637 #endif
9638 #if MAX_HISTORY
9639         { BUILTIN_NOSPEC        "history" , historycmd },
9640 #endif
9641 #if JOBS
9642         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9643         { BUILTIN_REGULAR       "kill"    , killcmd    },
9644 #endif
9645 #if ENABLE_FEATURE_SH_MATH
9646         { BUILTIN_NOSPEC        "let"     , letcmd     },
9647 #endif
9648         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9649 #if ENABLE_ASH_PRINTF
9650         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9651 #endif
9652         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9653         { BUILTIN_REGULAR       "read"    , readcmd    },
9654         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9655         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9656         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9657         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9658 #if BASH_SOURCE
9659         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9660 #endif
9661 #if ENABLE_ASH_TEST
9662         { BUILTIN_REGULAR       "test"    , testcmd    },
9663 #endif
9664         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9665         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9666         { BUILTIN_REGULAR       "true"    , truecmd    },
9667         { BUILTIN_NOSPEC        "type"    , typecmd    },
9668         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9669         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9670 #if ENABLE_ASH_ALIAS
9671         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9672 #endif
9673         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9674         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9675 };
9676
9677 /* Should match the above table! */
9678 #define COMMANDCMD (builtintab + \
9679         /* . : */       2 + \
9680         /* [ */         1 * ENABLE_ASH_TEST + \
9681         /* [[ */        1 * BASH_TEST2 + \
9682         /* alias */     1 * ENABLE_ASH_ALIAS + \
9683         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9684         /* break cd cddir  */   3)
9685 #define EVALCMD (COMMANDCMD + \
9686         /* command */   1 * ENABLE_ASH_CMDCMD + \
9687         /* continue */  1 + \
9688         /* echo */      1 * ENABLE_ASH_ECHO + \
9689         0)
9690 #define EXECCMD (EVALCMD + \
9691         /* eval */      1)
9692
9693 /*
9694  * Search the table of builtin commands.
9695  */
9696 static int
9697 pstrcmp1(const void *a, const void *b)
9698 {
9699         return strcmp((char*)a, *(char**)b + 1);
9700 }
9701 static struct builtincmd *
9702 find_builtin(const char *name)
9703 {
9704         struct builtincmd *bp;
9705
9706         bp = bsearch(
9707                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9708                 pstrcmp1
9709         );
9710         return bp;
9711 }
9712
9713 /*
9714  * Execute a simple command.
9715  */
9716 static int
9717 isassignment(const char *p)
9718 {
9719         const char *q = endofname(p);
9720         if (p == q)
9721                 return 0;
9722         return *q == '=';
9723 }
9724 static int FAST_FUNC
9725 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9726 {
9727         /* Preserve exitstatus of a previous possible redirection
9728          * as POSIX mandates */
9729         return back_exitstatus;
9730 }
9731 static int
9732 evalcommand(union node *cmd, int flags)
9733 {
9734         static const struct builtincmd null_bltin = {
9735                 "\0\0", bltincmd /* why three NULs? */
9736         };
9737         struct localvar_list *localvar_stop;
9738         struct redirtab *redir_stop;
9739         struct stackmark smark;
9740         union node *argp;
9741         struct arglist arglist;
9742         struct arglist varlist;
9743         char **argv;
9744         int argc;
9745         const struct strlist *sp;
9746         struct cmdentry cmdentry;
9747         struct job *jp;
9748         char *lastarg;
9749         const char *path;
9750         int spclbltin;
9751         int status;
9752         char **nargv;
9753         smallint cmd_is_exec;
9754
9755         /* First expand the arguments. */
9756         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9757         setstackmark(&smark);
9758         localvar_stop = pushlocalvars();
9759         back_exitstatus = 0;
9760
9761         cmdentry.cmdtype = CMDBUILTIN;
9762         cmdentry.u.cmd = &null_bltin;
9763         varlist.lastp = &varlist.list;
9764         *varlist.lastp = NULL;
9765         arglist.lastp = &arglist.list;
9766         *arglist.lastp = NULL;
9767
9768         argc = 0;
9769         if (cmd->ncmd.args) {
9770                 struct builtincmd *bcmd;
9771                 smallint pseudovarflag;
9772
9773                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9774                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9775
9776                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9777                         struct strlist **spp;
9778
9779                         spp = arglist.lastp;
9780                         if (pseudovarflag && isassignment(argp->narg.text))
9781                                 expandarg(argp, &arglist, EXP_VARTILDE);
9782                         else
9783                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9784
9785                         for (sp = *spp; sp; sp = sp->next)
9786                                 argc++;
9787                 }
9788         }
9789
9790         /* Reserve one extra spot at the front for shellexec. */
9791         nargv = stalloc(sizeof(char *) * (argc + 2));
9792         argv = ++nargv;
9793         for (sp = arglist.list; sp; sp = sp->next) {
9794                 TRACE(("evalcommand arg: %s\n", sp->text));
9795                 *nargv++ = sp->text;
9796         }
9797         *nargv = NULL;
9798
9799         lastarg = NULL;
9800         if (iflag && funcnest == 0 && argc > 0)
9801                 lastarg = nargv[-1];
9802
9803         expredir(cmd->ncmd.redirect);
9804         redir_stop = pushredir(cmd->ncmd.redirect);
9805         preverrout_fd = 2;
9806         if (BASH_XTRACEFD && xflag) {
9807                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9808                  * we do not emulate this. We only use its value.
9809                  */
9810                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9811                 if (xtracefd && is_number(xtracefd))
9812                         preverrout_fd = atoi(xtracefd);
9813
9814         }
9815         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9816
9817         path = vpath.var_text;
9818         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9819                 struct strlist **spp;
9820                 char *p;
9821
9822                 spp = varlist.lastp;
9823                 expandarg(argp, &varlist, EXP_VARTILDE);
9824
9825                 mklocal((*spp)->text);
9826
9827                 /*
9828                  * Modify the command lookup path, if a PATH= assignment
9829                  * is present
9830                  */
9831                 p = (*spp)->text;
9832                 if (varcmp(p, path) == 0)
9833                         path = p;
9834         }
9835
9836         /* Print the command if xflag is set. */
9837         if (xflag) {
9838                 const char *pfx = "";
9839
9840                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9841
9842                 sp = varlist.list;
9843                 while (sp) {
9844                         char *varval = sp->text;
9845                         char *eq = strchrnul(varval, '=');
9846                         if (*eq)
9847                                 eq++;
9848                         fdprintf(preverrout_fd, "%s%.*s%s",
9849                                 pfx,
9850                                 (int)(eq - varval), varval,
9851                                 maybe_single_quote(eq)
9852                         );
9853                         sp = sp->next;
9854                         pfx = " ";
9855                 }
9856
9857                 sp = arglist.list;
9858                 while (sp) {
9859                         fdprintf(preverrout_fd, "%s%s",
9860                                 pfx,
9861                                 /* always quote if matches reserved word: */
9862                                 findkwd(sp->text)
9863                                 ? single_quote(sp->text)
9864                                 : maybe_single_quote(sp->text)
9865                         );
9866                         sp = sp->next;
9867                         pfx = " ";
9868                 }
9869                 safe_write(preverrout_fd, "\n", 1);
9870         }
9871
9872         cmd_is_exec = 0;
9873         spclbltin = -1;
9874
9875         /* Now locate the command. */
9876         if (argc) {
9877                 int cmd_flag = DO_ERR;
9878 #if ENABLE_ASH_CMDCMD
9879                 const char *oldpath = path + 5;
9880 #endif
9881                 path += 5;
9882                 for (;;) {
9883                         find_command(argv[0], &cmdentry, cmd_flag, path);
9884                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9885                                 flush_stdout_stderr();
9886                                 status = 127;
9887                                 goto bail;
9888                         }
9889
9890                         /* implement bltin and command here */
9891                         if (cmdentry.cmdtype != CMDBUILTIN)
9892                                 break;
9893                         if (spclbltin < 0)
9894                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9895                         if (cmdentry.u.cmd == EXECCMD)
9896                                 cmd_is_exec = 1;
9897 #if ENABLE_ASH_CMDCMD
9898                         if (cmdentry.u.cmd == COMMANDCMD) {
9899                                 path = oldpath;
9900                                 nargv = parse_command_args(argv, &path);
9901                                 if (!nargv)
9902                                         break;
9903                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9904                                  * nargv => "PROG". path is updated if -p.
9905                                  */
9906                                 argc -= nargv - argv;
9907                                 argv = nargv;
9908                                 cmd_flag |= DO_NOFUNC;
9909                         } else
9910 #endif
9911                                 break;
9912                 }
9913         }
9914
9915         if (status) {
9916  bail:
9917                 exitstatus = status;
9918
9919                 /* We have a redirection error. */
9920                 if (spclbltin > 0)
9921                         raise_exception(EXERROR);
9922
9923                 goto out;
9924         }
9925
9926         /* Execute the command. */
9927         switch (cmdentry.cmdtype) {
9928         default: {
9929
9930 #if ENABLE_FEATURE_SH_NOFORK
9931 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9932  *     around run_nofork_applet() call.
9933  * (2) Should this check also be done in forkshell()?
9934  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9935  */
9936                 /* find_command() encodes applet_no as (-2 - applet_no) */
9937                 int applet_no = (- cmdentry.u.index - 2);
9938                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9939                         listsetvar(varlist.list, VEXPORT|VSTACK);
9940                         /*
9941                          * Run <applet>_main().
9942                          * Signals (^C) can't interrupt here.
9943                          * Otherwise we can mangle stdio or malloc internal state.
9944                          * This makes applets which can run for a long time
9945                          * and/or wait for user input ineligible for NOFORK:
9946                          * for example, "yes" or "rm" (rm -i waits for input).
9947                          */
9948                         INT_OFF;
9949                         status = run_nofork_applet(applet_no, argv);
9950                         /*
9951                          * Try enabling NOFORK for "yes" applet.
9952                          * ^C _will_ stop it (write returns EINTR),
9953                          * but this causes stdout FILE to be stuck
9954                          * and needing clearerr(). What if other applets
9955                          * also can get EINTRs? Do we need to switch
9956                          * our signals to SA_RESTART?
9957                          */
9958                         /*clearerr(stdout);*/
9959                         INT_ON;
9960                         break;
9961                 }
9962 #endif
9963                 /* Can we avoid forking? For example, very last command
9964                  * in a script or a subshell does not need forking,
9965                  * we can just exec it.
9966                  */
9967                 if (!(flags & EV_EXIT) || may_have_traps) {
9968                         /* No, forking off a child is necessary */
9969                         INT_OFF;
9970                         get_tty_state();
9971                         jp = makejob(/*cmd,*/ 1);
9972                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9973                                 /* parent */
9974                                 status = waitforjob(jp);
9975                                 INT_ON;
9976                                 TRACE(("forked child exited with %d\n", status));
9977                                 break;
9978                         }
9979                         /* child */
9980                         FORCE_INT_ON;
9981                         /* fall through to exec'ing external program */
9982                 }
9983                 listsetvar(varlist.list, VEXPORT|VSTACK);
9984                 shellexec(argv[0], argv, path, cmdentry.u.index);
9985                 /* NOTREACHED */
9986         } /* default */
9987         case CMDBUILTIN:
9988                 if (spclbltin > 0 || argc == 0) {
9989                         poplocalvars(1);
9990                         if (cmd_is_exec && argc > 1)
9991                                 listsetvar(varlist.list, VEXPORT);
9992                 }
9993
9994                 /* Tight loop with builtins only:
9995                  * "while kill -0 $child; do true; done"
9996                  * will never exit even if $child died, unless we do this
9997                  * to reap the zombie and make kill detect that it's gone: */
9998                 dowait(DOWAIT_NONBLOCK, NULL);
9999
10000                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10001                         if (exception_type == EXERROR && spclbltin <= 0) {
10002                                 FORCE_INT_ON;
10003                                 goto readstatus;
10004                         }
10005  raise:
10006                         longjmp(exception_handler->loc, 1);
10007                 }
10008                 goto readstatus;
10009
10010         case CMDFUNCTION:
10011                 poplocalvars(1);
10012                 /* See above for the rationale */
10013                 dowait(DOWAIT_NONBLOCK, NULL);
10014                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10015                         goto raise;
10016  readstatus:
10017                 status = exitstatus;
10018                 break;
10019         } /* switch */
10020
10021  out:
10022         if (cmd->ncmd.redirect)
10023                 popredir(/*drop:*/ cmd_is_exec);
10024         unwindredir(redir_stop);
10025         unwindlocalvars(localvar_stop);
10026         if (lastarg) {
10027                 /* dsl: I think this is intended to be used to support
10028                  * '_' in 'vi' command mode during line editing...
10029                  * However I implemented that within libedit itself.
10030                  */
10031                 setvar0("_", lastarg);
10032         }
10033         popstackmark(&smark);
10034
10035         return status;
10036 }
10037
10038 static int
10039 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10040 {
10041         char *volatile savecmdname;
10042         struct jmploc *volatile savehandler;
10043         struct jmploc jmploc;
10044         int status;
10045         int i;
10046
10047         savecmdname = commandname;
10048         savehandler = exception_handler;
10049         i = setjmp(jmploc.loc);
10050         if (i)
10051                 goto cmddone;
10052         exception_handler = &jmploc;
10053         commandname = argv[0];
10054         argptr = argv + 1;
10055         optptr = NULL;                  /* initialize nextopt */
10056         if (cmd == EVALCMD)
10057                 status = evalcmd(argc, argv, flags);
10058         else
10059                 status = (*cmd->builtin)(argc, argv);
10060         flush_stdout_stderr();
10061         status |= ferror(stdout);
10062         exitstatus = status;
10063  cmddone:
10064         clearerr(stdout);
10065         commandname = savecmdname;
10066         exception_handler = savehandler;
10067
10068         return i;
10069 }
10070
10071 static int
10072 goodname(const char *p)
10073 {
10074         return endofname(p)[0] == '\0';
10075 }
10076
10077
10078 /*
10079  * Search for a command.  This is called before we fork so that the
10080  * location of the command will be available in the parent as well as
10081  * the child.  The check for "goodname" is an overly conservative
10082  * check that the name will not be subject to expansion.
10083  */
10084 static void
10085 prehash(union node *n)
10086 {
10087         struct cmdentry entry;
10088
10089         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10090                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10091 }
10092
10093
10094 /* ============ Builtin commands
10095  *
10096  * Builtin commands whose functions are closely tied to evaluation
10097  * are implemented here.
10098  */
10099
10100 /*
10101  * Handle break and continue commands.  Break, continue, and return are
10102  * all handled by setting the evalskip flag.  The evaluation routines
10103  * above all check this flag, and if it is set they start skipping
10104  * commands rather than executing them.  The variable skipcount is
10105  * the number of loops to break/continue, or the number of function
10106  * levels to return.  (The latter is always 1.)  It should probably
10107  * be an error to break out of more loops than exist, but it isn't
10108  * in the standard shell so we don't make it one here.
10109  */
10110 static int FAST_FUNC
10111 breakcmd(int argc UNUSED_PARAM, char **argv)
10112 {
10113         int n = argv[1] ? number(argv[1]) : 1;
10114
10115         if (n <= 0)
10116                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10117         if (n > loopnest)
10118                 n = loopnest;
10119         if (n > 0) {
10120                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10121                 skipcount = n;
10122         }
10123         return 0;
10124 }
10125
10126
10127 /*
10128  * This implements the input routines used by the parser.
10129  */
10130
10131 enum {
10132         INPUT_PUSH_FILE = 1,
10133         INPUT_NOFILE_OK = 2,
10134 };
10135
10136 static smallint checkkwd;
10137 /* values of checkkwd variable */
10138 #define CHKALIAS        0x1
10139 #define CHKKWD          0x2
10140 #define CHKNL           0x4
10141 #define CHKEOFMARK      0x8
10142
10143 /*
10144  * Push a string back onto the input at this current parsefile level.
10145  * We handle aliases this way.
10146  */
10147 #if !ENABLE_ASH_ALIAS
10148 #define pushstring(s, ap) pushstring(s)
10149 #endif
10150 static void
10151 pushstring(char *s, struct alias *ap)
10152 {
10153         struct strpush *sp;
10154         int len;
10155
10156         len = strlen(s);
10157         INT_OFF;
10158         if (g_parsefile->strpush) {
10159                 sp = ckzalloc(sizeof(*sp));
10160                 sp->prev = g_parsefile->strpush;
10161         } else {
10162                 sp = &(g_parsefile->basestrpush);
10163         }
10164         g_parsefile->strpush = sp;
10165         sp->prev_string = g_parsefile->next_to_pgetc;
10166         sp->prev_left_in_line = g_parsefile->left_in_line;
10167         sp->unget = g_parsefile->unget;
10168         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10169 #if ENABLE_ASH_ALIAS
10170         sp->ap = ap;
10171         if (ap) {
10172                 ap->flag |= ALIASINUSE;
10173                 sp->string = s;
10174         }
10175 #endif
10176         g_parsefile->next_to_pgetc = s;
10177         g_parsefile->left_in_line = len;
10178         g_parsefile->unget = 0;
10179         INT_ON;
10180 }
10181
10182 static void
10183 popstring(void)
10184 {
10185         struct strpush *sp = g_parsefile->strpush;
10186
10187         INT_OFF;
10188 #if ENABLE_ASH_ALIAS
10189         if (sp->ap) {
10190                 if (g_parsefile->next_to_pgetc[-1] == ' '
10191                  || g_parsefile->next_to_pgetc[-1] == '\t'
10192                 ) {
10193                         checkkwd |= CHKALIAS;
10194                 }
10195                 if (sp->string != sp->ap->val) {
10196                         free(sp->string);
10197                 }
10198                 sp->ap->flag &= ~ALIASINUSE;
10199                 if (sp->ap->flag & ALIASDEAD) {
10200                         unalias(sp->ap->name);
10201                 }
10202         }
10203 #endif
10204         g_parsefile->next_to_pgetc = sp->prev_string;
10205         g_parsefile->left_in_line = sp->prev_left_in_line;
10206         g_parsefile->unget = sp->unget;
10207         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10208         g_parsefile->strpush = sp->prev;
10209         if (sp != &(g_parsefile->basestrpush))
10210                 free(sp);
10211         INT_ON;
10212 }
10213
10214 static int
10215 preadfd(void)
10216 {
10217         int nr;
10218         char *buf = g_parsefile->buf;
10219
10220         g_parsefile->next_to_pgetc = buf;
10221 #if ENABLE_FEATURE_EDITING
10222  retry:
10223         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10224                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10225         else {
10226 # if ENABLE_ASH_IDLE_TIMEOUT
10227                 int timeout = -1;
10228                 if (iflag) {
10229                         const char *tmout_var = lookupvar("TMOUT");
10230                         if (tmout_var) {
10231                                 timeout = atoi(tmout_var) * 1000;
10232                                 if (timeout <= 0)
10233                                         timeout = -1;
10234                         }
10235                 }
10236                 line_input_state->timeout = timeout;
10237 # endif
10238 # if ENABLE_FEATURE_TAB_COMPLETION
10239                 line_input_state->path_lookup = pathval();
10240 # endif
10241                 reinit_unicode_for_ash();
10242                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10243                 if (nr == 0) {
10244                         /* ^C pressed, "convert" to SIGINT */
10245                         write(STDOUT_FILENO, "^C", 2);
10246                         if (trap[SIGINT]) {
10247                                 buf[0] = '\n';
10248                                 buf[1] = '\0';
10249                                 raise(SIGINT);
10250                                 return 1;
10251                         }
10252                         exitstatus = 128 + SIGINT;
10253                         bb_putchar('\n');
10254                         goto retry;
10255                 }
10256                 if (nr < 0) {
10257                         if (errno == 0) {
10258                                 /* Ctrl+D pressed */
10259                                 nr = 0;
10260                         }
10261 # if ENABLE_ASH_IDLE_TIMEOUT
10262                         else if (errno == EAGAIN && timeout > 0) {
10263                                 puts("\007timed out waiting for input: auto-logout");
10264                                 exitshell();
10265                         }
10266 # endif
10267                 }
10268         }
10269 #else
10270         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10271 #endif
10272
10273 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10274         if (nr < 0) {
10275                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10276                         int flags = fcntl(0, F_GETFL);
10277                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10278                                 flags &= ~O_NONBLOCK;
10279                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10280                                         out2str("sh: turning off NDELAY mode\n");
10281                                         goto retry;
10282                                 }
10283                         }
10284                 }
10285         }
10286 #endif
10287         return nr;
10288 }
10289
10290 /*
10291  * Refill the input buffer and return the next input character:
10292  *
10293  * 1) If a string was pushed back on the input, pop it;
10294  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10295  *    or we are reading from a string so we can't refill the buffer,
10296  *    return EOF.
10297  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10298  * 4) Process input up to the next newline, deleting nul characters.
10299  */
10300 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10301 #define pgetc_debug(...) ((void)0)
10302 static int pgetc(void);
10303 static int
10304 preadbuffer(void)
10305 {
10306         char *q;
10307         int more;
10308
10309         if (g_parsefile->strpush) {
10310 #if ENABLE_ASH_ALIAS
10311                 if (g_parsefile->left_in_line == -1
10312                  && g_parsefile->strpush->ap
10313                  && g_parsefile->next_to_pgetc[-1] != ' '
10314                  && g_parsefile->next_to_pgetc[-1] != '\t'
10315                 ) {
10316                         pgetc_debug("preadbuffer PEOA");
10317                         return PEOA;
10318                 }
10319 #endif
10320                 popstring();
10321                 return pgetc();
10322         }
10323         /* on both branches above g_parsefile->left_in_line < 0.
10324          * "pgetc" needs refilling.
10325          */
10326
10327         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10328          * pungetc() may increment it a few times.
10329          * Assuming it won't increment it to less than -90.
10330          */
10331         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10332                 pgetc_debug("preadbuffer PEOF1");
10333                 /* even in failure keep left_in_line and next_to_pgetc
10334                  * in lock step, for correct multi-layer pungetc.
10335                  * left_in_line was decremented before preadbuffer(),
10336                  * must inc next_to_pgetc: */
10337                 g_parsefile->next_to_pgetc++;
10338                 return PEOF;
10339         }
10340
10341         more = g_parsefile->left_in_buffer;
10342         if (more <= 0) {
10343                 flush_stdout_stderr();
10344  again:
10345                 more = preadfd();
10346                 if (more <= 0) {
10347                         /* don't try reading again */
10348                         g_parsefile->left_in_line = -99;
10349                         pgetc_debug("preadbuffer PEOF2");
10350                         g_parsefile->next_to_pgetc++;
10351                         return PEOF;
10352                 }
10353         }
10354
10355         /* Find out where's the end of line.
10356          * Set g_parsefile->left_in_line
10357          * and g_parsefile->left_in_buffer acordingly.
10358          * NUL chars are deleted.
10359          */
10360         q = g_parsefile->next_to_pgetc;
10361         for (;;) {
10362                 char c;
10363
10364                 more--;
10365
10366                 c = *q;
10367                 if (c == '\0') {
10368                         memmove(q, q + 1, more);
10369                 } else {
10370                         q++;
10371                         if (c == '\n') {
10372                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10373                                 break;
10374                         }
10375                 }
10376
10377                 if (more <= 0) {
10378                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10379                         if (g_parsefile->left_in_line < 0)
10380                                 goto again;
10381                         break;
10382                 }
10383         }
10384         g_parsefile->left_in_buffer = more;
10385
10386         if (vflag) {
10387                 char save = *q;
10388                 *q = '\0';
10389                 out2str(g_parsefile->next_to_pgetc);
10390                 *q = save;
10391         }
10392
10393         pgetc_debug("preadbuffer at %d:%p'%s'",
10394                         g_parsefile->left_in_line,
10395                         g_parsefile->next_to_pgetc,
10396                         g_parsefile->next_to_pgetc);
10397         return (unsigned char)*g_parsefile->next_to_pgetc++;
10398 }
10399
10400 static void
10401 nlprompt(void)
10402 {
10403         g_parsefile->linno++;
10404         setprompt_if(doprompt, 2);
10405 }
10406 static void
10407 nlnoprompt(void)
10408 {
10409         g_parsefile->linno++;
10410         needprompt = doprompt;
10411 }
10412
10413 static int
10414 pgetc(void)
10415 {
10416         int c;
10417
10418         pgetc_debug("pgetc at %d:%p'%s'",
10419                         g_parsefile->left_in_line,
10420                         g_parsefile->next_to_pgetc,
10421                         g_parsefile->next_to_pgetc);
10422         if (g_parsefile->unget)
10423                 return g_parsefile->lastc[--g_parsefile->unget];
10424
10425         if (--g_parsefile->left_in_line >= 0)
10426                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10427         else
10428                 c = preadbuffer();
10429
10430         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10431         g_parsefile->lastc[0] = c;
10432
10433         return c;
10434 }
10435
10436 #if ENABLE_ASH_ALIAS
10437 static int
10438 pgetc_without_PEOA(void)
10439 {
10440         int c;
10441         do {
10442                 pgetc_debug("pgetc at %d:%p'%s'",
10443                                 g_parsefile->left_in_line,
10444                                 g_parsefile->next_to_pgetc,
10445                                 g_parsefile->next_to_pgetc);
10446                 c = pgetc();
10447         } while (c == PEOA);
10448         return c;
10449 }
10450 #else
10451 # define pgetc_without_PEOA() pgetc()
10452 #endif
10453
10454 /*
10455  * Undo a call to pgetc.  Only two characters may be pushed back.
10456  * PEOF may be pushed back.
10457  */
10458 static void
10459 pungetc(void)
10460 {
10461         g_parsefile->unget++;
10462 }
10463
10464 /* This one eats backslash+newline */
10465 static int
10466 pgetc_eatbnl(void)
10467 {
10468         int c;
10469
10470         while ((c = pgetc()) == '\\') {
10471                 if (pgetc() != '\n') {
10472                         pungetc();
10473                         break;
10474                 }
10475
10476                 nlprompt();
10477         }
10478
10479         return c;
10480 }
10481
10482 /*
10483  * To handle the "." command, a stack of input files is used.  Pushfile
10484  * adds a new entry to the stack and popfile restores the previous level.
10485  */
10486 static void
10487 pushfile(void)
10488 {
10489         struct parsefile *pf;
10490
10491         pf = ckzalloc(sizeof(*pf));
10492         pf->prev = g_parsefile;
10493         pf->pf_fd = -1;
10494         /*pf->strpush = NULL; - ckzalloc did it */
10495         /*pf->basestrpush.prev = NULL;*/
10496         /*pf->unget = 0;*/
10497         g_parsefile = pf;
10498 }
10499
10500 static void
10501 popfile(void)
10502 {
10503         struct parsefile *pf = g_parsefile;
10504
10505         if (pf == &basepf)
10506                 return;
10507
10508         INT_OFF;
10509         if (pf->pf_fd >= 0)
10510                 close(pf->pf_fd);
10511         free(pf->buf);
10512         while (pf->strpush)
10513                 popstring();
10514         g_parsefile = pf->prev;
10515         free(pf);
10516         INT_ON;
10517 }
10518
10519 /*
10520  * Return to top level.
10521  */
10522 static void
10523 popallfiles(void)
10524 {
10525         while (g_parsefile != &basepf)
10526                 popfile();
10527 }
10528
10529 /*
10530  * Close the file(s) that the shell is reading commands from.  Called
10531  * after a fork is done.
10532  */
10533 static void
10534 closescript(void)
10535 {
10536         popallfiles();
10537         if (g_parsefile->pf_fd > 0) {
10538                 close(g_parsefile->pf_fd);
10539                 g_parsefile->pf_fd = 0;
10540         }
10541 }
10542
10543 /*
10544  * Like setinputfile, but takes an open file descriptor.  Call this with
10545  * interrupts off.
10546  */
10547 static void
10548 setinputfd(int fd, int push)
10549 {
10550         if (push) {
10551                 pushfile();
10552                 g_parsefile->buf = NULL;
10553         }
10554         g_parsefile->pf_fd = fd;
10555         if (g_parsefile->buf == NULL)
10556                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10557         g_parsefile->left_in_buffer = 0;
10558         g_parsefile->left_in_line = 0;
10559         g_parsefile->linno = 1;
10560 }
10561
10562 /*
10563  * Set the input to take input from a file.  If push is set, push the
10564  * old input onto the stack first.
10565  */
10566 static int
10567 setinputfile(const char *fname, int flags)
10568 {
10569         int fd;
10570
10571         INT_OFF;
10572         fd = open(fname, O_RDONLY);
10573         if (fd < 0) {
10574                 if (flags & INPUT_NOFILE_OK)
10575                         goto out;
10576                 exitstatus = 127;
10577                 ash_msg_and_raise_error("can't open '%s'", fname);
10578         }
10579         if (fd < 10)
10580                 fd = savefd(fd);
10581         else
10582                 close_on_exec_on(fd);
10583         setinputfd(fd, flags & INPUT_PUSH_FILE);
10584  out:
10585         INT_ON;
10586         return fd;
10587 }
10588
10589 /*
10590  * Like setinputfile, but takes input from a string.
10591  */
10592 static void
10593 setinputstring(char *string)
10594 {
10595         INT_OFF;
10596         pushfile();
10597         g_parsefile->next_to_pgetc = string;
10598         g_parsefile->left_in_line = strlen(string);
10599         g_parsefile->buf = NULL;
10600         g_parsefile->linno = 1;
10601         INT_ON;
10602 }
10603
10604
10605 /*
10606  * Routines to check for mail.
10607  */
10608
10609 #if ENABLE_ASH_MAIL
10610
10611 /* Hash of mtimes of mailboxes */
10612 static unsigned mailtime_hash;
10613 /* Set if MAIL or MAILPATH is changed. */
10614 static smallint mail_var_path_changed;
10615
10616 /*
10617  * Print appropriate message(s) if mail has arrived.
10618  * If mail_var_path_changed is set,
10619  * then the value of MAIL has mail_var_path_changed,
10620  * so we just update the values.
10621  */
10622 static void
10623 chkmail(void)
10624 {
10625         const char *mpath;
10626         char *p;
10627         char *q;
10628         unsigned new_hash;
10629         struct stackmark smark;
10630         struct stat statb;
10631
10632         setstackmark(&smark);
10633         mpath = mpathset() ? mpathval() : mailval();
10634         new_hash = 0;
10635         for (;;) {
10636                 p = path_advance(&mpath, nullstr);
10637                 if (p == NULL)
10638                         break;
10639                 if (*p == '\0')
10640                         continue;
10641                 for (q = p; *q; q++)
10642                         continue;
10643 #if DEBUG
10644                 if (q[-1] != '/')
10645                         abort();
10646 #endif
10647                 q[-1] = '\0';                   /* delete trailing '/' */
10648                 if (stat(p, &statb) < 0) {
10649                         continue;
10650                 }
10651                 /* Very simplistic "hash": just a sum of all mtimes */
10652                 new_hash += (unsigned)statb.st_mtime;
10653         }
10654         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10655                 if (mailtime_hash != 0)
10656                         out2str("you have mail\n");
10657                 mailtime_hash = new_hash;
10658         }
10659         mail_var_path_changed = 0;
10660         popstackmark(&smark);
10661 }
10662
10663 static void FAST_FUNC
10664 changemail(const char *val UNUSED_PARAM)
10665 {
10666         mail_var_path_changed = 1;
10667 }
10668
10669 #endif /* ASH_MAIL */
10670
10671
10672 /* ============ ??? */
10673
10674 /*
10675  * Set the shell parameters.
10676  */
10677 static void
10678 setparam(char **argv)
10679 {
10680         char **newparam;
10681         char **ap;
10682         int nparam;
10683
10684         for (nparam = 0; argv[nparam]; nparam++)
10685                 continue;
10686         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10687         while (*argv) {
10688                 *ap++ = ckstrdup(*argv++);
10689         }
10690         *ap = NULL;
10691         freeparam(&shellparam);
10692         shellparam.malloced = 1;
10693         shellparam.nparam = nparam;
10694         shellparam.p = newparam;
10695 #if ENABLE_ASH_GETOPTS
10696         shellparam.optind = 1;
10697         shellparam.optoff = -1;
10698 #endif
10699 }
10700
10701 /*
10702  * Process shell options.  The global variable argptr contains a pointer
10703  * to the argument list; we advance it past the options.
10704  *
10705  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10706  * For a non-interactive shell, an error condition encountered
10707  * by a special built-in ... shall cause the shell to write a diagnostic message
10708  * to standard error and exit as shown in the following table:
10709  * Error                                           Special Built-In
10710  * ...
10711  * Utility syntax error (option or operand error)  Shall exit
10712  * ...
10713  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10714  * we see that bash does not do that (set "finishes" with error code 1 instead,
10715  * and shell continues), and people rely on this behavior!
10716  * Testcase:
10717  * set -o barfoo 2>/dev/null
10718  * echo $?
10719  *
10720  * Oh well. Let's mimic that.
10721  */
10722 static int
10723 plus_minus_o(char *name, int val)
10724 {
10725         int i;
10726
10727         if (name) {
10728                 for (i = 0; i < NOPTS; i++) {
10729                         if (strcmp(name, optnames(i)) == 0) {
10730                                 optlist[i] = val;
10731                                 return 0;
10732                         }
10733                 }
10734                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10735                 return 1;
10736         }
10737         for (i = 0; i < NOPTS; i++) {
10738                 if (val) {
10739                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10740                 } else {
10741                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10742                 }
10743         }
10744         return 0;
10745 }
10746 static void
10747 setoption(int flag, int val)
10748 {
10749         int i;
10750
10751         for (i = 0; i < NOPTS; i++) {
10752                 if (optletters(i) == flag) {
10753                         optlist[i] = val;
10754                         return;
10755                 }
10756         }
10757         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10758         /* NOTREACHED */
10759 }
10760 static int
10761 options(int cmdline, int *login_sh)
10762 {
10763         char *p;
10764         int val;
10765         int c;
10766
10767         if (cmdline)
10768                 minusc = NULL;
10769         while ((p = *argptr) != NULL) {
10770                 c = *p++;
10771                 if (c != '-' && c != '+')
10772                         break;
10773                 argptr++;
10774                 val = 0; /* val = 0 if c == '+' */
10775                 if (c == '-') {
10776                         val = 1;
10777                         if (p[0] == '\0' || LONE_DASH(p)) {
10778                                 if (!cmdline) {
10779                                         /* "-" means turn off -x and -v */
10780                                         if (p[0] == '\0')
10781                                                 xflag = vflag = 0;
10782                                         /* "--" means reset params */
10783                                         else if (*argptr == NULL)
10784                                                 setparam(argptr);
10785                                 }
10786                                 break;    /* "-" or "--" terminates options */
10787                         }
10788                 }
10789                 /* first char was + or - */
10790                 while ((c = *p++) != '\0') {
10791                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10792                         if (c == 'c' && cmdline) {
10793                                 minusc = p;     /* command is after shell args */
10794                         } else if (c == 'o') {
10795                                 if (plus_minus_o(*argptr, val)) {
10796                                         /* it already printed err message */
10797                                         return 1; /* error */
10798                                 }
10799                                 if (*argptr)
10800                                         argptr++;
10801                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10802                                 if (login_sh)
10803                                         *login_sh = 1;
10804                         /* bash does not accept +-login, we also won't */
10805                         } else if (cmdline && val && (c == '-')) { /* long options */
10806                                 if (strcmp(p, "login") == 0) {
10807                                         if (login_sh)
10808                                                 *login_sh = 1;
10809                                 }
10810                                 break;
10811                         } else {
10812                                 setoption(c, val);
10813                         }
10814                 }
10815         }
10816         return 0;
10817 }
10818
10819 /*
10820  * The shift builtin command.
10821  */
10822 static int FAST_FUNC
10823 shiftcmd(int argc UNUSED_PARAM, char **argv)
10824 {
10825         int n;
10826         char **ap1, **ap2;
10827
10828         n = 1;
10829         if (argv[1])
10830                 n = number(argv[1]);
10831         if (n > shellparam.nparam)
10832                 n = 0; /* bash compat, was = shellparam.nparam; */
10833         INT_OFF;
10834         shellparam.nparam -= n;
10835         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10836                 if (shellparam.malloced)
10837                         free(*ap1);
10838         }
10839         ap2 = shellparam.p;
10840         while ((*ap2++ = *ap1++) != NULL)
10841                 continue;
10842 #if ENABLE_ASH_GETOPTS
10843         shellparam.optind = 1;
10844         shellparam.optoff = -1;
10845 #endif
10846         INT_ON;
10847         return 0;
10848 }
10849
10850 /*
10851  * POSIX requires that 'set' (but not export or readonly) output the
10852  * variables in lexicographic order - by the locale's collating order (sigh).
10853  * Maybe we could keep them in an ordered balanced binary tree
10854  * instead of hashed lists.
10855  * For now just roll 'em through qsort for printing...
10856  */
10857 static int
10858 showvars(const char *sep_prefix, int on, int off)
10859 {
10860         const char *sep;
10861         char **ep, **epend;
10862
10863         ep = listvars(on, off, &epend);
10864         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10865
10866         sep = *sep_prefix ? " " : sep_prefix;
10867
10868         for (; ep < epend; ep++) {
10869                 const char *p;
10870                 const char *q;
10871
10872                 p = strchrnul(*ep, '=');
10873                 q = nullstr;
10874                 if (*p)
10875                         q = single_quote(++p);
10876                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10877         }
10878         return 0;
10879 }
10880
10881 /*
10882  * The set command builtin.
10883  */
10884 static int FAST_FUNC
10885 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10886 {
10887         int retval;
10888
10889         if (!argv[1])
10890                 return showvars(nullstr, 0, VUNSET);
10891
10892         INT_OFF;
10893         retval = options(/*cmdline:*/ 0, NULL);
10894         if (retval == 0) { /* if no parse error... */
10895                 optschanged();
10896                 if (*argptr != NULL) {
10897                         setparam(argptr);
10898                 }
10899         }
10900         INT_ON;
10901         return retval;
10902 }
10903
10904 #if ENABLE_ASH_RANDOM_SUPPORT
10905 static void FAST_FUNC
10906 change_random(const char *value)
10907 {
10908         uint32_t t;
10909
10910         if (value == NULL) {
10911                 /* "get", generate */
10912                 t = next_random(&random_gen);
10913                 /* set without recursion */
10914                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10915                 vrandom.flags &= ~VNOFUNC;
10916         } else {
10917                 /* set/reset */
10918                 t = strtoul(value, NULL, 10);
10919                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10920         }
10921 }
10922 #endif
10923
10924 #if ENABLE_ASH_GETOPTS
10925 static int
10926 getopts(char *optstr, char *optvar, char **optfirst)
10927 {
10928         char *p, *q;
10929         char c = '?';
10930         int done = 0;
10931         char sbuf[2];
10932         char **optnext;
10933         int ind = shellparam.optind;
10934         int off = shellparam.optoff;
10935
10936         sbuf[1] = '\0';
10937
10938         shellparam.optind = -1;
10939         optnext = optfirst + ind - 1;
10940
10941         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10942                 p = NULL;
10943         else
10944                 p = optnext[-1] + off;
10945         if (p == NULL || *p == '\0') {
10946                 /* Current word is done, advance */
10947                 p = *optnext;
10948                 if (p == NULL || *p != '-' || *++p == '\0') {
10949  atend:
10950                         p = NULL;
10951                         done = 1;
10952                         goto out;
10953                 }
10954                 optnext++;
10955                 if (LONE_DASH(p))        /* check for "--" */
10956                         goto atend;
10957         }
10958
10959         c = *p++;
10960         for (q = optstr; *q != c;) {
10961                 if (*q == '\0') {
10962                         if (optstr[0] == ':') {
10963                                 sbuf[0] = c;
10964                                 /*sbuf[1] = '\0'; - already is */
10965                                 setvar0("OPTARG", sbuf);
10966                         } else {
10967                                 fprintf(stderr, "Illegal option -%c\n", c);
10968                                 unsetvar("OPTARG");
10969                         }
10970                         c = '?';
10971                         goto out;
10972                 }
10973                 if (*++q == ':')
10974                         q++;
10975         }
10976
10977         if (*++q == ':') {
10978                 if (*p == '\0' && (p = *optnext) == NULL) {
10979                         if (optstr[0] == ':') {
10980                                 sbuf[0] = c;
10981                                 /*sbuf[1] = '\0'; - already is */
10982                                 setvar0("OPTARG", sbuf);
10983                                 c = ':';
10984                         } else {
10985                                 fprintf(stderr, "No arg for -%c option\n", c);
10986                                 unsetvar("OPTARG");
10987                                 c = '?';
10988                         }
10989                         goto out;
10990                 }
10991
10992                 if (p == *optnext)
10993                         optnext++;
10994                 setvar0("OPTARG", p);
10995                 p = NULL;
10996         } else
10997                 setvar0("OPTARG", nullstr);
10998  out:
10999         ind = optnext - optfirst + 1;
11000         setvar("OPTIND", itoa(ind), VNOFUNC);
11001         sbuf[0] = c;
11002         /*sbuf[1] = '\0'; - already is */
11003         setvar0(optvar, sbuf);
11004
11005         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11006         shellparam.optind = ind;
11007
11008         return done;
11009 }
11010
11011 /*
11012  * The getopts builtin.  Shellparam.optnext points to the next argument
11013  * to be processed.  Shellparam.optptr points to the next character to
11014  * be processed in the current argument.  If shellparam.optnext is NULL,
11015  * then it's the first time getopts has been called.
11016  */
11017 static int FAST_FUNC
11018 getoptscmd(int argc, char **argv)
11019 {
11020         char **optbase;
11021
11022         if (argc < 3)
11023                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11024         if (argc == 3) {
11025                 optbase = shellparam.p;
11026                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11027                         shellparam.optind = 1;
11028                         shellparam.optoff = -1;
11029                 }
11030         } else {
11031                 optbase = &argv[3];
11032                 if ((unsigned)shellparam.optind > argc - 2) {
11033                         shellparam.optind = 1;
11034                         shellparam.optoff = -1;
11035                 }
11036         }
11037
11038         return getopts(argv[1], argv[2], optbase);
11039 }
11040 #endif /* ASH_GETOPTS */
11041
11042
11043 /* ============ Shell parser */
11044
11045 struct heredoc {
11046         struct heredoc *next;   /* next here document in list */
11047         union node *here;       /* redirection node */
11048         char *eofmark;          /* string indicating end of input */
11049         smallint striptabs;     /* if set, strip leading tabs */
11050 };
11051
11052 static smallint tokpushback;           /* last token pushed back */
11053 static smallint quoteflag;             /* set if (part of) last token was quoted */
11054 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11055 static struct heredoc *heredoclist;    /* list of here documents to read */
11056 static char *wordtext;                 /* text of last word returned by readtoken */
11057 static struct nodelist *backquotelist;
11058 static union node *redirnode;
11059 static struct heredoc *heredoc;
11060
11061 static const char *
11062 tokname(char *buf, int tok)
11063 {
11064         if (tok < TSEMI)
11065                 return tokname_array[tok];
11066         sprintf(buf, "\"%s\"", tokname_array[tok]);
11067         return buf;
11068 }
11069
11070 /* raise_error_unexpected_syntax:
11071  * Called when an unexpected token is read during the parse.  The argument
11072  * is the token that is expected, or -1 if more than one type of token can
11073  * occur at this point.
11074  */
11075 static void raise_error_unexpected_syntax(int) NORETURN;
11076 static void
11077 raise_error_unexpected_syntax(int token)
11078 {
11079         char msg[64];
11080         char buf[16];
11081         int l;
11082
11083         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11084         if (token >= 0)
11085                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11086         raise_error_syntax(msg);
11087         /* NOTREACHED */
11088 }
11089
11090 /* parsing is heavily cross-recursive, need these forward decls */
11091 static union node *andor(void);
11092 static union node *pipeline(void);
11093 static union node *parse_command(void);
11094 static void parseheredoc(void);
11095 static int peektoken(void);
11096 static int readtoken(void);
11097
11098 static union node *
11099 list(int nlflag)
11100 {
11101         union node *n1, *n2, *n3;
11102         int tok;
11103
11104         n1 = NULL;
11105         for (;;) {
11106                 switch (peektoken()) {
11107                 case TNL:
11108                         if (!(nlflag & 1))
11109                                 break;
11110                         parseheredoc();
11111                         return n1;
11112
11113                 case TEOF:
11114                         if (!n1 && (nlflag & 1))
11115                                 n1 = NODE_EOF;
11116                         parseheredoc();
11117                         return n1;
11118                 }
11119
11120                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11121                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11122                         return n1;
11123                 nlflag |= 2;
11124
11125                 n2 = andor();
11126                 tok = readtoken();
11127                 if (tok == TBACKGND) {
11128                         if (n2->type == NPIPE) {
11129                                 n2->npipe.pipe_backgnd = 1;
11130                         } else {
11131                                 if (n2->type != NREDIR) {
11132                                         n3 = stzalloc(sizeof(struct nredir));
11133                                         n3->nredir.n = n2;
11134                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11135                                         n2 = n3;
11136                                 }
11137                                 n2->type = NBACKGND;
11138                         }
11139                 }
11140                 if (n1 == NULL) {
11141                         n1 = n2;
11142                 } else {
11143                         n3 = stzalloc(sizeof(struct nbinary));
11144                         n3->type = NSEMI;
11145                         n3->nbinary.ch1 = n1;
11146                         n3->nbinary.ch2 = n2;
11147                         n1 = n3;
11148                 }
11149                 switch (tok) {
11150                 case TNL:
11151                 case TEOF:
11152                         tokpushback = 1;
11153                         /* fall through */
11154                 case TBACKGND:
11155                 case TSEMI:
11156                         break;
11157                 default:
11158                         if ((nlflag & 1))
11159                                 raise_error_unexpected_syntax(-1);
11160                         tokpushback = 1;
11161                         return n1;
11162                 }
11163         }
11164 }
11165
11166 static union node *
11167 andor(void)
11168 {
11169         union node *n1, *n2, *n3;
11170         int t;
11171
11172         n1 = pipeline();
11173         for (;;) {
11174                 t = readtoken();
11175                 if (t == TAND) {
11176                         t = NAND;
11177                 } else if (t == TOR) {
11178                         t = NOR;
11179                 } else {
11180                         tokpushback = 1;
11181                         return n1;
11182                 }
11183                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11184                 n2 = pipeline();
11185                 n3 = stzalloc(sizeof(struct nbinary));
11186                 n3->type = t;
11187                 n3->nbinary.ch1 = n1;
11188                 n3->nbinary.ch2 = n2;
11189                 n1 = n3;
11190         }
11191 }
11192
11193 static union node *
11194 pipeline(void)
11195 {
11196         union node *n1, *n2, *pipenode;
11197         struct nodelist *lp, *prev;
11198         int negate;
11199
11200         negate = 0;
11201         TRACE(("pipeline: entered\n"));
11202         if (readtoken() == TNOT) {
11203                 negate = !negate;
11204                 checkkwd = CHKKWD | CHKALIAS;
11205         } else
11206                 tokpushback = 1;
11207         n1 = parse_command();
11208         if (readtoken() == TPIPE) {
11209                 pipenode = stzalloc(sizeof(struct npipe));
11210                 pipenode->type = NPIPE;
11211                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11212                 lp = stzalloc(sizeof(struct nodelist));
11213                 pipenode->npipe.cmdlist = lp;
11214                 lp->n = n1;
11215                 do {
11216                         prev = lp;
11217                         lp = stzalloc(sizeof(struct nodelist));
11218                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11219                         lp->n = parse_command();
11220                         prev->next = lp;
11221                 } while (readtoken() == TPIPE);
11222                 lp->next = NULL;
11223                 n1 = pipenode;
11224         }
11225         tokpushback = 1;
11226         if (negate) {
11227                 n2 = stzalloc(sizeof(struct nnot));
11228                 n2->type = NNOT;
11229                 n2->nnot.com = n1;
11230                 return n2;
11231         }
11232         return n1;
11233 }
11234
11235 static union node *
11236 makename(void)
11237 {
11238         union node *n;
11239
11240         n = stzalloc(sizeof(struct narg));
11241         n->type = NARG;
11242         /*n->narg.next = NULL; - stzalloc did it */
11243         n->narg.text = wordtext;
11244         n->narg.backquote = backquotelist;
11245         return n;
11246 }
11247
11248 static void
11249 fixredir(union node *n, const char *text, int err)
11250 {
11251         int fd;
11252
11253         TRACE(("Fix redir %s %d\n", text, err));
11254         if (!err)
11255                 n->ndup.vname = NULL;
11256
11257         fd = bb_strtou(text, NULL, 10);
11258         if (!errno && fd >= 0)
11259                 n->ndup.dupfd = fd;
11260         else if (LONE_DASH(text))
11261                 n->ndup.dupfd = -1;
11262         else {
11263                 if (err)
11264                         raise_error_syntax("bad fd number");
11265                 n->ndup.vname = makename();
11266         }
11267 }
11268
11269 static void
11270 parsefname(void)
11271 {
11272         union node *n = redirnode;
11273
11274         if (n->type == NHERE)
11275                 checkkwd = CHKEOFMARK;
11276         if (readtoken() != TWORD)
11277                 raise_error_unexpected_syntax(-1);
11278         if (n->type == NHERE) {
11279                 struct heredoc *here = heredoc;
11280                 struct heredoc *p;
11281
11282                 if (quoteflag == 0)
11283                         n->type = NXHERE;
11284                 TRACE(("Here document %d\n", n->type));
11285                 rmescapes(wordtext, 0);
11286                 here->eofmark = wordtext;
11287                 here->next = NULL;
11288                 if (heredoclist == NULL)
11289                         heredoclist = here;
11290                 else {
11291                         for (p = heredoclist; p->next; p = p->next)
11292                                 continue;
11293                         p->next = here;
11294                 }
11295         } else if (n->type == NTOFD || n->type == NFROMFD) {
11296                 fixredir(n, wordtext, 0);
11297         } else {
11298                 n->nfile.fname = makename();
11299         }
11300 }
11301
11302 static union node *
11303 simplecmd(void)
11304 {
11305         union node *args, **app;
11306         union node *n = NULL;
11307         union node *vars, **vpp;
11308         union node **rpp, *redir;
11309         int savecheckkwd;
11310 #if BASH_TEST2
11311         smallint double_brackets_flag = 0;
11312 #endif
11313         IF_BASH_FUNCTION(smallint function_flag = 0;)
11314
11315         args = NULL;
11316         app = &args;
11317         vars = NULL;
11318         vpp = &vars;
11319         redir = NULL;
11320         rpp = &redir;
11321
11322         savecheckkwd = CHKALIAS;
11323         for (;;) {
11324                 int t;
11325                 checkkwd = savecheckkwd;
11326                 t = readtoken();
11327                 switch (t) {
11328 #if BASH_FUNCTION
11329                 case TFUNCTION:
11330                         if (peektoken() != TWORD)
11331                                 raise_error_unexpected_syntax(TWORD);
11332                         function_flag = 1;
11333                         break;
11334 #endif
11335 #if BASH_TEST2
11336                 case TAND: /* "&&" */
11337                 case TOR: /* "||" */
11338                         if (!double_brackets_flag) {
11339                                 tokpushback = 1;
11340                                 goto out;
11341                         }
11342                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11343 #endif
11344                 case TWORD:
11345                         n = stzalloc(sizeof(struct narg));
11346                         n->type = NARG;
11347                         /*n->narg.next = NULL; - stzalloc did it */
11348                         n->narg.text = wordtext;
11349 #if BASH_TEST2
11350                         if (strcmp("[[", wordtext) == 0)
11351                                 double_brackets_flag = 1;
11352                         else if (strcmp("]]", wordtext) == 0)
11353                                 double_brackets_flag = 0;
11354 #endif
11355                         n->narg.backquote = backquotelist;
11356                         if (savecheckkwd && isassignment(wordtext)) {
11357                                 *vpp = n;
11358                                 vpp = &n->narg.next;
11359                         } else {
11360                                 *app = n;
11361                                 app = &n->narg.next;
11362                                 savecheckkwd = 0;
11363                         }
11364 #if BASH_FUNCTION
11365                         if (function_flag) {
11366                                 checkkwd = CHKNL | CHKKWD;
11367                                 switch (peektoken()) {
11368                                 case TBEGIN:
11369                                 case TIF:
11370                                 case TCASE:
11371                                 case TUNTIL:
11372                                 case TWHILE:
11373                                 case TFOR:
11374                                         goto do_func;
11375                                 case TLP:
11376                                         function_flag = 0;
11377                                         break;
11378                                 case TWORD:
11379                                         if (strcmp("[[", wordtext) == 0)
11380                                                 goto do_func;
11381                                         /* fall through */
11382                                 default:
11383                                         raise_error_unexpected_syntax(-1);
11384                                 }
11385                         }
11386 #endif
11387                         break;
11388                 case TREDIR:
11389                         *rpp = n = redirnode;
11390                         rpp = &n->nfile.next;
11391                         parsefname();   /* read name of redirection file */
11392                         break;
11393                 case TLP:
11394  IF_BASH_FUNCTION(do_func:)
11395                         if (args && app == &args->narg.next
11396                          && !vars && !redir
11397                         ) {
11398                                 struct builtincmd *bcmd;
11399                                 const char *name;
11400
11401                                 /* We have a function */
11402                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11403                                         raise_error_unexpected_syntax(TRP);
11404                                 name = n->narg.text;
11405                                 if (!goodname(name)
11406                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11407                                 ) {
11408                                         raise_error_syntax("bad function name");
11409                                 }
11410                                 n->type = NDEFUN;
11411                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11412                                 n->narg.next = parse_command();
11413                                 return n;
11414                         }
11415                         IF_BASH_FUNCTION(function_flag = 0;)
11416                         /* fall through */
11417                 default:
11418                         tokpushback = 1;
11419                         goto out;
11420                 }
11421         }
11422  out:
11423         *app = NULL;
11424         *vpp = NULL;
11425         *rpp = NULL;
11426         n = stzalloc(sizeof(struct ncmd));
11427         n->type = NCMD;
11428         n->ncmd.args = args;
11429         n->ncmd.assign = vars;
11430         n->ncmd.redirect = redir;
11431         return n;
11432 }
11433
11434 static union node *
11435 parse_command(void)
11436 {
11437         union node *n1, *n2;
11438         union node *ap, **app;
11439         union node *cp, **cpp;
11440         union node *redir, **rpp;
11441         union node **rpp2;
11442         int t;
11443
11444         redir = NULL;
11445         rpp2 = &redir;
11446
11447         switch (readtoken()) {
11448         default:
11449                 raise_error_unexpected_syntax(-1);
11450                 /* NOTREACHED */
11451         case TIF:
11452                 n1 = stzalloc(sizeof(struct nif));
11453                 n1->type = NIF;
11454                 n1->nif.test = list(0);
11455                 if (readtoken() != TTHEN)
11456                         raise_error_unexpected_syntax(TTHEN);
11457                 n1->nif.ifpart = list(0);
11458                 n2 = n1;
11459                 while (readtoken() == TELIF) {
11460                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11461                         n2 = n2->nif.elsepart;
11462                         n2->type = NIF;
11463                         n2->nif.test = list(0);
11464                         if (readtoken() != TTHEN)
11465                                 raise_error_unexpected_syntax(TTHEN);
11466                         n2->nif.ifpart = list(0);
11467                 }
11468                 if (lasttoken == TELSE)
11469                         n2->nif.elsepart = list(0);
11470                 else {
11471                         n2->nif.elsepart = NULL;
11472                         tokpushback = 1;
11473                 }
11474                 t = TFI;
11475                 break;
11476         case TWHILE:
11477         case TUNTIL: {
11478                 int got;
11479                 n1 = stzalloc(sizeof(struct nbinary));
11480                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11481                 n1->nbinary.ch1 = list(0);
11482                 got = readtoken();
11483                 if (got != TDO) {
11484                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11485                                         got == TWORD ? wordtext : ""));
11486                         raise_error_unexpected_syntax(TDO);
11487                 }
11488                 n1->nbinary.ch2 = list(0);
11489                 t = TDONE;
11490                 break;
11491         }
11492         case TFOR:
11493                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11494                         raise_error_syntax("bad for loop variable");
11495                 n1 = stzalloc(sizeof(struct nfor));
11496                 n1->type = NFOR;
11497                 n1->nfor.var = wordtext;
11498                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11499                 if (readtoken() == TIN) {
11500                         app = &ap;
11501                         while (readtoken() == TWORD) {
11502                                 n2 = stzalloc(sizeof(struct narg));
11503                                 n2->type = NARG;
11504                                 /*n2->narg.next = NULL; - stzalloc did it */
11505                                 n2->narg.text = wordtext;
11506                                 n2->narg.backquote = backquotelist;
11507                                 *app = n2;
11508                                 app = &n2->narg.next;
11509                         }
11510                         *app = NULL;
11511                         n1->nfor.args = ap;
11512                         if (lasttoken != TNL && lasttoken != TSEMI)
11513                                 raise_error_unexpected_syntax(-1);
11514                 } else {
11515                         n2 = stzalloc(sizeof(struct narg));
11516                         n2->type = NARG;
11517                         /*n2->narg.next = NULL; - stzalloc did it */
11518                         n2->narg.text = (char *)dolatstr;
11519                         /*n2->narg.backquote = NULL;*/
11520                         n1->nfor.args = n2;
11521                         /*
11522                          * Newline or semicolon here is optional (but note
11523                          * that the original Bourne shell only allowed NL).
11524                          */
11525                         if (lasttoken != TSEMI)
11526                                 tokpushback = 1;
11527                 }
11528                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11529                 if (readtoken() != TDO)
11530                         raise_error_unexpected_syntax(TDO);
11531                 n1->nfor.body = list(0);
11532                 t = TDONE;
11533                 break;
11534         case TCASE:
11535                 n1 = stzalloc(sizeof(struct ncase));
11536                 n1->type = NCASE;
11537                 if (readtoken() != TWORD)
11538                         raise_error_unexpected_syntax(TWORD);
11539                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11540                 n2->type = NARG;
11541                 /*n2->narg.next = NULL; - stzalloc did it */
11542                 n2->narg.text = wordtext;
11543                 n2->narg.backquote = backquotelist;
11544                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11545                 if (readtoken() != TIN)
11546                         raise_error_unexpected_syntax(TIN);
11547                 cpp = &n1->ncase.cases;
11548  next_case:
11549                 checkkwd = CHKNL | CHKKWD;
11550                 t = readtoken();
11551                 while (t != TESAC) {
11552                         if (lasttoken == TLP)
11553                                 readtoken();
11554                         *cpp = cp = stzalloc(sizeof(struct nclist));
11555                         cp->type = NCLIST;
11556                         app = &cp->nclist.pattern;
11557                         for (;;) {
11558                                 *app = ap = stzalloc(sizeof(struct narg));
11559                                 ap->type = NARG;
11560                                 /*ap->narg.next = NULL; - stzalloc did it */
11561                                 ap->narg.text = wordtext;
11562                                 ap->narg.backquote = backquotelist;
11563                                 if (readtoken() != TPIPE)
11564                                         break;
11565                                 app = &ap->narg.next;
11566                                 readtoken();
11567                         }
11568                         //ap->narg.next = NULL;
11569                         if (lasttoken != TRP)
11570                                 raise_error_unexpected_syntax(TRP);
11571                         cp->nclist.body = list(2);
11572
11573                         cpp = &cp->nclist.next;
11574
11575                         checkkwd = CHKNL | CHKKWD;
11576                         t = readtoken();
11577                         if (t != TESAC) {
11578                                 if (t != TENDCASE)
11579                                         raise_error_unexpected_syntax(TENDCASE);
11580                                 goto next_case;
11581                         }
11582                 }
11583                 *cpp = NULL;
11584                 goto redir;
11585         case TLP:
11586                 n1 = stzalloc(sizeof(struct nredir));
11587                 n1->type = NSUBSHELL;
11588                 n1->nredir.n = list(0);
11589                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11590                 t = TRP;
11591                 break;
11592         case TBEGIN:
11593                 n1 = list(0);
11594                 t = TEND;
11595                 break;
11596         IF_BASH_FUNCTION(case TFUNCTION:)
11597         case TWORD:
11598         case TREDIR:
11599                 tokpushback = 1;
11600                 return simplecmd();
11601         }
11602
11603         if (readtoken() != t)
11604                 raise_error_unexpected_syntax(t);
11605
11606  redir:
11607         /* Now check for redirection which may follow command */
11608         checkkwd = CHKKWD | CHKALIAS;
11609         rpp = rpp2;
11610         while (readtoken() == TREDIR) {
11611                 *rpp = n2 = redirnode;
11612                 rpp = &n2->nfile.next;
11613                 parsefname();
11614         }
11615         tokpushback = 1;
11616         *rpp = NULL;
11617         if (redir) {
11618                 if (n1->type != NSUBSHELL) {
11619                         n2 = stzalloc(sizeof(struct nredir));
11620                         n2->type = NREDIR;
11621                         n2->nredir.n = n1;
11622                         n1 = n2;
11623                 }
11624                 n1->nredir.redirect = redir;
11625         }
11626         return n1;
11627 }
11628
11629 #if BASH_DOLLAR_SQUOTE
11630 static int
11631 decode_dollar_squote(void)
11632 {
11633         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11634         int c, cnt;
11635         char *p;
11636         char buf[4];
11637
11638         c = pgetc();
11639         p = strchr(C_escapes, c);
11640         if (p) {
11641                 buf[0] = c;
11642                 p = buf;
11643                 cnt = 3;
11644                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11645                         do {
11646                                 c = pgetc();
11647                                 *++p = c;
11648                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11649                         pungetc();
11650                 } else if (c == 'x') { /* \xHH */
11651                         do {
11652                                 c = pgetc();
11653                                 *++p = c;
11654                         } while (isxdigit(c) && --cnt);
11655                         pungetc();
11656                         if (cnt == 3) { /* \x but next char is "bad" */
11657                                 c = 'x';
11658                                 goto unrecognized;
11659                         }
11660                 } else { /* simple seq like \\ or \t */
11661                         p++;
11662                 }
11663                 *p = '\0';
11664                 p = buf;
11665                 c = bb_process_escape_sequence((void*)&p);
11666         } else { /* unrecognized "\z": print both chars unless ' or " */
11667                 if (c != '\'' && c != '"') {
11668  unrecognized:
11669                         c |= 0x100; /* "please encode \, then me" */
11670                 }
11671         }
11672         return c;
11673 }
11674 #endif
11675
11676 /* Used by expandstr to get here-doc like behaviour. */
11677 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11678
11679 static ALWAYS_INLINE int
11680 realeofmark(const char *eofmark)
11681 {
11682         return eofmark && eofmark != FAKEEOFMARK;
11683 }
11684
11685 /*
11686  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11687  * is not NULL, read a here document.  In the latter case, eofmark is the
11688  * word which marks the end of the document and striptabs is true if
11689  * leading tabs should be stripped from the document.  The argument c
11690  * is the first character of the input token or document.
11691  *
11692  * Because C does not have internal subroutines, I have simulated them
11693  * using goto's to implement the subroutine linkage.  The following macros
11694  * will run code that appears at the end of readtoken1.
11695  */
11696 #define CHECKEND()      {goto checkend; checkend_return:;}
11697 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11698 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11699 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11700 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11701 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11702 static int
11703 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11704 {
11705         /* NB: syntax parameter fits into smallint */
11706         /* c parameter is an unsigned char or PEOF or PEOA */
11707         char *out;
11708         size_t len;
11709         struct nodelist *bqlist;
11710         smallint quotef;
11711         smallint dblquote;
11712         smallint oldstyle;
11713         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11714         smallint pssyntax;   /* we are expanding a prompt string */
11715         int varnest;         /* levels of variables expansion */
11716         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11717         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11718         int dqvarnest;       /* levels of variables expansion within double quotes */
11719
11720         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11721
11722         startlinno = g_parsefile->linno;
11723         bqlist = NULL;
11724         quotef = 0;
11725         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11726 #if ENABLE_ASH_EXPAND_PRMT
11727         pssyntax = (syntax == PSSYNTAX);
11728         if (pssyntax)
11729                 syntax = DQSYNTAX;
11730 #else
11731         pssyntax = 0; /* constant */
11732 #endif
11733         dblquote = (syntax == DQSYNTAX);
11734         varnest = 0;
11735         IF_FEATURE_SH_MATH(arinest = 0;)
11736         IF_FEATURE_SH_MATH(parenlevel = 0;)
11737         dqvarnest = 0;
11738
11739         STARTSTACKSTR(out);
11740  loop:
11741         /* For each line, until end of word */
11742         CHECKEND();     /* set c to PEOF if at end of here document */
11743         for (;;) {      /* until end of line or end of word */
11744                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11745                 switch (SIT(c, syntax)) {
11746                 case CNL:       /* '\n' */
11747                         if (syntax == BASESYNTAX)
11748                                 goto endword;   /* exit outer loop */
11749                         USTPUTC(c, out);
11750                         nlprompt();
11751                         c = pgetc();
11752                         goto loop;              /* continue outer loop */
11753                 case CWORD:
11754                         USTPUTC(c, out);
11755                         break;
11756                 case CCTL:
11757 #if BASH_DOLLAR_SQUOTE
11758                         if (c == '\\' && bash_dollar_squote) {
11759                                 c = decode_dollar_squote();
11760                                 if (c == '\0') {
11761                                         /* skip $'\000', $'\x00' (like bash) */
11762                                         break;
11763                                 }
11764                                 if (c & 0x100) {
11765                                         /* Unknown escape. Encode as '\z' */
11766                                         c = (unsigned char)c;
11767                                         if (eofmark == NULL || dblquote)
11768                                                 USTPUTC(CTLESC, out);
11769                                         USTPUTC('\\', out);
11770                                 }
11771                         }
11772 #endif
11773                         if (eofmark == NULL || dblquote)
11774                                 USTPUTC(CTLESC, out);
11775                         USTPUTC(c, out);
11776                         break;
11777                 case CBACK:     /* backslash */
11778                         c = pgetc_without_PEOA();
11779                         if (c == PEOF) {
11780                                 USTPUTC(CTLESC, out);
11781                                 USTPUTC('\\', out);
11782                                 pungetc();
11783                         } else if (c == '\n') {
11784                                 nlprompt();
11785                         } else {
11786                                 if (pssyntax && c == '$') {
11787                                         USTPUTC(CTLESC, out);
11788                                         USTPUTC('\\', out);
11789                                 }
11790                                 /* Backslash is retained if we are in "str" and next char isn't special */
11791                                 if (dblquote
11792                                  && c != '\\'
11793                                  && c != '`'
11794                                  && c != '$'
11795                                  && (c != '"' || eofmark != NULL)
11796                                 ) {
11797                                         USTPUTC('\\', out);
11798                                 }
11799                                 USTPUTC(CTLESC, out);
11800                                 USTPUTC(c, out);
11801                                 quotef = 1;
11802                         }
11803                         break;
11804                 case CSQUOTE:
11805                         syntax = SQSYNTAX;
11806  quotemark:
11807                         if (eofmark == NULL) {
11808                                 USTPUTC(CTLQUOTEMARK, out);
11809                         }
11810                         break;
11811                 case CDQUOTE:
11812                         syntax = DQSYNTAX;
11813                         dblquote = 1;
11814                         goto quotemark;
11815                 case CENDQUOTE:
11816                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11817                         if (eofmark != NULL && varnest == 0) {
11818                                 USTPUTC(c, out);
11819                         } else {
11820                                 if (dqvarnest == 0) {
11821                                         syntax = BASESYNTAX;
11822                                         dblquote = 0;
11823                                 }
11824                                 quotef = 1;
11825                                 goto quotemark;
11826                         }
11827                         break;
11828                 case CVAR:      /* '$' */
11829                         PARSESUB();             /* parse substitution */
11830                         break;
11831                 case CENDVAR:   /* '}' */
11832                         if (varnest > 0) {
11833                                 varnest--;
11834                                 if (dqvarnest > 0) {
11835                                         dqvarnest--;
11836                                 }
11837                                 c = CTLENDVAR;
11838                         }
11839                         USTPUTC(c, out);
11840                         break;
11841 #if ENABLE_FEATURE_SH_MATH
11842                 case CLP:       /* '(' in arithmetic */
11843                         parenlevel++;
11844                         USTPUTC(c, out);
11845                         break;
11846                 case CRP:       /* ')' in arithmetic */
11847                         if (parenlevel > 0) {
11848                                 parenlevel--;
11849                         } else {
11850                                 if (pgetc_eatbnl() == ')') {
11851                                         c = CTLENDARI;
11852                                         if (--arinest == 0) {
11853                                                 syntax = prevsyntax;
11854                                         }
11855                                 } else {
11856                                         /*
11857                                          * unbalanced parens
11858                                          * (don't 2nd guess - no error)
11859                                          */
11860                                         pungetc();
11861                                 }
11862                         }
11863                         USTPUTC(c, out);
11864                         break;
11865 #endif
11866                 case CBQUOTE:   /* '`' */
11867                         PARSEBACKQOLD();
11868                         break;
11869                 case CENDFILE:
11870                         goto endword;           /* exit outer loop */
11871                 case CIGN:
11872                         break;
11873                 default:
11874                         if (varnest == 0) {
11875 #if BASH_REDIR_OUTPUT
11876                                 if (c == '&') {
11877 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11878                                         if (pgetc() == '>')
11879                                                 c = 0x100 + '>'; /* flag &> */
11880                                         pungetc();
11881                                 }
11882 #endif
11883                                 goto endword;   /* exit outer loop */
11884                         }
11885                         IF_ASH_ALIAS(if (c != PEOA))
11886                                 USTPUTC(c, out);
11887                 }
11888                 c = pgetc();
11889         } /* for (;;) */
11890  endword:
11891
11892 #if ENABLE_FEATURE_SH_MATH
11893         if (syntax == ARISYNTAX)
11894                 raise_error_syntax("missing '))'");
11895 #endif
11896         if (syntax != BASESYNTAX && eofmark == NULL)
11897                 raise_error_syntax("unterminated quoted string");
11898         if (varnest != 0) {
11899                 startlinno = g_parsefile->linno;
11900                 /* { */
11901                 raise_error_syntax("missing '}'");
11902         }
11903         USTPUTC('\0', out);
11904         len = out - (char *)stackblock();
11905         out = stackblock();
11906         if (eofmark == NULL) {
11907                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11908                  && quotef == 0
11909                 ) {
11910                         if (isdigit_str9(out)) {
11911                                 PARSEREDIR(); /* passed as params: out, c */
11912                                 lasttoken = TREDIR;
11913                                 return lasttoken;
11914                         }
11915                         /* else: non-number X seen, interpret it
11916                          * as "NNNX>file" = "NNNX >file" */
11917                 }
11918                 pungetc();
11919         }
11920         quoteflag = quotef;
11921         backquotelist = bqlist;
11922         grabstackblock(len);
11923         wordtext = out;
11924         lasttoken = TWORD;
11925         return lasttoken;
11926 /* end of readtoken routine */
11927
11928 /*
11929  * Check to see whether we are at the end of the here document.  When this
11930  * is called, c is set to the first character of the next input line.  If
11931  * we are at the end of the here document, this routine sets the c to PEOF.
11932  */
11933 checkend: {
11934         if (realeofmark(eofmark)) {
11935                 int markloc;
11936                 char *p;
11937
11938 #if ENABLE_ASH_ALIAS
11939                 if (c == PEOA)
11940                         c = pgetc_without_PEOA();
11941 #endif
11942                 if (striptabs) {
11943                         while (c == '\t') {
11944                                 c = pgetc_without_PEOA();
11945                         }
11946                 }
11947
11948                 markloc = out - (char *)stackblock();
11949                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11950                         if (c != *p)
11951                                 goto more_heredoc;
11952
11953                         c = pgetc_without_PEOA();
11954                 }
11955
11956                 if (c == '\n' || c == PEOF) {
11957                         c = PEOF;
11958                         g_parsefile->linno++;
11959                         needprompt = doprompt;
11960                 } else {
11961                         int len_here;
11962
11963  more_heredoc:
11964                         p = (char *)stackblock() + markloc + 1;
11965                         len_here = out - p;
11966
11967                         if (len_here) {
11968                                 len_here -= (c >= PEOF);
11969                                 c = p[-1];
11970
11971                                 if (len_here) {
11972                                         char *str;
11973
11974                                         str = alloca(len_here + 1);
11975                                         *(char *)mempcpy(str, p, len_here) = '\0';
11976
11977                                         pushstring(str, NULL);
11978                                 }
11979                         }
11980                 }
11981
11982                 STADJUST((char *)stackblock() + markloc - out, out);
11983         }
11984         goto checkend_return;
11985 }
11986
11987 /*
11988  * Parse a redirection operator.  The variable "out" points to a string
11989  * specifying the fd to be redirected.  The variable "c" contains the
11990  * first character of the redirection operator.
11991  */
11992 parseredir: {
11993         /* out is already checked to be a valid number or "" */
11994         int fd = (*out == '\0' ? -1 : atoi(out));
11995         union node *np;
11996
11997         np = stzalloc(sizeof(struct nfile));
11998         if (c == '>') {
11999                 np->nfile.fd = 1;
12000                 c = pgetc();
12001                 if (c == '>')
12002                         np->type = NAPPEND;
12003                 else if (c == '|')
12004                         np->type = NCLOBBER;
12005                 else if (c == '&')
12006                         np->type = NTOFD;
12007                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12008                 else {
12009                         np->type = NTO;
12010                         pungetc();
12011                 }
12012         }
12013 #if BASH_REDIR_OUTPUT
12014         else if (c == 0x100 + '>') { /* this flags &> redirection */
12015                 np->nfile.fd = 1;
12016                 pgetc(); /* this is '>', no need to check */
12017                 np->type = NTO2;
12018         }
12019 #endif
12020         else { /* c == '<' */
12021                 /*np->nfile.fd = 0; - stzalloc did it */
12022                 c = pgetc();
12023                 switch (c) {
12024                 case '<':
12025                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12026                                 np = stzalloc(sizeof(struct nhere));
12027                                 /*np->nfile.fd = 0; - stzalloc did it */
12028                         }
12029                         np->type = NHERE;
12030                         heredoc = stzalloc(sizeof(struct heredoc));
12031                         heredoc->here = np;
12032                         c = pgetc();
12033                         if (c == '-') {
12034                                 heredoc->striptabs = 1;
12035                         } else {
12036                                 /*heredoc->striptabs = 0; - stzalloc did it */
12037                                 pungetc();
12038                         }
12039                         break;
12040
12041                 case '&':
12042                         np->type = NFROMFD;
12043                         break;
12044
12045                 case '>':
12046                         np->type = NFROMTO;
12047                         break;
12048
12049                 default:
12050                         np->type = NFROM;
12051                         pungetc();
12052                         break;
12053                 }
12054         }
12055         if (fd >= 0)
12056                 np->nfile.fd = fd;
12057         redirnode = np;
12058         goto parseredir_return;
12059 }
12060
12061 /*
12062  * Parse a substitution.  At this point, we have read the dollar sign
12063  * and nothing else.
12064  */
12065
12066 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12067  * (assuming ascii char codes, as the original implementation did) */
12068 #define is_special(c) \
12069         (((unsigned)(c) - 33 < 32) \
12070                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12071 parsesub: {
12072         unsigned char subtype;
12073         int typeloc;
12074
12075         c = pgetc_eatbnl();
12076         if ((checkkwd & CHKEOFMARK)
12077          || c > 255 /* PEOA or PEOF */
12078          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12079         ) {
12080 #if BASH_DOLLAR_SQUOTE
12081                 if (syntax != DQSYNTAX && c == '\'')
12082                         bash_dollar_squote = 1;
12083                 else
12084 #endif
12085                         USTPUTC('$', out);
12086                 pungetc();
12087         } else if (c == '(') {
12088                 /* $(command) or $((arith)) */
12089                 if (pgetc_eatbnl() == '(') {
12090 #if ENABLE_FEATURE_SH_MATH
12091                         PARSEARITH();
12092 #else
12093                         raise_error_syntax("support for $((arith)) is disabled");
12094 #endif
12095                 } else {
12096                         pungetc();
12097                         PARSEBACKQNEW();
12098                 }
12099         } else {
12100                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12101                 USTPUTC(CTLVAR, out);
12102                 typeloc = out - (char *)stackblock();
12103                 STADJUST(1, out);
12104                 subtype = VSNORMAL;
12105                 if (c == '{') {
12106                         c = pgetc_eatbnl();
12107                         subtype = 0;
12108                 }
12109  varname:
12110                 if (is_name(c)) {
12111                         /* $[{[#]]NAME[}] */
12112                         do {
12113                                 STPUTC(c, out);
12114                                 c = pgetc_eatbnl();
12115                         } while (is_in_name(c));
12116                 } else if (isdigit(c)) {
12117                         /* $[{[#]]NUM[}] */
12118                         do {
12119                                 STPUTC(c, out);
12120                                 c = pgetc_eatbnl();
12121                         } while (isdigit(c));
12122                 } else if (is_special(c)) {
12123                         /* $[{[#]]<specialchar>[}] */
12124                         int cc = c;
12125
12126                         c = pgetc_eatbnl();
12127                         if (!subtype && cc == '#') {
12128                                 subtype = VSLENGTH;
12129                                 if (c == '_' || isalnum(c))
12130                                         goto varname;
12131                                 cc = c;
12132                                 c = pgetc_eatbnl();
12133                                 if (cc == '}' || c != '}') {
12134                                         pungetc();
12135                                         subtype = 0;
12136                                         c = cc;
12137                                         cc = '#';
12138                                 }
12139                         }
12140                         USTPUTC(cc, out);
12141                 } else {
12142                         goto badsub;
12143                 }
12144                 if (c != '}' && subtype == VSLENGTH) {
12145                         /* ${#VAR didn't end with } */
12146                         goto badsub;
12147                 }
12148
12149                 if (subtype == 0) {
12150                         static const char types[] ALIGN1 = "}-+?=";
12151                         /* ${VAR...} but not $VAR or ${#VAR} */
12152                         /* c == first char after VAR */
12153                         switch (c) {
12154                         case ':':
12155                                 c = pgetc_eatbnl();
12156 #if BASH_SUBSTR
12157                                 /* This check is only needed to not misinterpret
12158                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12159                                  * constructs.
12160                                  */
12161                                 if (!strchr(types, c)) {
12162                                         subtype = VSSUBSTR;
12163                                         pungetc();
12164                                         break; /* "goto badsub" is bigger (!) */
12165                                 }
12166 #endif
12167                                 subtype = VSNUL;
12168                                 /*FALLTHROUGH*/
12169                         default: {
12170                                 const char *p = strchr(types, c);
12171                                 if (p == NULL)
12172                                         break;
12173                                 subtype |= p - types + VSNORMAL;
12174                                 break;
12175                         }
12176                         case '%':
12177                         case '#': {
12178                                 int cc = c;
12179                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12180                                 c = pgetc_eatbnl();
12181                                 if (c != cc)
12182                                         goto badsub;
12183                                 subtype++;
12184                                 break;
12185                         }
12186 #if BASH_PATTERN_SUBST
12187                         case '/':
12188                                 /* ${v/[/]pattern/repl} */
12189 //TODO: encode pattern and repl separately.
12190 // Currently ${v/$var_with_slash/repl} is horribly broken
12191                                 subtype = VSREPLACE;
12192                                 c = pgetc_eatbnl();
12193                                 if (c != '/')
12194                                         goto badsub;
12195                                 subtype++; /* VSREPLACEALL */
12196                                 break;
12197 #endif
12198                         }
12199                 } else {
12200  badsub:
12201                         pungetc();
12202                 }
12203                 ((unsigned char *)stackblock())[typeloc] = subtype;
12204                 if (subtype != VSNORMAL) {
12205                         varnest++;
12206                         if (dblquote)
12207                                 dqvarnest++;
12208                 }
12209                 STPUTC('=', out);
12210         }
12211         goto parsesub_return;
12212 }
12213
12214 /*
12215  * Called to parse command substitutions.  Newstyle is set if the command
12216  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12217  * list of commands (passed by reference), and savelen is the number of
12218  * characters on the top of the stack which must be preserved.
12219  */
12220 parsebackq: {
12221         struct nodelist **nlpp;
12222         union node *n;
12223         char *str;
12224         size_t savelen;
12225         smallint saveprompt = 0;
12226
12227         str = NULL;
12228         savelen = out - (char *)stackblock();
12229         if (savelen > 0) {
12230                 /*
12231                  * FIXME: this can allocate very large block on stack and SEGV.
12232                  * Example:
12233                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12234                  * allocates 100kb for every command subst. With about
12235                  * a hundred command substitutions stack overflows.
12236                  * With larger prepended string, SEGV happens sooner.
12237                  */
12238                 str = alloca(savelen);
12239                 memcpy(str, stackblock(), savelen);
12240         }
12241
12242         if (oldstyle) {
12243                 /* We must read until the closing backquote, giving special
12244                  * treatment to some slashes, and then push the string and
12245                  * reread it as input, interpreting it normally.
12246                  */
12247                 char *pout;
12248                 size_t psavelen;
12249                 char *pstr;
12250
12251                 STARTSTACKSTR(pout);
12252                 for (;;) {
12253                         int pc;
12254
12255                         setprompt_if(needprompt, 2);
12256                         pc = pgetc();
12257                         switch (pc) {
12258                         case '`':
12259                                 goto done;
12260
12261                         case '\\':
12262                                 pc = pgetc();
12263                                 if (pc == '\n') {
12264                                         nlprompt();
12265                                         /*
12266                                          * If eating a newline, avoid putting
12267                                          * the newline into the new character
12268                                          * stream (via the STPUTC after the
12269                                          * switch).
12270                                          */
12271                                         continue;
12272                                 }
12273                                 if (pc != '\\' && pc != '`' && pc != '$'
12274                                  && (!dblquote || pc != '"')
12275                                 ) {
12276                                         STPUTC('\\', pout);
12277                                 }
12278                                 if (pc <= 255 /* not PEOA or PEOF */) {
12279                                         break;
12280                                 }
12281                                 /* fall through */
12282
12283                         case PEOF:
12284                         IF_ASH_ALIAS(case PEOA:)
12285                                 startlinno = g_parsefile->linno;
12286                                 raise_error_syntax("EOF in backquote substitution");
12287
12288                         case '\n':
12289                                 nlnoprompt();
12290                                 break;
12291
12292                         default:
12293                                 break;
12294                         }
12295                         STPUTC(pc, pout);
12296                 }
12297  done:
12298                 STPUTC('\0', pout);
12299                 psavelen = pout - (char *)stackblock();
12300                 if (psavelen > 0) {
12301                         pstr = grabstackstr(pout);
12302                         setinputstring(pstr);
12303                 }
12304         }
12305         nlpp = &bqlist;
12306         while (*nlpp)
12307                 nlpp = &(*nlpp)->next;
12308         *nlpp = stzalloc(sizeof(**nlpp));
12309         /* (*nlpp)->next = NULL; - stzalloc did it */
12310
12311         if (oldstyle) {
12312                 saveprompt = doprompt;
12313                 doprompt = 0;
12314         }
12315
12316         n = list(2);
12317
12318         if (oldstyle)
12319                 doprompt = saveprompt;
12320         else if (readtoken() != TRP)
12321                 raise_error_unexpected_syntax(TRP);
12322
12323         (*nlpp)->n = n;
12324         if (oldstyle) {
12325                 /*
12326                  * Start reading from old file again, ignoring any pushed back
12327                  * tokens left from the backquote parsing
12328                  */
12329                 popfile();
12330                 tokpushback = 0;
12331         }
12332         while (stackblocksize() <= savelen)
12333                 growstackblock();
12334         STARTSTACKSTR(out);
12335         if (str) {
12336                 memcpy(out, str, savelen);
12337                 STADJUST(savelen, out);
12338         }
12339         USTPUTC(CTLBACKQ, out);
12340         if (oldstyle)
12341                 goto parsebackq_oldreturn;
12342         goto parsebackq_newreturn;
12343 }
12344
12345 #if ENABLE_FEATURE_SH_MATH
12346 /*
12347  * Parse an arithmetic expansion (indicate start of one and set state)
12348  */
12349 parsearith: {
12350         if (++arinest == 1) {
12351                 prevsyntax = syntax;
12352                 syntax = ARISYNTAX;
12353         }
12354         USTPUTC(CTLARI, out);
12355         goto parsearith_return;
12356 }
12357 #endif
12358 } /* end of readtoken */
12359
12360 /*
12361  * Read the next input token.
12362  * If the token is a word, we set backquotelist to the list of cmds in
12363  *      backquotes.  We set quoteflag to true if any part of the word was
12364  *      quoted.
12365  * If the token is TREDIR, then we set redirnode to a structure containing
12366  *      the redirection.
12367  * In all cases, the variable startlinno is set to the number of the line
12368  *      on which the token starts.
12369  *
12370  * [Change comment:  here documents and internal procedures]
12371  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12372  *  word parsing code into a separate routine.  In this case, readtoken
12373  *  doesn't need to have any internal procedures, but parseword does.
12374  *  We could also make parseoperator in essence the main routine, and
12375  *  have parseword (readtoken1?) handle both words and redirection.]
12376  */
12377 #define NEW_xxreadtoken
12378 #ifdef NEW_xxreadtoken
12379 /* singles must be first! */
12380 static const char xxreadtoken_chars[7] ALIGN1 = {
12381         '\n', '(', ')', /* singles */
12382         '&', '|', ';',  /* doubles */
12383         0
12384 };
12385
12386 #define xxreadtoken_singles 3
12387 #define xxreadtoken_doubles 3
12388
12389 static const char xxreadtoken_tokens[] ALIGN1 = {
12390         TNL, TLP, TRP,          /* only single occurrence allowed */
12391         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12392         TEOF,                   /* corresponds to trailing nul */
12393         TAND, TOR, TENDCASE     /* if double occurrence */
12394 };
12395
12396 static int
12397 xxreadtoken(void)
12398 {
12399         int c;
12400
12401         if (tokpushback) {
12402                 tokpushback = 0;
12403                 return lasttoken;
12404         }
12405         setprompt_if(needprompt, 2);
12406         startlinno = g_parsefile->linno;
12407         for (;;) {                      /* until token or start of word found */
12408                 c = pgetc();
12409                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12410                         continue;
12411
12412                 if (c == '#') {
12413                         while ((c = pgetc()) != '\n' && c != PEOF)
12414                                 continue;
12415                         pungetc();
12416                 } else if (c == '\\') {
12417                         if (pgetc() != '\n') {
12418                                 pungetc();
12419                                 break; /* return readtoken1(...) */
12420                         }
12421                         nlprompt();
12422                 } else {
12423                         const char *p;
12424
12425                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12426                         if (c != PEOF) {
12427                                 if (c == '\n') {
12428                                         nlnoprompt();
12429                                 }
12430
12431                                 p = strchr(xxreadtoken_chars, c);
12432                                 if (p == NULL)
12433                                         break; /* return readtoken1(...) */
12434
12435                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12436                                         int cc = pgetc();
12437                                         if (cc == c) {    /* double occurrence? */
12438                                                 p += xxreadtoken_doubles + 1;
12439                                         } else {
12440                                                 pungetc();
12441 #if BASH_REDIR_OUTPUT
12442                                                 if (c == '&' && cc == '>') /* &> */
12443                                                         break; /* return readtoken1(...) */
12444 #endif
12445                                         }
12446                                 }
12447                         }
12448                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12449                         return lasttoken;
12450                 }
12451         } /* for (;;) */
12452
12453         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12454 }
12455 #else /* old xxreadtoken */
12456 #define RETURN(token)   return lasttoken = token
12457 static int
12458 xxreadtoken(void)
12459 {
12460         int c;
12461
12462         if (tokpushback) {
12463                 tokpushback = 0;
12464                 return lasttoken;
12465         }
12466         setprompt_if(needprompt, 2);
12467         startlinno = g_parsefile->linno;
12468         for (;;) {      /* until token or start of word found */
12469                 c = pgetc();
12470                 switch (c) {
12471                 case ' ': case '\t':
12472                 IF_ASH_ALIAS(case PEOA:)
12473                         continue;
12474                 case '#':
12475                         while ((c = pgetc()) != '\n' && c != PEOF)
12476                                 continue;
12477                         pungetc();
12478                         continue;
12479                 case '\\':
12480                         if (pgetc() == '\n') {
12481                                 nlprompt();
12482                                 continue;
12483                         }
12484                         pungetc();
12485                         goto breakloop;
12486                 case '\n':
12487                         nlnoprompt();
12488                         RETURN(TNL);
12489                 case PEOF:
12490                         RETURN(TEOF);
12491                 case '&':
12492                         if (pgetc() == '&')
12493                                 RETURN(TAND);
12494                         pungetc();
12495                         RETURN(TBACKGND);
12496                 case '|':
12497                         if (pgetc() == '|')
12498                                 RETURN(TOR);
12499                         pungetc();
12500                         RETURN(TPIPE);
12501                 case ';':
12502                         if (pgetc() == ';')
12503                                 RETURN(TENDCASE);
12504                         pungetc();
12505                         RETURN(TSEMI);
12506                 case '(':
12507                         RETURN(TLP);
12508                 case ')':
12509                         RETURN(TRP);
12510                 default:
12511                         goto breakloop;
12512                 }
12513         }
12514  breakloop:
12515         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12516 #undef RETURN
12517 }
12518 #endif /* old xxreadtoken */
12519
12520 static int
12521 readtoken(void)
12522 {
12523         int t;
12524         int kwd = checkkwd;
12525 #if DEBUG
12526         smallint alreadyseen = tokpushback;
12527 #endif
12528
12529 #if ENABLE_ASH_ALIAS
12530  top:
12531 #endif
12532
12533         t = xxreadtoken();
12534
12535         /*
12536          * eat newlines
12537          */
12538         if (kwd & CHKNL) {
12539                 while (t == TNL) {
12540                         parseheredoc();
12541                         t = xxreadtoken();
12542                 }
12543         }
12544
12545         if (t != TWORD || quoteflag) {
12546                 goto out;
12547         }
12548
12549         /*
12550          * check for keywords
12551          */
12552         if (kwd & CHKKWD) {
12553                 const char *const *pp;
12554
12555                 pp = findkwd(wordtext);
12556                 if (pp) {
12557                         lasttoken = t = pp - tokname_array;
12558                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12559                         goto out;
12560                 }
12561         }
12562
12563         if (checkkwd & CHKALIAS) {
12564 #if ENABLE_ASH_ALIAS
12565                 struct alias *ap;
12566                 ap = lookupalias(wordtext, 1);
12567                 if (ap != NULL) {
12568                         if (*ap->val) {
12569                                 pushstring(ap->val, ap);
12570                         }
12571                         goto top;
12572                 }
12573 #endif
12574         }
12575  out:
12576         checkkwd = 0;
12577 #if DEBUG
12578         if (!alreadyseen)
12579                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12580         else
12581                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12582 #endif
12583         return t;
12584 }
12585
12586 static int
12587 peektoken(void)
12588 {
12589         int t;
12590
12591         t = readtoken();
12592         tokpushback = 1;
12593         return t;
12594 }
12595
12596 /*
12597  * Read and parse a command.  Returns NODE_EOF on end of file.
12598  * (NULL is a valid parse tree indicating a blank line.)
12599  */
12600 static union node *
12601 parsecmd(int interact)
12602 {
12603         tokpushback = 0;
12604         checkkwd = 0;
12605         heredoclist = 0;
12606         doprompt = interact;
12607         setprompt_if(doprompt, doprompt);
12608         needprompt = 0;
12609         return list(1);
12610 }
12611
12612 /*
12613  * Input any here documents.
12614  */
12615 static void
12616 parseheredoc(void)
12617 {
12618         struct heredoc *here;
12619         union node *n;
12620
12621         here = heredoclist;
12622         heredoclist = NULL;
12623
12624         while (here) {
12625                 setprompt_if(needprompt, 2);
12626                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12627                                 here->eofmark, here->striptabs);
12628                 n = stzalloc(sizeof(struct narg));
12629                 n->narg.type = NARG;
12630                 /*n->narg.next = NULL; - stzalloc did it */
12631                 n->narg.text = wordtext;
12632                 n->narg.backquote = backquotelist;
12633                 here->here->nhere.doc = n;
12634                 here = here->next;
12635         }
12636 }
12637
12638
12639 static const char *
12640 expandstr(const char *ps, int syntax_type)
12641 {
12642         union node n;
12643         int saveprompt;
12644
12645         /* XXX Fix (char *) cast. */
12646         setinputstring((char *)ps);
12647
12648         saveprompt = doprompt;
12649         doprompt = 0;
12650         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12651         doprompt = saveprompt;
12652
12653         popfile();
12654
12655         n.narg.type = NARG;
12656         n.narg.next = NULL;
12657         n.narg.text = wordtext;
12658         n.narg.backquote = backquotelist;
12659
12660         expandarg(&n, NULL, EXP_QUOTED);
12661         return stackblock();
12662 }
12663
12664 static inline int
12665 parser_eof(void)
12666 {
12667         return tokpushback && lasttoken == TEOF;
12668 }
12669
12670 /*
12671  * Execute a command or commands contained in a string.
12672  */
12673 static int
12674 evalstring(char *s, int flags)
12675 {
12676         struct jmploc *volatile savehandler;
12677         struct jmploc jmploc;
12678         int ex;
12679
12680         union node *n;
12681         struct stackmark smark;
12682         int status;
12683
12684         s = sstrdup(s);
12685         setinputstring(s);
12686         setstackmark(&smark);
12687
12688         status = 0;
12689         /* On exception inside execution loop, we must popfile().
12690          * Try interactively:
12691          *      readonly a=a
12692          *      command eval "a=b"  # throws "is read only" error
12693          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12694          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12695          */
12696         savehandler = exception_handler;
12697         ex = setjmp(jmploc.loc);
12698         if (ex)
12699                 goto out;
12700         exception_handler = &jmploc;
12701
12702         while ((n = parsecmd(0)) != NODE_EOF) {
12703                 int i;
12704
12705                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12706                 if (n)
12707                         status = i;
12708                 popstackmark(&smark);
12709                 if (evalskip)
12710                         break;
12711         }
12712  out:
12713         popstackmark(&smark);
12714         popfile();
12715         stunalloc(s);
12716
12717         exception_handler = savehandler;
12718         if (ex)
12719                 longjmp(exception_handler->loc, ex);
12720
12721         return status;
12722 }
12723
12724 /*
12725  * The eval command.
12726  */
12727 static int FAST_FUNC
12728 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12729 {
12730         char *p;
12731         char *concat;
12732
12733         if (argv[1]) {
12734                 p = argv[1];
12735                 argv += 2;
12736                 if (argv[0]) {
12737                         STARTSTACKSTR(concat);
12738                         for (;;) {
12739                                 concat = stack_putstr(p, concat);
12740                                 p = *argv++;
12741                                 if (p == NULL)
12742                                         break;
12743                                 STPUTC(' ', concat);
12744                         }
12745                         STPUTC('\0', concat);
12746                         p = grabstackstr(concat);
12747                 }
12748                 return evalstring(p, flags & EV_TESTED);
12749         }
12750         return 0;
12751 }
12752
12753 /*
12754  * Read and execute commands.
12755  * "Top" is nonzero for the top level command loop;
12756  * it turns on prompting if the shell is interactive.
12757  */
12758 static int
12759 cmdloop(int top)
12760 {
12761         union node *n;
12762         struct stackmark smark;
12763         int inter;
12764         int status = 0;
12765         int numeof = 0;
12766
12767         TRACE(("cmdloop(%d) called\n", top));
12768         for (;;) {
12769                 int skip;
12770
12771                 setstackmark(&smark);
12772 #if JOBS
12773                 if (doing_jobctl)
12774                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12775 #endif
12776                 inter = 0;
12777                 if (iflag && top) {
12778                         inter++;
12779                         chkmail();
12780                 }
12781                 n = parsecmd(inter);
12782 #if DEBUG
12783                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12784                         showtree(n);
12785 #endif
12786                 if (n == NODE_EOF) {
12787                         if (!top || numeof >= 50)
12788                                 break;
12789                         if (!stoppedjobs()) {
12790                                 if (!Iflag)
12791                                         break;
12792                                 out2str("\nUse \"exit\" to leave shell.\n");
12793                         }
12794                         numeof++;
12795                 } else if (nflag == 0) {
12796                         int i;
12797
12798                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12799                         job_warning >>= 1;
12800                         numeof = 0;
12801                         i = evaltree(n, 0);
12802                         if (n)
12803                                 status = i;
12804                 }
12805                 popstackmark(&smark);
12806                 skip = evalskip;
12807
12808                 if (skip) {
12809                         evalskip &= ~SKIPFUNC;
12810                         break;
12811                 }
12812         }
12813         return status;
12814 }
12815
12816 /*
12817  * Take commands from a file.  To be compatible we should do a path
12818  * search for the file, which is necessary to find sub-commands.
12819  */
12820 static char *
12821 find_dot_file(char *name)
12822 {
12823         char *fullname;
12824         const char *path = pathval();
12825         struct stat statb;
12826
12827         /* don't try this for absolute or relative paths */
12828         if (strchr(name, '/'))
12829                 return name;
12830
12831         while ((fullname = path_advance(&path, name)) != NULL) {
12832                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12833                         /*
12834                          * Don't bother freeing here, since it will
12835                          * be freed by the caller.
12836                          */
12837                         return fullname;
12838                 }
12839                 if (fullname != name)
12840                         stunalloc(fullname);
12841         }
12842
12843         /* not found in the PATH */
12844         ash_msg_and_raise_error("%s: not found", name);
12845         /* NOTREACHED */
12846 }
12847
12848 static int FAST_FUNC
12849 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12850 {
12851         /* "false; . empty_file; echo $?" should print 0, not 1: */
12852         int status = 0;
12853         char *fullname;
12854         char **argv;
12855         char *args_need_save;
12856         volatile struct shparam saveparam;
12857
12858 //???
12859 //      struct strlist *sp;
12860 //      for (sp = cmdenviron; sp; sp = sp->next)
12861 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12862
12863         nextopt(nullstr); /* handle possible "--" */
12864         argv = argptr;
12865
12866         if (!argv[0]) {
12867                 /* bash says: "bash: .: filename argument required" */
12868                 return 2; /* bash compat */
12869         }
12870
12871         /* This aborts if file isn't found, which is POSIXly correct.
12872          * bash returns exitcode 1 instead.
12873          */
12874         fullname = find_dot_file(argv[0]);
12875         argv++;
12876         args_need_save = argv[0];
12877         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12878                 int argc;
12879                 saveparam = shellparam;
12880                 shellparam.malloced = 0;
12881                 argc = 1;
12882                 while (argv[argc])
12883                         argc++;
12884                 shellparam.nparam = argc;
12885                 shellparam.p = argv;
12886         };
12887
12888         /* This aborts if file can't be opened, which is POSIXly correct.
12889          * bash returns exitcode 1 instead.
12890          */
12891         setinputfile(fullname, INPUT_PUSH_FILE);
12892         commandname = fullname;
12893         status = cmdloop(0);
12894         popfile();
12895
12896         if (args_need_save) {
12897                 freeparam(&shellparam);
12898                 shellparam = saveparam;
12899         };
12900
12901         return status;
12902 }
12903
12904 static int FAST_FUNC
12905 exitcmd(int argc UNUSED_PARAM, char **argv)
12906 {
12907         if (stoppedjobs())
12908                 return 0;
12909         if (argv[1])
12910                 exitstatus = number(argv[1]);
12911         raise_exception(EXEXIT);
12912         /* NOTREACHED */
12913 }
12914
12915 /*
12916  * Read a file containing shell functions.
12917  */
12918 static void
12919 readcmdfile(char *name)
12920 {
12921         setinputfile(name, INPUT_PUSH_FILE);
12922         cmdloop(0);
12923         popfile();
12924 }
12925
12926
12927 /* ============ find_command inplementation */
12928
12929 /*
12930  * Resolve a command name.  If you change this routine, you may have to
12931  * change the shellexec routine as well.
12932  */
12933 static void
12934 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12935 {
12936         struct tblentry *cmdp;
12937         int idx;
12938         int prev;
12939         char *fullname;
12940         struct stat statb;
12941         int e;
12942         int updatetbl;
12943         struct builtincmd *bcmd;
12944
12945         /* If name contains a slash, don't use PATH or hash table */
12946         if (strchr(name, '/') != NULL) {
12947                 entry->u.index = -1;
12948                 if (act & DO_ABS) {
12949                         while (stat(name, &statb) < 0) {
12950 #ifdef SYSV
12951                                 if (errno == EINTR)
12952                                         continue;
12953 #endif
12954                                 entry->cmdtype = CMDUNKNOWN;
12955                                 return;
12956                         }
12957                 }
12958                 entry->cmdtype = CMDNORMAL;
12959                 return;
12960         }
12961
12962 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12963
12964         updatetbl = (path == pathval());
12965         if (!updatetbl) {
12966                 act |= DO_ALTPATH;
12967                 if (strstr(path, "%builtin") != NULL)
12968                         act |= DO_ALTBLTIN;
12969         }
12970
12971         /* If name is in the table, check answer will be ok */
12972         cmdp = cmdlookup(name, 0);
12973         if (cmdp != NULL) {
12974                 int bit;
12975
12976                 switch (cmdp->cmdtype) {
12977                 default:
12978 #if DEBUG
12979                         abort();
12980 #endif
12981                 case CMDNORMAL:
12982                         bit = DO_ALTPATH;
12983                         break;
12984                 case CMDFUNCTION:
12985                         bit = DO_NOFUNC;
12986                         break;
12987                 case CMDBUILTIN:
12988                         bit = DO_ALTBLTIN;
12989                         break;
12990                 }
12991                 if (act & bit) {
12992                         updatetbl = 0;
12993                         cmdp = NULL;
12994                 } else if (cmdp->rehash == 0)
12995                         /* if not invalidated by cd, we're done */
12996                         goto success;
12997         }
12998
12999         /* If %builtin not in path, check for builtin next */
13000         bcmd = find_builtin(name);
13001         if (bcmd) {
13002                 if (IS_BUILTIN_REGULAR(bcmd))
13003                         goto builtin_success;
13004                 if (act & DO_ALTPATH) {
13005                         if (!(act & DO_ALTBLTIN))
13006                                 goto builtin_success;
13007                 } else if (builtinloc <= 0) {
13008                         goto builtin_success;
13009                 }
13010         }
13011
13012 #if ENABLE_FEATURE_SH_STANDALONE
13013         {
13014                 int applet_no = find_applet_by_name(name);
13015                 if (applet_no >= 0) {
13016                         entry->cmdtype = CMDNORMAL;
13017                         entry->u.index = -2 - applet_no;
13018                         return;
13019                 }
13020         }
13021 #endif
13022
13023         /* We have to search path. */
13024         prev = -1;              /* where to start */
13025         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13026                 if (cmdp->cmdtype == CMDBUILTIN)
13027                         prev = builtinloc;
13028                 else
13029                         prev = cmdp->param.index;
13030         }
13031
13032         e = ENOENT;
13033         idx = -1;
13034  loop:
13035         while ((fullname = path_advance(&path, name)) != NULL) {
13036                 stunalloc(fullname);
13037                 /* NB: code below will still use fullname
13038                  * despite it being "unallocated" */
13039                 idx++;
13040                 if (pathopt) {
13041                         if (prefix(pathopt, "builtin")) {
13042                                 if (bcmd)
13043                                         goto builtin_success;
13044                                 continue;
13045                         }
13046                         if ((act & DO_NOFUNC)
13047                          || !prefix(pathopt, "func")
13048                         ) {     /* ignore unimplemented options */
13049                                 continue;
13050                         }
13051                 }
13052                 /* if rehash, don't redo absolute path names */
13053                 if (fullname[0] == '/' && idx <= prev) {
13054                         if (idx < prev)
13055                                 continue;
13056                         TRACE(("searchexec \"%s\": no change\n", name));
13057                         goto success;
13058                 }
13059                 while (stat(fullname, &statb) < 0) {
13060 #ifdef SYSV
13061                         if (errno == EINTR)
13062                                 continue;
13063 #endif
13064                         if (errno != ENOENT && errno != ENOTDIR)
13065                                 e = errno;
13066                         goto loop;
13067                 }
13068                 e = EACCES;     /* if we fail, this will be the error */
13069                 if (!S_ISREG(statb.st_mode))
13070                         continue;
13071                 if (pathopt) {          /* this is a %func directory */
13072                         stalloc(strlen(fullname) + 1);
13073                         /* NB: stalloc will return space pointed by fullname
13074                          * (because we don't have any intervening allocations
13075                          * between stunalloc above and this stalloc) */
13076                         readcmdfile(fullname);
13077                         cmdp = cmdlookup(name, 0);
13078                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13079                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13080                         stunalloc(fullname);
13081                         goto success;
13082                 }
13083                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13084                 if (!updatetbl) {
13085                         entry->cmdtype = CMDNORMAL;
13086                         entry->u.index = idx;
13087                         return;
13088                 }
13089                 INT_OFF;
13090                 cmdp = cmdlookup(name, 1);
13091                 cmdp->cmdtype = CMDNORMAL;
13092                 cmdp->param.index = idx;
13093                 INT_ON;
13094                 goto success;
13095         }
13096
13097         /* We failed.  If there was an entry for this command, delete it */
13098         if (cmdp && updatetbl)
13099                 delete_cmd_entry();
13100         if (act & DO_ERR)
13101                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13102         entry->cmdtype = CMDUNKNOWN;
13103         return;
13104
13105  builtin_success:
13106         if (!updatetbl) {
13107                 entry->cmdtype = CMDBUILTIN;
13108                 entry->u.cmd = bcmd;
13109                 return;
13110         }
13111         INT_OFF;
13112         cmdp = cmdlookup(name, 1);
13113         cmdp->cmdtype = CMDBUILTIN;
13114         cmdp->param.cmd = bcmd;
13115         INT_ON;
13116  success:
13117         cmdp->rehash = 0;
13118         entry->cmdtype = cmdp->cmdtype;
13119         entry->u = cmdp->param;
13120 }
13121
13122
13123 /*
13124  * The trap builtin.
13125  */
13126 static int FAST_FUNC
13127 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13128 {
13129         char *action;
13130         char **ap;
13131         int signo, exitcode;
13132
13133         nextopt(nullstr);
13134         ap = argptr;
13135         if (!*ap) {
13136                 for (signo = 0; signo < NSIG; signo++) {
13137                         char *tr = trap_ptr[signo];
13138                         if (tr) {
13139                                 /* note: bash adds "SIG", but only if invoked
13140                                  * as "bash". If called as "sh", or if set -o posix,
13141                                  * then it prints short signal names.
13142                                  * We are printing short names: */
13143                                 out1fmt("trap -- %s %s\n",
13144                                                 single_quote(tr),
13145                                                 get_signame(signo));
13146                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13147                  * In this case, we will exit very soon, no need to free(). */
13148                                 /* if (trap_ptr != trap && tp[0]) */
13149                                 /*      free(tr); */
13150                         }
13151                 }
13152                 /*
13153                 if (trap_ptr != trap) {
13154                         free(trap_ptr);
13155                         trap_ptr = trap;
13156                 }
13157                 */
13158                 return 0;
13159         }
13160
13161         /* Why the second check?
13162          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13163          * In this case, NUM is signal no, not an action.
13164          */
13165         action = NULL;
13166         if (ap[1] && !is_number(ap[0]))
13167                 action = *ap++;
13168
13169         exitcode = 0;
13170         while (*ap) {
13171                 signo = get_signum(*ap);
13172                 if (signo < 0) {
13173                         /* Mimic bash message exactly */
13174                         ash_msg("%s: invalid signal specification", *ap);
13175                         exitcode = 1;
13176                         goto next;
13177                 }
13178                 INT_OFF;
13179                 if (action) {
13180                         if (LONE_DASH(action))
13181                                 action = NULL;
13182                         else {
13183                                 if (action[0]) /* not NULL and not "" and not "-" */
13184                                         may_have_traps = 1;
13185                                 action = ckstrdup(action);
13186                         }
13187                 }
13188                 free(trap[signo]);
13189                 trap[signo] = action;
13190                 if (signo != 0)
13191                         setsignal(signo);
13192                 INT_ON;
13193  next:
13194                 ap++;
13195         }
13196         return exitcode;
13197 }
13198
13199
13200 /* ============ Builtins */
13201
13202 #if ENABLE_ASH_HELP
13203 static int FAST_FUNC
13204 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13205 {
13206         unsigned col;
13207         unsigned i;
13208
13209         out1fmt(
13210                 "Built-in commands:\n"
13211                 "------------------\n");
13212         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13213                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13214                                         builtintab[i].name + 1);
13215                 if (col > 60) {
13216                         out1fmt("\n");
13217                         col = 0;
13218                 }
13219         }
13220 # if ENABLE_FEATURE_SH_STANDALONE
13221         {
13222                 const char *a = applet_names;
13223                 while (*a) {
13224                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13225                         if (col > 60) {
13226                                 out1fmt("\n");
13227                                 col = 0;
13228                         }
13229                         while (*a++ != '\0')
13230                                 continue;
13231                 }
13232         }
13233 # endif
13234         newline_and_flush(stdout);
13235         return EXIT_SUCCESS;
13236 }
13237 #endif
13238
13239 #if MAX_HISTORY
13240 static int FAST_FUNC
13241 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13242 {
13243         show_history(line_input_state);
13244         return EXIT_SUCCESS;
13245 }
13246 #endif
13247
13248 /*
13249  * The export and readonly commands.
13250  */
13251 static int FAST_FUNC
13252 exportcmd(int argc UNUSED_PARAM, char **argv)
13253 {
13254         struct var *vp;
13255         char *name;
13256         const char *p;
13257         char **aptr;
13258         char opt;
13259         int flag;
13260         int flag_off;
13261
13262         /* "readonly" in bash accepts, but ignores -n.
13263          * We do the same: it saves a conditional in nextopt's param.
13264          */
13265         flag_off = 0;
13266         while ((opt = nextopt("np")) != '\0') {
13267                 if (opt == 'n')
13268                         flag_off = VEXPORT;
13269         }
13270         flag = VEXPORT;
13271         if (argv[0][0] == 'r') {
13272                 flag = VREADONLY;
13273                 flag_off = 0; /* readonly ignores -n */
13274         }
13275         flag_off = ~flag_off;
13276
13277         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13278         {
13279                 aptr = argptr;
13280                 name = *aptr;
13281                 if (name) {
13282                         do {
13283                                 p = strchr(name, '=');
13284                                 if (p != NULL) {
13285                                         p++;
13286                                 } else {
13287                                         vp = *findvar(hashvar(name), name);
13288                                         if (vp) {
13289                                                 vp->flags = ((vp->flags | flag) & flag_off);
13290                                                 continue;
13291                                         }
13292                                 }
13293                                 setvar(name, p, (flag & flag_off));
13294                         } while ((name = *++aptr) != NULL);
13295                         return 0;
13296                 }
13297         }
13298
13299         /* No arguments. Show the list of exported or readonly vars.
13300          * -n is ignored.
13301          */
13302         showvars(argv[0], flag, 0);
13303         return 0;
13304 }
13305
13306 /*
13307  * Delete a function if it exists.
13308  */
13309 static void
13310 unsetfunc(const char *name)
13311 {
13312         struct tblentry *cmdp;
13313
13314         cmdp = cmdlookup(name, 0);
13315         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13316                 delete_cmd_entry();
13317 }
13318
13319 /*
13320  * The unset builtin command.  We unset the function before we unset the
13321  * variable to allow a function to be unset when there is a readonly variable
13322  * with the same name.
13323  */
13324 static int FAST_FUNC
13325 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13326 {
13327         char **ap;
13328         int i;
13329         int flag = 0;
13330
13331         while ((i = nextopt("vf")) != 0) {
13332                 flag = i;
13333         }
13334
13335         for (ap = argptr; *ap; ap++) {
13336                 if (flag != 'f') {
13337                         unsetvar(*ap);
13338                         continue;
13339                 }
13340                 if (flag != 'v')
13341                         unsetfunc(*ap);
13342         }
13343         return 0;
13344 }
13345
13346 static const unsigned char timescmd_str[] ALIGN1 = {
13347         ' ',  offsetof(struct tms, tms_utime),
13348         '\n', offsetof(struct tms, tms_stime),
13349         ' ',  offsetof(struct tms, tms_cutime),
13350         '\n', offsetof(struct tms, tms_cstime),
13351         0
13352 };
13353 static int FAST_FUNC
13354 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13355 {
13356         unsigned clk_tck;
13357         const unsigned char *p;
13358         struct tms buf;
13359
13360         clk_tck = bb_clk_tck();
13361
13362         times(&buf);
13363         p = timescmd_str;
13364         do {
13365                 unsigned sec, frac;
13366                 unsigned long t;
13367                 t = *(clock_t *)(((char *) &buf) + p[1]);
13368                 sec = t / clk_tck;
13369                 frac = t % clk_tck;
13370                 out1fmt("%um%u.%03us%c",
13371                         sec / 60, sec % 60,
13372                         (frac * 1000) / clk_tck,
13373                         p[0]);
13374                 p += 2;
13375         } while (*p);
13376
13377         return 0;
13378 }
13379
13380 #if ENABLE_FEATURE_SH_MATH
13381 /*
13382  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13383  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13384  *
13385  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13386  */
13387 static int FAST_FUNC
13388 letcmd(int argc UNUSED_PARAM, char **argv)
13389 {
13390         arith_t i;
13391
13392         argv++;
13393         if (!*argv)
13394                 ash_msg_and_raise_error("expression expected");
13395         do {
13396                 i = ash_arith(*argv);
13397         } while (*++argv);
13398
13399         return !i;
13400 }
13401 #endif
13402
13403 /*
13404  * The read builtin. Options:
13405  *      -r              Do not interpret '\' specially
13406  *      -s              Turn off echo (tty only)
13407  *      -n NCHARS       Read NCHARS max
13408  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13409  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13410  *      -u FD           Read from given FD instead of fd 0
13411  *      -d DELIM        End on DELIM char, not newline
13412  * This uses unbuffered input, which may be avoidable in some cases.
13413  * TODO: bash also has:
13414  *      -a ARRAY        Read into array[0],[1],etc
13415  *      -e              Use line editing (tty only)
13416  */
13417 static int FAST_FUNC
13418 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13419 {
13420         char *opt_n = NULL;
13421         char *opt_p = NULL;
13422         char *opt_t = NULL;
13423         char *opt_u = NULL;
13424         char *opt_d = NULL; /* optimized out if !BASH */
13425         int read_flags = 0;
13426         const char *r;
13427         int i;
13428
13429         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13430                 switch (i) {
13431                 case 'p':
13432                         opt_p = optionarg;
13433                         break;
13434                 case 'n':
13435                         opt_n = optionarg;
13436                         break;
13437                 case 's':
13438                         read_flags |= BUILTIN_READ_SILENT;
13439                         break;
13440                 case 't':
13441                         opt_t = optionarg;
13442                         break;
13443                 case 'r':
13444                         read_flags |= BUILTIN_READ_RAW;
13445                         break;
13446                 case 'u':
13447                         opt_u = optionarg;
13448                         break;
13449 #if BASH_READ_D
13450                 case 'd':
13451                         opt_d = optionarg;
13452                         break;
13453 #endif
13454                 default:
13455                         break;
13456                 }
13457         }
13458
13459         /* "read -s" needs to save/restore termios, can't allow ^C
13460          * to jump out of it.
13461          */
13462  again:
13463         INT_OFF;
13464         r = shell_builtin_read(setvar0,
13465                 argptr,
13466                 bltinlookup("IFS"), /* can be NULL */
13467                 read_flags,
13468                 opt_n,
13469                 opt_p,
13470                 opt_t,
13471                 opt_u,
13472                 opt_d
13473         );
13474         INT_ON;
13475
13476         if ((uintptr_t)r == 1 && errno == EINTR) {
13477                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13478                  * Correct behavior is to not exit "read"
13479                  */
13480                 if (pending_sig == 0)
13481                         goto again;
13482         }
13483
13484         if ((uintptr_t)r > 1)
13485                 ash_msg_and_raise_error(r);
13486
13487         return (uintptr_t)r;
13488 }
13489
13490 static int FAST_FUNC
13491 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13492 {
13493         static const char permuser[3] ALIGN1 = "ogu";
13494
13495         mode_t mask;
13496         int symbolic_mode = 0;
13497
13498         while (nextopt("S") != '\0') {
13499                 symbolic_mode = 1;
13500         }
13501
13502         INT_OFF;
13503         mask = umask(0);
13504         umask(mask);
13505         INT_ON;
13506
13507         if (*argptr == NULL) {
13508                 if (symbolic_mode) {
13509                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13510                         char *p = buf;
13511                         int i;
13512
13513                         i = 2;
13514                         for (;;) {
13515                                 *p++ = ',';
13516                                 *p++ = permuser[i];
13517                                 *p++ = '=';
13518                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13519                                 if (!(mask & 0400)) *p++ = 'r';
13520                                 if (!(mask & 0200)) *p++ = 'w';
13521                                 if (!(mask & 0100)) *p++ = 'x';
13522                                 mask <<= 3;
13523                                 if (--i < 0)
13524                                         break;
13525                         }
13526                         *p = '\0';
13527                         puts(buf + 1);
13528                 } else {
13529                         out1fmt("%04o\n", mask);
13530                 }
13531         } else {
13532                 char *modestr = *argptr;
13533                 /* numeric umasks are taken as-is */
13534                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13535                 if (!isdigit(modestr[0]))
13536                         mask ^= 0777;
13537                 mask = bb_parse_mode(modestr, mask);
13538                 if ((unsigned)mask > 0777) {
13539                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13540                 }
13541                 if (!isdigit(modestr[0]))
13542                         mask ^= 0777;
13543                 umask(mask);
13544         }
13545         return 0;
13546 }
13547
13548 static int FAST_FUNC
13549 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13550 {
13551         return shell_builtin_ulimit(argv);
13552 }
13553
13554 /* ============ main() and helpers */
13555
13556 /*
13557  * Called to exit the shell.
13558  */
13559 static void
13560 exitshell(void)
13561 {
13562         struct jmploc loc;
13563         char *p;
13564         int status;
13565
13566 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13567         save_history(line_input_state);
13568 #endif
13569         status = exitstatus;
13570         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13571         if (setjmp(loc.loc)) {
13572                 if (exception_type == EXEXIT)
13573                         status = exitstatus;
13574                 goto out;
13575         }
13576         exception_handler = &loc;
13577         p = trap[0];
13578         if (p) {
13579                 trap[0] = NULL;
13580                 evalskip = 0;
13581                 evalstring(p, 0);
13582                 /*free(p); - we'll exit soon */
13583         }
13584  out:
13585         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13586          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13587          */
13588         setjobctl(0);
13589         flush_stdout_stderr();
13590         _exit(status);
13591         /* NOTREACHED */
13592 }
13593
13594 /* Don't inline: conserve stack of caller from having our locals too */
13595 static NOINLINE void
13596 init(void)
13597 {
13598         /* we will never free this */
13599         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13600
13601         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13602         setsignal(SIGCHLD);
13603
13604         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13605          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13606          */
13607         signal(SIGHUP, SIG_DFL);
13608
13609         {
13610                 char **envp;
13611                 const char *p;
13612
13613                 initvar();
13614                 for (envp = environ; envp && *envp; envp++) {
13615                         p = endofname(*envp);
13616                         if (p != *envp && *p == '=') {
13617                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13618                         }
13619                 }
13620
13621                 setvareq((char*)defoptindvar, VTEXTFIXED);
13622
13623                 setvar0("PPID", utoa(getppid()));
13624 #if BASH_SHLVL_VAR
13625                 p = lookupvar("SHLVL");
13626                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13627 #endif
13628 #if BASH_HOSTNAME_VAR
13629                 if (!lookupvar("HOSTNAME")) {
13630                         struct utsname uts;
13631                         uname(&uts);
13632                         setvar0("HOSTNAME", uts.nodename);
13633                 }
13634 #endif
13635                 p = lookupvar("PWD");
13636                 if (p) {
13637                         struct stat st1, st2;
13638                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13639                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13640                         ) {
13641                                 p = NULL;
13642                         }
13643                 }
13644                 setpwd(p, 0);
13645         }
13646 }
13647
13648
13649 //usage:#define ash_trivial_usage
13650 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13651 //usage:#define ash_full_usage "\n\n"
13652 //usage:        "Unix shell interpreter"
13653
13654 /*
13655  * Process the shell command line arguments.
13656  */
13657 static int
13658 procargs(char **argv)
13659 {
13660         int i;
13661         const char *xminusc;
13662         char **xargv;
13663         int login_sh;
13664
13665         xargv = argv;
13666         login_sh = xargv[0] && xargv[0][0] == '-';
13667         arg0 = xargv[0];
13668         /* if (xargv[0]) - mmm, this is always true! */
13669                 xargv++;
13670         for (i = 0; i < NOPTS; i++)
13671                 optlist[i] = 2;
13672         argptr = xargv;
13673         if (options(/*cmdline:*/ 1, &login_sh)) {
13674                 /* it already printed err message */
13675                 raise_exception(EXERROR);
13676         }
13677         xargv = argptr;
13678         xminusc = minusc;
13679         if (*xargv == NULL) {
13680                 if (xminusc)
13681                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13682                 sflag = 1;
13683         }
13684         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13685                 iflag = 1;
13686         if (mflag == 2)
13687                 mflag = iflag;
13688         for (i = 0; i < NOPTS; i++)
13689                 if (optlist[i] == 2)
13690                         optlist[i] = 0;
13691 #if DEBUG == 2
13692         debug = 1;
13693 #endif
13694         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13695         if (xminusc) {
13696                 minusc = *xargv++;
13697                 if (*xargv)
13698                         goto setarg0;
13699         } else if (!sflag) {
13700                 setinputfile(*xargv, 0);
13701  setarg0:
13702                 arg0 = *xargv++;
13703                 commandname = arg0;
13704         }
13705
13706         shellparam.p = xargv;
13707 #if ENABLE_ASH_GETOPTS
13708         shellparam.optind = 1;
13709         shellparam.optoff = -1;
13710 #endif
13711         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13712         while (*xargv) {
13713                 shellparam.nparam++;
13714                 xargv++;
13715         }
13716         optschanged();
13717
13718         return login_sh;
13719 }
13720
13721 /*
13722  * Read /etc/profile, ~/.profile, $ENV.
13723  */
13724 static void
13725 read_profile(const char *name)
13726 {
13727         name = expandstr(name, DQSYNTAX);
13728         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13729                 return;
13730         cmdloop(0);
13731         popfile();
13732 }
13733
13734 /*
13735  * This routine is called when an error or an interrupt occurs in an
13736  * interactive shell and control is returned to the main command loop.
13737  * (In dash, this function is auto-generated by build machinery).
13738  */
13739 static void
13740 reset(void)
13741 {
13742         /* from eval.c: */
13743         evalskip = 0;
13744         loopnest = 0;
13745
13746         /* from expand.c: */
13747         ifsfree();
13748
13749         /* from input.c: */
13750         g_parsefile->left_in_buffer = 0;
13751         g_parsefile->left_in_line = 0;      /* clear input buffer */
13752         popallfiles();
13753
13754         /* from redir.c: */
13755         unwindredir(NULL);
13756
13757         /* from var.c: */
13758         unwindlocalvars(NULL);
13759 }
13760
13761 #if PROFILE
13762 static short profile_buf[16384];
13763 extern int etext();
13764 #endif
13765
13766 /*
13767  * Main routine.  We initialize things, parse the arguments, execute
13768  * profiles if we're a login shell, and then call cmdloop to execute
13769  * commands.  The setjmp call sets up the location to jump to when an
13770  * exception occurs.  When an exception occurs the variable "state"
13771  * is used to figure out how far we had gotten.
13772  */
13773 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13774 int ash_main(int argc UNUSED_PARAM, char **argv)
13775 {
13776         volatile smallint state;
13777         struct jmploc jmploc;
13778         struct stackmark smark;
13779         int login_sh;
13780
13781         /* Initialize global data */
13782         INIT_G_misc();
13783         INIT_G_memstack();
13784         INIT_G_var();
13785 #if ENABLE_ASH_ALIAS
13786         INIT_G_alias();
13787 #endif
13788         INIT_G_cmdtable();
13789
13790 #if PROFILE
13791         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13792 #endif
13793
13794 #if ENABLE_FEATURE_EDITING
13795         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13796 #endif
13797         state = 0;
13798         if (setjmp(jmploc.loc)) {
13799                 smallint e;
13800                 smallint s;
13801
13802                 reset();
13803
13804                 e = exception_type;
13805                 s = state;
13806                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13807                         exitshell();
13808                 }
13809                 if (e == EXINT) {
13810                         newline_and_flush(stderr);
13811                 }
13812
13813                 popstackmark(&smark);
13814                 FORCE_INT_ON; /* enable interrupts */
13815                 if (s == 1)
13816                         goto state1;
13817                 if (s == 2)
13818                         goto state2;
13819                 if (s == 3)
13820                         goto state3;
13821                 goto state4;
13822         }
13823         exception_handler = &jmploc;
13824         rootpid = getpid();
13825
13826         init();
13827         setstackmark(&smark);
13828         login_sh = procargs(argv);
13829 #if DEBUG
13830         TRACE(("Shell args: "));
13831         trace_puts_args(argv);
13832 #endif
13833
13834         if (login_sh) {
13835                 const char *hp;
13836
13837                 state = 1;
13838                 read_profile("/etc/profile");
13839  state1:
13840                 state = 2;
13841                 hp = lookupvar("HOME");
13842                 if (hp)
13843                         read_profile("$HOME/.profile");
13844         }
13845  state2:
13846         state = 3;
13847         if (
13848 #ifndef linux
13849          getuid() == geteuid() && getgid() == getegid() &&
13850 #endif
13851          iflag
13852         ) {
13853                 const char *shinit = lookupvar("ENV");
13854                 if (shinit != NULL && *shinit != '\0')
13855                         read_profile(shinit);
13856         }
13857         popstackmark(&smark);
13858  state3:
13859         state = 4;
13860         if (minusc) {
13861                 /* evalstring pushes parsefile stack.
13862                  * Ensure we don't falsely claim that 0 (stdin)
13863                  * is one of stacked source fds.
13864                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13865                 // if (!sflag) g_parsefile->pf_fd = -1;
13866                 // ^^ not necessary since now we special-case fd 0
13867                 // in save_fd_on_redirect()
13868                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13869         }
13870
13871         if (sflag || minusc == NULL) {
13872 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13873                 if (iflag) {
13874                         const char *hp = lookupvar("HISTFILE");
13875                         if (!hp) {
13876                                 hp = lookupvar("HOME");
13877                                 if (hp) {
13878                                         INT_OFF;
13879                                         hp = concat_path_file(hp, ".ash_history");
13880                                         setvar0("HISTFILE", hp);
13881                                         free((char*)hp);
13882                                         INT_ON;
13883                                         hp = lookupvar("HISTFILE");
13884                                 }
13885                         }
13886                         if (hp)
13887                                 line_input_state->hist_file = hp;
13888 # if ENABLE_FEATURE_SH_HISTFILESIZE
13889                         hp = lookupvar("HISTFILESIZE");
13890                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13891 # endif
13892                 }
13893 #endif
13894  state4: /* XXX ??? - why isn't this before the "if" statement */
13895                 cmdloop(1);
13896         }
13897 #if PROFILE
13898         monitor(0);
13899 #endif
13900 #ifdef GPROF
13901         {
13902                 extern void _mcleanup(void);
13903                 _mcleanup();
13904         }
13905 #endif
13906         TRACE(("End of main reached\n"));
13907         exitshell();
13908         /* NOTREACHED */
13909 }
13910
13911
13912 /*-
13913  * Copyright (c) 1989, 1991, 1993, 1994
13914  *      The Regents of the University of California.  All rights reserved.
13915  *
13916  * This code is derived from software contributed to Berkeley by
13917  * Kenneth Almquist.
13918  *
13919  * Redistribution and use in source and binary forms, with or without
13920  * modification, are permitted provided that the following conditions
13921  * are met:
13922  * 1. Redistributions of source code must retain the above copyright
13923  *    notice, this list of conditions and the following disclaimer.
13924  * 2. Redistributions in binary form must reproduce the above copyright
13925  *    notice, this list of conditions and the following disclaimer in the
13926  *    documentation and/or other materials provided with the distribution.
13927  * 3. Neither the name of the University nor the names of its contributors
13928  *    may be used to endorse or promote products derived from this software
13929  *    without specific prior written permission.
13930  *
13931  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
13932  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13933  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13934  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13935  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13936  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13937  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13938  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13939  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13940  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13941  * SUCH DAMAGE.
13942  */