ash: [VAR] Fix poplocalvar on abnormal exit from function
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 static void raise_error_syntax(const char *) NORETURN;
1310 static void
1311 raise_error_syntax(const char *msg)
1312 {
1313         ash_msg_and_raise_error("syntax error: %s", msg);
1314         /* NOTREACHED */
1315 }
1316
1317 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1318 static void
1319 ash_msg_and_raise(int cond, const char *msg, ...)
1320 {
1321         va_list ap;
1322
1323         va_start(ap, msg);
1324         ash_vmsg_and_raise(cond, msg, ap);
1325         /* NOTREACHED */
1326         va_end(ap);
1327 }
1328
1329 /*
1330  * error/warning routines for external builtins
1331  */
1332 static void
1333 ash_msg(const char *fmt, ...)
1334 {
1335         va_list ap;
1336
1337         va_start(ap, fmt);
1338         ash_vmsg(fmt, ap);
1339         va_end(ap);
1340 }
1341
1342 /*
1343  * Return a string describing an error.  The returned string may be a
1344  * pointer to a static buffer that will be overwritten on the next call.
1345  * Action describes the operation that got the error.
1346  */
1347 static const char *
1348 errmsg(int e, const char *em)
1349 {
1350         if (e == ENOENT || e == ENOTDIR) {
1351                 return em;
1352         }
1353         return strerror(e);
1354 }
1355
1356
1357 /* ============ Memory allocation */
1358
1359 #if 0
1360 /* I consider these wrappers nearly useless:
1361  * ok, they return you to nearest exception handler, but
1362  * how much memory do you leak in the process, making
1363  * memory starvation worse?
1364  */
1365 static void *
1366 ckrealloc(void * p, size_t nbytes)
1367 {
1368         p = realloc(p, nbytes);
1369         if (!p)
1370                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1371         return p;
1372 }
1373
1374 static void *
1375 ckmalloc(size_t nbytes)
1376 {
1377         return ckrealloc(NULL, nbytes);
1378 }
1379
1380 static void *
1381 ckzalloc(size_t nbytes)
1382 {
1383         return memset(ckmalloc(nbytes), 0, nbytes);
1384 }
1385
1386 static char *
1387 ckstrdup(const char *s)
1388 {
1389         char *p = strdup(s);
1390         if (!p)
1391                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1392         return p;
1393 }
1394 #else
1395 /* Using bbox equivalents. They exit if out of memory */
1396 # define ckrealloc xrealloc
1397 # define ckmalloc  xmalloc
1398 # define ckzalloc  xzalloc
1399 # define ckstrdup  xstrdup
1400 #endif
1401
1402 /*
1403  * It appears that grabstackstr() will barf with such alignments
1404  * because stalloc() will return a string allocated in a new stackblock.
1405  */
1406 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1407 enum {
1408         /* Most machines require the value returned from malloc to be aligned
1409          * in some way.  The following macro will get this right
1410          * on many machines.  */
1411         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1412         /* Minimum size of a block */
1413         MINSIZE = SHELL_ALIGN(504),
1414 };
1415
1416 struct stack_block {
1417         struct stack_block *prev;
1418         char space[MINSIZE];
1419 };
1420
1421 struct stackmark {
1422         struct stack_block *stackp;
1423         char *stacknxt;
1424         size_t stacknleft;
1425 };
1426
1427
1428 struct globals_memstack {
1429         struct stack_block *g_stackp; // = &stackbase;
1430         char *g_stacknxt; // = stackbase.space;
1431         char *sstrend; // = stackbase.space + MINSIZE;
1432         size_t g_stacknleft; // = MINSIZE;
1433         struct stack_block stackbase;
1434 };
1435 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1436 #define G_memstack (*ash_ptr_to_globals_memstack)
1437 #define g_stackp     (G_memstack.g_stackp    )
1438 #define g_stacknxt   (G_memstack.g_stacknxt  )
1439 #define sstrend      (G_memstack.sstrend     )
1440 #define g_stacknleft (G_memstack.g_stacknleft)
1441 #define stackbase    (G_memstack.stackbase   )
1442 #define INIT_G_memstack() do { \
1443         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1444         barrier(); \
1445         g_stackp = &stackbase; \
1446         g_stacknxt = stackbase.space; \
1447         g_stacknleft = MINSIZE; \
1448         sstrend = stackbase.space + MINSIZE; \
1449 } while (0)
1450
1451
1452 #define stackblock()     ((void *)g_stacknxt)
1453 #define stackblocksize() g_stacknleft
1454
1455 /*
1456  * Parse trees for commands are allocated in lifo order, so we use a stack
1457  * to make this more efficient, and also to avoid all sorts of exception
1458  * handling code to handle interrupts in the middle of a parse.
1459  *
1460  * The size 504 was chosen because the Ultrix malloc handles that size
1461  * well.
1462  */
1463 static void *
1464 stalloc(size_t nbytes)
1465 {
1466         char *p;
1467         size_t aligned;
1468
1469         aligned = SHELL_ALIGN(nbytes);
1470         if (aligned > g_stacknleft) {
1471                 size_t len;
1472                 size_t blocksize;
1473                 struct stack_block *sp;
1474
1475                 blocksize = aligned;
1476                 if (blocksize < MINSIZE)
1477                         blocksize = MINSIZE;
1478                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1479                 if (len < blocksize)
1480                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1481                 INT_OFF;
1482                 sp = ckmalloc(len);
1483                 sp->prev = g_stackp;
1484                 g_stacknxt = sp->space;
1485                 g_stacknleft = blocksize;
1486                 sstrend = g_stacknxt + blocksize;
1487                 g_stackp = sp;
1488                 INT_ON;
1489         }
1490         p = g_stacknxt;
1491         g_stacknxt += aligned;
1492         g_stacknleft -= aligned;
1493         return p;
1494 }
1495
1496 static void *
1497 stzalloc(size_t nbytes)
1498 {
1499         return memset(stalloc(nbytes), 0, nbytes);
1500 }
1501
1502 static void
1503 stunalloc(void *p)
1504 {
1505 #if DEBUG
1506         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1507                 write(STDERR_FILENO, "stunalloc\n", 10);
1508                 abort();
1509         }
1510 #endif
1511         g_stacknleft += g_stacknxt - (char *)p;
1512         g_stacknxt = p;
1513 }
1514
1515 /*
1516  * Like strdup but works with the ash stack.
1517  */
1518 static char *
1519 sstrdup(const char *p)
1520 {
1521         size_t len = strlen(p) + 1;
1522         return memcpy(stalloc(len), p, len);
1523 }
1524
1525 static inline void
1526 grabstackblock(size_t len)
1527 {
1528         stalloc(len);
1529 }
1530
1531 static void
1532 pushstackmark(struct stackmark *mark, size_t len)
1533 {
1534         mark->stackp = g_stackp;
1535         mark->stacknxt = g_stacknxt;
1536         mark->stacknleft = g_stacknleft;
1537         grabstackblock(len);
1538 }
1539
1540 static void
1541 setstackmark(struct stackmark *mark)
1542 {
1543         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1544 }
1545
1546 static void
1547 popstackmark(struct stackmark *mark)
1548 {
1549         struct stack_block *sp;
1550
1551         if (!mark->stackp)
1552                 return;
1553
1554         INT_OFF;
1555         while (g_stackp != mark->stackp) {
1556                 sp = g_stackp;
1557                 g_stackp = sp->prev;
1558                 free(sp);
1559         }
1560         g_stacknxt = mark->stacknxt;
1561         g_stacknleft = mark->stacknleft;
1562         sstrend = mark->stacknxt + mark->stacknleft;
1563         INT_ON;
1564 }
1565
1566 /*
1567  * When the parser reads in a string, it wants to stick the string on the
1568  * stack and only adjust the stack pointer when it knows how big the
1569  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1570  * of space on top of the stack and stackblocklen returns the length of
1571  * this block.  Growstackblock will grow this space by at least one byte,
1572  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1573  * part of the block that has been used.
1574  */
1575 static void
1576 growstackblock(void)
1577 {
1578         size_t newlen;
1579
1580         newlen = g_stacknleft * 2;
1581         if (newlen < g_stacknleft)
1582                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1583         if (newlen < 128)
1584                 newlen += 128;
1585
1586         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1587                 struct stack_block *sp;
1588                 struct stack_block *prevstackp;
1589                 size_t grosslen;
1590
1591                 INT_OFF;
1592                 sp = g_stackp;
1593                 prevstackp = sp->prev;
1594                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1595                 sp = ckrealloc(sp, grosslen);
1596                 sp->prev = prevstackp;
1597                 g_stackp = sp;
1598                 g_stacknxt = sp->space;
1599                 g_stacknleft = newlen;
1600                 sstrend = sp->space + newlen;
1601                 INT_ON;
1602         } else {
1603                 char *oldspace = g_stacknxt;
1604                 size_t oldlen = g_stacknleft;
1605                 char *p = stalloc(newlen);
1606
1607                 /* free the space we just allocated */
1608                 g_stacknxt = memcpy(p, oldspace, oldlen);
1609                 g_stacknleft += newlen;
1610         }
1611 }
1612
1613 /*
1614  * The following routines are somewhat easier to use than the above.
1615  * The user declares a variable of type STACKSTR, which may be declared
1616  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1617  * the user uses the macro STPUTC to add characters to the string.  In
1618  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1619  * grown as necessary.  When the user is done, she can just leave the
1620  * string there and refer to it using stackblock().  Or she can allocate
1621  * the space for it using grabstackstr().  If it is necessary to allow
1622  * someone else to use the stack temporarily and then continue to grow
1623  * the string, the user should use grabstack to allocate the space, and
1624  * then call ungrabstr(p) to return to the previous mode of operation.
1625  *
1626  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1627  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1628  * is space for at least one character.
1629  */
1630 static void *
1631 growstackstr(void)
1632 {
1633         size_t len = stackblocksize();
1634         growstackblock();
1635         return (char *)stackblock() + len;
1636 }
1637
1638 /*
1639  * Called from CHECKSTRSPACE.
1640  */
1641 static char *
1642 makestrspace(size_t newlen, char *p)
1643 {
1644         size_t len = p - g_stacknxt;
1645         size_t size;
1646
1647         for (;;) {
1648                 size_t nleft;
1649
1650                 size = stackblocksize();
1651                 nleft = size - len;
1652                 if (nleft >= newlen)
1653                         break;
1654                 growstackblock();
1655         }
1656         return (char *)stackblock() + len;
1657 }
1658
1659 static char *
1660 stack_nputstr(const char *s, size_t n, char *p)
1661 {
1662         p = makestrspace(n, p);
1663         p = (char *)mempcpy(p, s, n);
1664         return p;
1665 }
1666
1667 static char *
1668 stack_putstr(const char *s, char *p)
1669 {
1670         return stack_nputstr(s, strlen(s), p);
1671 }
1672
1673 static char *
1674 _STPUTC(int c, char *p)
1675 {
1676         if (p == sstrend)
1677                 p = growstackstr();
1678         *p++ = c;
1679         return p;
1680 }
1681
1682 #define STARTSTACKSTR(p)        ((p) = stackblock())
1683 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1684 #define CHECKSTRSPACE(n, p) do { \
1685         char *q = (p); \
1686         size_t l = (n); \
1687         size_t m = sstrend - q; \
1688         if (l > m) \
1689                 (p) = makestrspace(l, q); \
1690 } while (0)
1691 #define USTPUTC(c, p)           (*(p)++ = (c))
1692 #define STACKSTRNUL(p) do { \
1693         if ((p) == sstrend) \
1694                 (p) = growstackstr(); \
1695         *(p) = '\0'; \
1696 } while (0)
1697 #define STUNPUTC(p)             (--(p))
1698 #define STTOPC(p)               ((p)[-1])
1699 #define STADJUST(amount, p)     ((p) += (amount))
1700
1701 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1702 #define ungrabstackstr(s, p)    stunalloc(s)
1703 #define stackstrend()           ((void *)sstrend)
1704
1705
1706 /* ============ String helpers */
1707
1708 /*
1709  * prefix -- see if pfx is a prefix of string.
1710  */
1711 static char *
1712 prefix(const char *string, const char *pfx)
1713 {
1714         while (*pfx) {
1715                 if (*pfx++ != *string++)
1716                         return NULL;
1717         }
1718         return (char *) string;
1719 }
1720
1721 /*
1722  * Check for a valid number.  This should be elsewhere.
1723  */
1724 static int
1725 is_number(const char *p)
1726 {
1727         do {
1728                 if (!isdigit(*p))
1729                         return 0;
1730         } while (*++p != '\0');
1731         return 1;
1732 }
1733
1734 /*
1735  * Convert a string of digits to an integer, printing an error message on
1736  * failure.
1737  */
1738 static int
1739 number(const char *s)
1740 {
1741         if (!is_number(s))
1742                 ash_msg_and_raise_error(msg_illnum, s);
1743         return atoi(s);
1744 }
1745
1746 /*
1747  * Produce a single quoted string suitable as input to the shell.
1748  * The return string is allocated on the stack.
1749  */
1750 static char *
1751 single_quote(const char *s)
1752 {
1753         char *p;
1754
1755         STARTSTACKSTR(p);
1756
1757         do {
1758                 char *q;
1759                 size_t len;
1760
1761                 len = strchrnul(s, '\'') - s;
1762
1763                 q = p = makestrspace(len + 3, p);
1764
1765                 *q++ = '\'';
1766                 q = (char *)mempcpy(q, s, len);
1767                 *q++ = '\'';
1768                 s += len;
1769
1770                 STADJUST(q - p, p);
1771
1772                 if (*s != '\'')
1773                         break;
1774                 len = 0;
1775                 do len++; while (*++s == '\'');
1776
1777                 q = p = makestrspace(len + 3, p);
1778
1779                 *q++ = '"';
1780                 q = (char *)mempcpy(q, s - len, len);
1781                 *q++ = '"';
1782
1783                 STADJUST(q - p, p);
1784         } while (*s);
1785
1786         USTPUTC('\0', p);
1787
1788         return stackblock();
1789 }
1790
1791 /*
1792  * Produce a possibly single quoted string suitable as input to the shell.
1793  * If quoting was done, the return string is allocated on the stack,
1794  * otherwise a pointer to the original string is returned.
1795  */
1796 static const char *
1797 maybe_single_quote(const char *s)
1798 {
1799         const char *p = s;
1800
1801         while (*p) {
1802                 /* Assuming ACSII */
1803                 /* quote ctrl_chars space !"#$%&'()* */
1804                 if (*p < '+')
1805                         goto need_quoting;
1806                 /* quote ;<=>? */
1807                 if (*p >= ';' && *p <= '?')
1808                         goto need_quoting;
1809                 /* quote `[\ */
1810                 if (*p == '`')
1811                         goto need_quoting;
1812                 if (*p == '[')
1813                         goto need_quoting;
1814                 if (*p == '\\')
1815                         goto need_quoting;
1816                 /* quote {|}~ DEL and high bytes */
1817                 if (*p > 'z')
1818                         goto need_quoting;
1819                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1820                 /* TODO: maybe avoid quoting % */
1821                 p++;
1822         }
1823         return s;
1824
1825  need_quoting:
1826         return single_quote(s);
1827 }
1828
1829
1830 /* ============ nextopt */
1831
1832 static char **argptr;                  /* argument list for builtin commands */
1833 static char *optionarg;                /* set by nextopt (like getopt) */
1834 static char *optptr;                   /* used by nextopt */
1835
1836 /*
1837  * XXX - should get rid of. Have all builtins use getopt(3).
1838  * The library getopt must have the BSD extension static variable
1839  * "optreset", otherwise it can't be used within the shell safely.
1840  *
1841  * Standard option processing (a la getopt) for builtin routines.
1842  * The only argument that is passed to nextopt is the option string;
1843  * the other arguments are unnecessary. It returns the character,
1844  * or '\0' on end of input.
1845  */
1846 static int
1847 nextopt(const char *optstring)
1848 {
1849         char *p;
1850         const char *q;
1851         char c;
1852
1853         p = optptr;
1854         if (p == NULL || *p == '\0') {
1855                 /* We ate entire "-param", take next one */
1856                 p = *argptr;
1857                 if (p == NULL)
1858                         return '\0';
1859                 if (*p != '-')
1860                         return '\0';
1861                 if (*++p == '\0') /* just "-" ? */
1862                         return '\0';
1863                 argptr++;
1864                 if (LONE_DASH(p)) /* "--" ? */
1865                         return '\0';
1866                 /* p => next "-param" */
1867         }
1868         /* p => some option char in the middle of a "-param" */
1869         c = *p++;
1870         for (q = optstring; *q != c;) {
1871                 if (*q == '\0')
1872                         ash_msg_and_raise_error("illegal option -%c", c);
1873                 if (*++q == ':')
1874                         q++;
1875         }
1876         if (*++q == ':') {
1877                 if (*p == '\0') {
1878                         p = *argptr++;
1879                         if (p == NULL)
1880                                 ash_msg_and_raise_error("no arg for -%c option", c);
1881                 }
1882                 optionarg = p;
1883                 p = NULL;
1884         }
1885         optptr = p;
1886         return c;
1887 }
1888
1889
1890 /* ============ Shell variables */
1891
1892 /*
1893  * The parsefile structure pointed to by the global variable parsefile
1894  * contains information about the current file being read.
1895  */
1896 struct shparam {
1897         int nparam;             /* # of positional parameters (without $0) */
1898 #if ENABLE_ASH_GETOPTS
1899         int optind;             /* next parameter to be processed by getopts */
1900         int optoff;             /* used by getopts */
1901 #endif
1902         unsigned char malloced; /* if parameter list dynamically allocated */
1903         char **p;               /* parameter list */
1904 };
1905
1906 /*
1907  * Free the list of positional parameters.
1908  */
1909 static void
1910 freeparam(volatile struct shparam *param)
1911 {
1912         if (param->malloced) {
1913                 char **ap, **ap1;
1914                 ap = ap1 = param->p;
1915                 while (*ap)
1916                         free(*ap++);
1917                 free(ap1);
1918         }
1919 }
1920
1921 #if ENABLE_ASH_GETOPTS
1922 static void FAST_FUNC getoptsreset(const char *value);
1923 #endif
1924
1925 struct var {
1926         struct var *next;               /* next entry in hash list */
1927         int flags;                      /* flags are defined above */
1928         const char *var_text;           /* name=value */
1929         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1930                                         /* the variable gets set/unset */
1931 };
1932
1933 struct localvar {
1934         struct localvar *next;          /* next local variable in list */
1935         struct var *vp;                 /* the variable that was made local */
1936         int flags;                      /* saved flags */
1937         const char *text;               /* saved text */
1938 };
1939
1940 /* flags */
1941 #define VEXPORT         0x01    /* variable is exported */
1942 #define VREADONLY       0x02    /* variable cannot be modified */
1943 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1944 #define VTEXTFIXED      0x08    /* text is statically allocated */
1945 #define VSTACK          0x10    /* text is allocated on the stack */
1946 #define VUNSET          0x20    /* the variable is not set */
1947 #define VNOFUNC         0x40    /* don't call the callback function */
1948 #define VNOSET          0x80    /* do not set variable - just readonly test */
1949 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1950 #if ENABLE_ASH_RANDOM_SUPPORT
1951 # define VDYNAMIC       0x200   /* dynamic variable */
1952 #else
1953 # define VDYNAMIC       0
1954 #endif
1955
1956
1957 /* Need to be before varinit_data[] */
1958 #if ENABLE_LOCALE_SUPPORT
1959 static void FAST_FUNC
1960 change_lc_all(const char *value)
1961 {
1962         if (value && *value != '\0')
1963                 setlocale(LC_ALL, value);
1964 }
1965 static void FAST_FUNC
1966 change_lc_ctype(const char *value)
1967 {
1968         if (value && *value != '\0')
1969                 setlocale(LC_CTYPE, value);
1970 }
1971 #endif
1972 #if ENABLE_ASH_MAIL
1973 static void chkmail(void);
1974 static void changemail(const char *var_value) FAST_FUNC;
1975 #else
1976 # define chkmail()  ((void)0)
1977 #endif
1978 static void changepath(const char *) FAST_FUNC;
1979 #if ENABLE_ASH_RANDOM_SUPPORT
1980 static void change_random(const char *) FAST_FUNC;
1981 #endif
1982
1983 static const struct {
1984         int flags;
1985         const char *var_text;
1986         void (*var_func)(const char *) FAST_FUNC;
1987 } varinit_data[] = {
1988         /*
1989          * Note: VEXPORT would not work correctly here for NOFORK applets:
1990          * some environment strings may be constant.
1991          */
1992         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1993 #if ENABLE_ASH_MAIL
1994         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1995         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1996 #endif
1997         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1998         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1999         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2000         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2001 #if ENABLE_ASH_GETOPTS
2002         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2003 #endif
2004 #if ENABLE_ASH_RANDOM_SUPPORT
2005         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2006 #endif
2007 #if ENABLE_LOCALE_SUPPORT
2008         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2009         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2010 #endif
2011 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2012         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2013 #endif
2014 };
2015
2016 struct redirtab;
2017
2018 struct globals_var {
2019         struct shparam shellparam;      /* $@ current positional parameters */
2020         struct redirtab *redirlist;
2021         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2022         struct var *vartab[VTABSIZE];
2023         struct var varinit[ARRAY_SIZE(varinit_data)];
2024 };
2025 extern struct globals_var *const ash_ptr_to_globals_var;
2026 #define G_var (*ash_ptr_to_globals_var)
2027 #define shellparam    (G_var.shellparam   )
2028 //#define redirlist     (G_var.redirlist    )
2029 #define preverrout_fd (G_var.preverrout_fd)
2030 #define vartab        (G_var.vartab       )
2031 #define varinit       (G_var.varinit      )
2032 #define INIT_G_var() do { \
2033         unsigned i; \
2034         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2035         barrier(); \
2036         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2037                 varinit[i].flags    = varinit_data[i].flags; \
2038                 varinit[i].var_text = varinit_data[i].var_text; \
2039                 varinit[i].var_func = varinit_data[i].var_func; \
2040         } \
2041 } while (0)
2042
2043 #define vifs      varinit[0]
2044 #if ENABLE_ASH_MAIL
2045 # define vmail    (&vifs)[1]
2046 # define vmpath   (&vmail)[1]
2047 # define vpath    (&vmpath)[1]
2048 #else
2049 # define vpath    (&vifs)[1]
2050 #endif
2051 #define vps1      (&vpath)[1]
2052 #define vps2      (&vps1)[1]
2053 #define vps4      (&vps2)[1]
2054 #if ENABLE_ASH_GETOPTS
2055 # define voptind  (&vps4)[1]
2056 # if ENABLE_ASH_RANDOM_SUPPORT
2057 #  define vrandom (&voptind)[1]
2058 # endif
2059 #else
2060 # if ENABLE_ASH_RANDOM_SUPPORT
2061 #  define vrandom (&vps4)[1]
2062 # endif
2063 #endif
2064
2065 /*
2066  * The following macros access the values of the above variables.
2067  * They have to skip over the name.  They return the null string
2068  * for unset variables.
2069  */
2070 #define ifsval()        (vifs.var_text + 4)
2071 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2072 #if ENABLE_ASH_MAIL
2073 # define mailval()      (vmail.var_text + 5)
2074 # define mpathval()     (vmpath.var_text + 9)
2075 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2076 #endif
2077 #define pathval()       (vpath.var_text + 5)
2078 #define ps1val()        (vps1.var_text + 4)
2079 #define ps2val()        (vps2.var_text + 4)
2080 #define ps4val()        (vps4.var_text + 4)
2081 #if ENABLE_ASH_GETOPTS
2082 # define optindval()    (voptind.var_text + 7)
2083 #endif
2084
2085 #if ENABLE_ASH_GETOPTS
2086 static void FAST_FUNC
2087 getoptsreset(const char *value)
2088 {
2089         shellparam.optind = number(value) ?: 1;
2090         shellparam.optoff = -1;
2091 }
2092 #endif
2093
2094 /*
2095  * Compares two strings up to the first = or '\0'.  The first
2096  * string must be terminated by '='; the second may be terminated by
2097  * either '=' or '\0'.
2098  */
2099 static int
2100 varcmp(const char *p, const char *q)
2101 {
2102         int c, d;
2103
2104         while ((c = *p) == (d = *q)) {
2105                 if (c == '\0' || c == '=')
2106                         goto out;
2107                 p++;
2108                 q++;
2109         }
2110         if (c == '=')
2111                 c = '\0';
2112         if (d == '=')
2113                 d = '\0';
2114  out:
2115         return c - d;
2116 }
2117
2118 /*
2119  * Find the appropriate entry in the hash table from the name.
2120  */
2121 static struct var **
2122 hashvar(const char *p)
2123 {
2124         unsigned hashval;
2125
2126         hashval = ((unsigned char) *p) << 4;
2127         while (*p && *p != '=')
2128                 hashval += (unsigned char) *p++;
2129         return &vartab[hashval % VTABSIZE];
2130 }
2131
2132 static int
2133 vpcmp(const void *a, const void *b)
2134 {
2135         return varcmp(*(const char **)a, *(const char **)b);
2136 }
2137
2138 /*
2139  * This routine initializes the builtin variables.
2140  */
2141 static void
2142 initvar(void)
2143 {
2144         struct var *vp;
2145         struct var *end;
2146         struct var **vpp;
2147
2148         /*
2149          * PS1 depends on uid
2150          */
2151 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2152         vps1.var_text = "PS1=\\w \\$ ";
2153 #else
2154         if (!geteuid())
2155                 vps1.var_text = "PS1=# ";
2156 #endif
2157         vp = varinit;
2158         end = vp + ARRAY_SIZE(varinit);
2159         do {
2160                 vpp = hashvar(vp->var_text);
2161                 vp->next = *vpp;
2162                 *vpp = vp;
2163         } while (++vp < end);
2164 }
2165
2166 static struct var **
2167 findvar(struct var **vpp, const char *name)
2168 {
2169         for (; *vpp; vpp = &(*vpp)->next) {
2170                 if (varcmp((*vpp)->var_text, name) == 0) {
2171                         break;
2172                 }
2173         }
2174         return vpp;
2175 }
2176
2177 /*
2178  * Find the value of a variable.  Returns NULL if not set.
2179  */
2180 static const char* FAST_FUNC
2181 lookupvar(const char *name)
2182 {
2183         struct var *v;
2184
2185         v = *findvar(hashvar(name), name);
2186         if (v) {
2187 #if ENABLE_ASH_RANDOM_SUPPORT
2188         /*
2189          * Dynamic variables are implemented roughly the same way they are
2190          * in bash. Namely, they're "special" so long as they aren't unset.
2191          * As soon as they're unset, they're no longer dynamic, and dynamic
2192          * lookup will no longer happen at that point. -- PFM.
2193          */
2194                 if (v->flags & VDYNAMIC)
2195                         v->var_func(NULL);
2196 #endif
2197                 if (!(v->flags & VUNSET))
2198                         return var_end(v->var_text);
2199         }
2200         return NULL;
2201 }
2202
2203 #if ENABLE_UNICODE_SUPPORT
2204 static void
2205 reinit_unicode_for_ash(void)
2206 {
2207         /* Unicode support should be activated even if LANG is set
2208          * _during_ shell execution, not only if it was set when
2209          * shell was started. Therefore, re-check LANG every time:
2210          */
2211         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2212          || ENABLE_UNICODE_USING_LOCALE
2213         ) {
2214                 const char *s = lookupvar("LC_ALL");
2215                 if (!s) s = lookupvar("LC_CTYPE");
2216                 if (!s) s = lookupvar("LANG");
2217                 reinit_unicode(s);
2218         }
2219 }
2220 #else
2221 # define reinit_unicode_for_ash() ((void)0)
2222 #endif
2223
2224 /*
2225  * Search the environment of a builtin command.
2226  */
2227 static inline const char *
2228 bltinlookup(const char *name)
2229 {
2230         return lookupvar(name);
2231 }
2232
2233 /*
2234  * Same as setvar except that the variable and value are passed in
2235  * the first argument as name=value.  Since the first argument will
2236  * be actually stored in the table, it should not be a string that
2237  * will go away.
2238  * Called with interrupts off.
2239  */
2240 static void
2241 setvareq(char *s, int flags)
2242 {
2243         struct var *vp, **vpp;
2244
2245         vpp = hashvar(s);
2246         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2247         vp = *findvar(vpp, s);
2248         if (vp) {
2249                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2250                         const char *n;
2251
2252                         if (flags & VNOSAVE)
2253                                 free(s);
2254                         n = vp->var_text;
2255                         exitstatus = 1;
2256                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2257                 }
2258
2259                 if (flags & VNOSET)
2260                         return;
2261
2262                 if (vp->var_func && !(flags & VNOFUNC))
2263                         vp->var_func(var_end(s));
2264
2265                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2266                         free((char*)vp->var_text);
2267
2268                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2269                         *vpp = vp->next;
2270                         free(vp);
2271  out_free:
2272                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2273                                 free(s);
2274                         return;
2275                 }
2276
2277                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2278         } else {
2279                 /* variable s is not found */
2280                 if (flags & VNOSET)
2281                         return;
2282                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2283                         goto out_free;
2284                 vp = ckzalloc(sizeof(*vp));
2285                 vp->next = *vpp;
2286                 /*vp->func = NULL; - ckzalloc did it */
2287                 *vpp = vp;
2288         }
2289         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2290                 s = ckstrdup(s);
2291         vp->var_text = s;
2292         vp->flags = flags;
2293 }
2294
2295 /*
2296  * Set the value of a variable.  The flags argument is ored with the
2297  * flags of the variable.  If val is NULL, the variable is unset.
2298  */
2299 static void
2300 setvar(const char *name, const char *val, int flags)
2301 {
2302         const char *q;
2303         char *p;
2304         char *nameeq;
2305         size_t namelen;
2306         size_t vallen;
2307
2308         q = endofname(name);
2309         p = strchrnul(q, '=');
2310         namelen = p - name;
2311         if (!namelen || p != q)
2312                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2313         vallen = 0;
2314         if (val == NULL) {
2315                 flags |= VUNSET;
2316         } else {
2317                 vallen = strlen(val);
2318         }
2319
2320         INT_OFF;
2321         nameeq = ckmalloc(namelen + vallen + 2);
2322         p = mempcpy(nameeq, name, namelen);
2323         if (val) {
2324                 *p++ = '=';
2325                 p = mempcpy(p, val, vallen);
2326         }
2327         *p = '\0';
2328         setvareq(nameeq, flags | VNOSAVE);
2329         INT_ON;
2330 }
2331
2332 static void FAST_FUNC
2333 setvar0(const char *name, const char *val)
2334 {
2335         setvar(name, val, 0);
2336 }
2337
2338 /*
2339  * Unset the specified variable.
2340  */
2341 static void
2342 unsetvar(const char *s)
2343 {
2344         setvar(s, NULL, 0);
2345 }
2346
2347 /*
2348  * Process a linked list of variable assignments.
2349  */
2350 static void
2351 listsetvar(struct strlist *list_set_var, int flags)
2352 {
2353         struct strlist *lp = list_set_var;
2354
2355         if (!lp)
2356                 return;
2357         INT_OFF;
2358         do {
2359                 setvareq(lp->text, flags);
2360                 lp = lp->next;
2361         } while (lp);
2362         INT_ON;
2363 }
2364
2365 /*
2366  * Generate a list of variables satisfying the given conditions.
2367  */
2368 static char **
2369 listvars(int on, int off, char ***end)
2370 {
2371         struct var **vpp;
2372         struct var *vp;
2373         char **ep;
2374         int mask;
2375
2376         STARTSTACKSTR(ep);
2377         vpp = vartab;
2378         mask = on | off;
2379         do {
2380                 for (vp = *vpp; vp; vp = vp->next) {
2381                         if ((vp->flags & mask) == on) {
2382                                 if (ep == stackstrend())
2383                                         ep = growstackstr();
2384                                 *ep++ = (char*)vp->var_text;
2385                         }
2386                 }
2387         } while (++vpp < vartab + VTABSIZE);
2388         if (ep == stackstrend())
2389                 ep = growstackstr();
2390         if (end)
2391                 *end = ep;
2392         *ep++ = NULL;
2393         return grabstackstr(ep);
2394 }
2395
2396
2397 /* ============ Path search helper
2398  *
2399  * The variable path (passed by reference) should be set to the start
2400  * of the path before the first call; path_advance will update
2401  * this value as it proceeds.  Successive calls to path_advance will return
2402  * the possible path expansions in sequence.  If an option (indicated by
2403  * a percent sign) appears in the path entry then the global variable
2404  * pathopt will be set to point to it; otherwise pathopt will be set to
2405  * NULL.
2406  */
2407 static const char *pathopt;     /* set by path_advance */
2408
2409 static char *
2410 path_advance(const char **path, const char *name)
2411 {
2412         const char *p;
2413         char *q;
2414         const char *start;
2415         size_t len;
2416
2417         if (*path == NULL)
2418                 return NULL;
2419         start = *path;
2420         for (p = start; *p && *p != ':' && *p != '%'; p++)
2421                 continue;
2422         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2423         while (stackblocksize() < len)
2424                 growstackblock();
2425         q = stackblock();
2426         if (p != start) {
2427                 q = mempcpy(q, start, p - start);
2428                 *q++ = '/';
2429         }
2430         strcpy(q, name);
2431         pathopt = NULL;
2432         if (*p == '%') {
2433                 pathopt = ++p;
2434                 while (*p && *p != ':')
2435                         p++;
2436         }
2437         if (*p == ':')
2438                 *path = p + 1;
2439         else
2440                 *path = NULL;
2441         return stalloc(len);
2442 }
2443
2444
2445 /* ============ Prompt */
2446
2447 static smallint doprompt;                   /* if set, prompt the user */
2448 static smallint needprompt;                 /* true if interactive and at start of line */
2449
2450 #if ENABLE_FEATURE_EDITING
2451 static line_input_t *line_input_state;
2452 static const char *cmdedit_prompt;
2453 static void
2454 putprompt(const char *s)
2455 {
2456         if (ENABLE_ASH_EXPAND_PRMT) {
2457                 free((char*)cmdedit_prompt);
2458                 cmdedit_prompt = ckstrdup(s);
2459                 return;
2460         }
2461         cmdedit_prompt = s;
2462 }
2463 #else
2464 static void
2465 putprompt(const char *s)
2466 {
2467         out2str(s);
2468 }
2469 #endif
2470
2471 /* expandstr() needs parsing machinery, so it is far away ahead... */
2472 static const char *expandstr(const char *ps);
2473
2474 static void
2475 setprompt_if(smallint do_set, int whichprompt)
2476 {
2477         const char *prompt;
2478         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2479
2480         if (!do_set)
2481                 return;
2482
2483         needprompt = 0;
2484
2485         switch (whichprompt) {
2486         case 1:
2487                 prompt = ps1val();
2488                 break;
2489         case 2:
2490                 prompt = ps2val();
2491                 break;
2492         default:                        /* 0 */
2493                 prompt = nullstr;
2494         }
2495 #if ENABLE_ASH_EXPAND_PRMT
2496         pushstackmark(&smark, stackblocksize());
2497         putprompt(expandstr(prompt));
2498         popstackmark(&smark);
2499 #else
2500         putprompt(prompt);
2501 #endif
2502 }
2503
2504
2505 /* ============ The cd and pwd commands */
2506
2507 #define CD_PHYSICAL 1
2508 #define CD_PRINT 2
2509
2510 static int
2511 cdopt(void)
2512 {
2513         int flags = 0;
2514         int i, j;
2515
2516         j = 'L';
2517         while ((i = nextopt("LP")) != '\0') {
2518                 if (i != j) {
2519                         flags ^= CD_PHYSICAL;
2520                         j = i;
2521                 }
2522         }
2523
2524         return flags;
2525 }
2526
2527 /*
2528  * Update curdir (the name of the current directory) in response to a
2529  * cd command.
2530  */
2531 static const char *
2532 updatepwd(const char *dir)
2533 {
2534         char *new;
2535         char *p;
2536         char *cdcomppath;
2537         const char *lim;
2538
2539         cdcomppath = sstrdup(dir);
2540         STARTSTACKSTR(new);
2541         if (*dir != '/') {
2542                 if (curdir == nullstr)
2543                         return 0;
2544                 new = stack_putstr(curdir, new);
2545         }
2546         new = makestrspace(strlen(dir) + 2, new);
2547         lim = (char *)stackblock() + 1;
2548         if (*dir != '/') {
2549                 if (new[-1] != '/')
2550                         USTPUTC('/', new);
2551                 if (new > lim && *lim == '/')
2552                         lim++;
2553         } else {
2554                 USTPUTC('/', new);
2555                 cdcomppath++;
2556                 if (dir[1] == '/' && dir[2] != '/') {
2557                         USTPUTC('/', new);
2558                         cdcomppath++;
2559                         lim++;
2560                 }
2561         }
2562         p = strtok(cdcomppath, "/");
2563         while (p) {
2564                 switch (*p) {
2565                 case '.':
2566                         if (p[1] == '.' && p[2] == '\0') {
2567                                 while (new > lim) {
2568                                         STUNPUTC(new);
2569                                         if (new[-1] == '/')
2570                                                 break;
2571                                 }
2572                                 break;
2573                         }
2574                         if (p[1] == '\0')
2575                                 break;
2576                         /* fall through */
2577                 default:
2578                         new = stack_putstr(p, new);
2579                         USTPUTC('/', new);
2580                 }
2581                 p = strtok(NULL, "/");
2582         }
2583         if (new > lim)
2584                 STUNPUTC(new);
2585         *new = 0;
2586         return stackblock();
2587 }
2588
2589 /*
2590  * Find out what the current directory is. If we already know the current
2591  * directory, this routine returns immediately.
2592  */
2593 static char *
2594 getpwd(void)
2595 {
2596         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2597         return dir ? dir : nullstr;
2598 }
2599
2600 static void
2601 setpwd(const char *val, int setold)
2602 {
2603         char *oldcur, *dir;
2604
2605         oldcur = dir = curdir;
2606
2607         if (setold) {
2608                 setvar("OLDPWD", oldcur, VEXPORT);
2609         }
2610         INT_OFF;
2611         if (physdir != nullstr) {
2612                 if (physdir != oldcur)
2613                         free(physdir);
2614                 physdir = nullstr;
2615         }
2616         if (oldcur == val || !val) {
2617                 char *s = getpwd();
2618                 physdir = s;
2619                 if (!val)
2620                         dir = s;
2621         } else
2622                 dir = ckstrdup(val);
2623         if (oldcur != dir && oldcur != nullstr) {
2624                 free(oldcur);
2625         }
2626         curdir = dir;
2627         INT_ON;
2628         setvar("PWD", dir, VEXPORT);
2629 }
2630
2631 static void hashcd(void);
2632
2633 /*
2634  * Actually do the chdir.  We also call hashcd to let other routines
2635  * know that the current directory has changed.
2636  */
2637 static int
2638 docd(const char *dest, int flags)
2639 {
2640         const char *dir = NULL;
2641         int err;
2642
2643         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2644
2645         INT_OFF;
2646         if (!(flags & CD_PHYSICAL)) {
2647                 dir = updatepwd(dest);
2648                 if (dir)
2649                         dest = dir;
2650         }
2651         err = chdir(dest);
2652         if (err)
2653                 goto out;
2654         setpwd(dir, 1);
2655         hashcd();
2656  out:
2657         INT_ON;
2658         return err;
2659 }
2660
2661 static int FAST_FUNC
2662 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2663 {
2664         const char *dest;
2665         const char *path;
2666         const char *p;
2667         char c;
2668         struct stat statb;
2669         int flags;
2670
2671         flags = cdopt();
2672         dest = *argptr;
2673         if (!dest)
2674                 dest = bltinlookup("HOME");
2675         else if (LONE_DASH(dest)) {
2676                 dest = bltinlookup("OLDPWD");
2677                 flags |= CD_PRINT;
2678         }
2679         if (!dest)
2680                 dest = nullstr;
2681         if (*dest == '/')
2682                 goto step6;
2683         if (*dest == '.') {
2684                 c = dest[1];
2685  dotdot:
2686                 switch (c) {
2687                 case '\0':
2688                 case '/':
2689                         goto step6;
2690                 case '.':
2691                         c = dest[2];
2692                         if (c != '.')
2693                                 goto dotdot;
2694                 }
2695         }
2696         if (!*dest)
2697                 dest = ".";
2698         path = bltinlookup("CDPATH");
2699         while (path) {
2700                 c = *path;
2701                 p = path_advance(&path, dest);
2702                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2703                         if (c && c != ':')
2704                                 flags |= CD_PRINT;
2705  docd:
2706                         if (!docd(p, flags))
2707                                 goto out;
2708                         goto err;
2709                 }
2710         }
2711
2712  step6:
2713         p = dest;
2714         goto docd;
2715
2716  err:
2717         ash_msg_and_raise_error("can't cd to %s", dest);
2718         /* NOTREACHED */
2719  out:
2720         if (flags & CD_PRINT)
2721                 out1fmt("%s\n", curdir);
2722         return 0;
2723 }
2724
2725 static int FAST_FUNC
2726 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2727 {
2728         int flags;
2729         const char *dir = curdir;
2730
2731         flags = cdopt();
2732         if (flags) {
2733                 if (physdir == nullstr)
2734                         setpwd(dir, 0);
2735                 dir = physdir;
2736         }
2737         out1fmt("%s\n", dir);
2738         return 0;
2739 }
2740
2741
2742 /* ============ ... */
2743
2744
2745 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2746
2747 /* Syntax classes */
2748 #define CWORD     0             /* character is nothing special */
2749 #define CNL       1             /* newline character */
2750 #define CBACK     2             /* a backslash character */
2751 #define CSQUOTE   3             /* single quote */
2752 #define CDQUOTE   4             /* double quote */
2753 #define CENDQUOTE 5             /* a terminating quote */
2754 #define CBQUOTE   6             /* backwards single quote */
2755 #define CVAR      7             /* a dollar sign */
2756 #define CENDVAR   8             /* a '}' character */
2757 #define CLP       9             /* a left paren in arithmetic */
2758 #define CRP      10             /* a right paren in arithmetic */
2759 #define CENDFILE 11             /* end of file */
2760 #define CCTL     12             /* like CWORD, except it must be escaped */
2761 #define CSPCL    13             /* these terminate a word */
2762 #define CIGN     14             /* character should be ignored */
2763
2764 #define PEOF     256
2765 #if ENABLE_ASH_ALIAS
2766 # define PEOA    257
2767 #endif
2768
2769 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2770
2771 #if ENABLE_FEATURE_SH_MATH
2772 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2773 #else
2774 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2775 #endif
2776 static const uint16_t S_I_T[] ALIGN2 = {
2777 #if ENABLE_ASH_ALIAS
2778         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2779 #endif
2780         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2781         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2782         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2783         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2784         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2785         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2786         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2787         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2788         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2789         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2790         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2791 #if !USE_SIT_FUNCTION
2792         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2793         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2794         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2795 #endif
2796 #undef SIT_ITEM
2797 };
2798 /* Constants below must match table above */
2799 enum {
2800 #if ENABLE_ASH_ALIAS
2801         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2802 #endif
2803         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2804         CNL_CNL_CNL_CNL                    , /*  2 */
2805         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2806         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2807         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2808         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2809         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2810         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2811         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2812         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2813         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2814         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2815         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2816         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2817 };
2818
2819 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2820  * caller must ensure proper cast on it if c is *char_ptr!
2821  */
2822 /* Values for syntax param */
2823 #define BASESYNTAX 0    /* not in quotes */
2824 #define DQSYNTAX   1    /* in double quotes */
2825 #define SQSYNTAX   2    /* in single quotes */
2826 #define ARISYNTAX  3    /* in arithmetic */
2827 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2828
2829 #if USE_SIT_FUNCTION
2830
2831 static int
2832 SIT(int c, int syntax)
2833 {
2834         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2835         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2836         /*
2837          * This causes '/' to be prepended with CTLESC in dquoted string,
2838          * making "./file"* treated incorrectly because we feed
2839          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2840          * The "homegrown" glob implementation is okay with that,
2841          * but glibc one isn't. With '/' always treated as CWORD,
2842          * both work fine.
2843          */
2844 # if ENABLE_ASH_ALIAS
2845         static const uint8_t syntax_index_table[] ALIGN1 = {
2846                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2847                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2848                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2849                 11, 3                           /* "}~" */
2850         };
2851 # else
2852         static const uint8_t syntax_index_table[] ALIGN1 = {
2853                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2854                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2855                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2856                 10, 2                           /* "}~" */
2857         };
2858 # endif
2859         const char *s;
2860         int indx;
2861
2862         if (c == PEOF)
2863                 return CENDFILE;
2864 # if ENABLE_ASH_ALIAS
2865         if (c == PEOA)
2866                 indx = 0;
2867         else
2868 # endif
2869         {
2870                 /* Cast is purely for paranoia here,
2871                  * just in case someone passed signed char to us */
2872                 if ((unsigned char)c >= CTL_FIRST
2873                  && (unsigned char)c <= CTL_LAST
2874                 ) {
2875                         return CCTL;
2876                 }
2877                 s = strchrnul(spec_symbls, c);
2878                 if (*s == '\0')
2879                         return CWORD;
2880                 indx = syntax_index_table[s - spec_symbls];
2881         }
2882         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2883 }
2884
2885 #else   /* !USE_SIT_FUNCTION */
2886
2887 static const uint8_t syntax_index_table[] ALIGN1 = {
2888         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2889         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2890         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2891         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2892         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2893         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2894         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2895         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2896         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2897         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2898         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2899         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2900         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2901         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2902         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2903         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2904         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2912         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2913         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2914         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2915         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2916         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2917         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2918         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2919         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2920         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2921         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2922         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2923         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2924         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2925         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2926         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2927         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2928         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2929         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2930         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2931         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2932         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2934         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2935         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2936 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2937         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2939         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2940         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2941         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2943         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2949         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2950         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2951         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2952         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2953         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2954         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2982         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2983         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2984         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2987         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3015         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3016         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3017         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3018         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3019         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3020         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3021         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3022         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3023         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3024         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3025         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3026         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3027         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3146         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3147 # if ENABLE_ASH_ALIAS
3148         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3149 # endif
3150 };
3151
3152 #if 1
3153 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3154 #else /* debug version, caught one signed char bug */
3155 # define SIT(c, syntax) \
3156         ({ \
3157                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3158                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3159                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3160                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3161                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3162         })
3163 #endif
3164
3165 #endif  /* !USE_SIT_FUNCTION */
3166
3167
3168 /* ============ Alias handling */
3169
3170 #if ENABLE_ASH_ALIAS
3171
3172 #define ALIASINUSE 1
3173 #define ALIASDEAD  2
3174
3175 struct alias {
3176         struct alias *next;
3177         char *name;
3178         char *val;
3179         int flag;
3180 };
3181
3182
3183 static struct alias **atab; // [ATABSIZE];
3184 #define INIT_G_alias() do { \
3185         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3186 } while (0)
3187
3188
3189 static struct alias **
3190 __lookupalias(const char *name)
3191 {
3192         unsigned int hashval;
3193         struct alias **app;
3194         const char *p;
3195         unsigned int ch;
3196
3197         p = name;
3198
3199         ch = (unsigned char)*p;
3200         hashval = ch << 4;
3201         while (ch) {
3202                 hashval += ch;
3203                 ch = (unsigned char)*++p;
3204         }
3205         app = &atab[hashval % ATABSIZE];
3206
3207         for (; *app; app = &(*app)->next) {
3208                 if (strcmp(name, (*app)->name) == 0) {
3209                         break;
3210                 }
3211         }
3212
3213         return app;
3214 }
3215
3216 static struct alias *
3217 lookupalias(const char *name, int check)
3218 {
3219         struct alias *ap = *__lookupalias(name);
3220
3221         if (check && ap && (ap->flag & ALIASINUSE))
3222                 return NULL;
3223         return ap;
3224 }
3225
3226 static struct alias *
3227 freealias(struct alias *ap)
3228 {
3229         struct alias *next;
3230
3231         if (ap->flag & ALIASINUSE) {
3232                 ap->flag |= ALIASDEAD;
3233                 return ap;
3234         }
3235
3236         next = ap->next;
3237         free(ap->name);
3238         free(ap->val);
3239         free(ap);
3240         return next;
3241 }
3242
3243 static void
3244 setalias(const char *name, const char *val)
3245 {
3246         struct alias *ap, **app;
3247
3248         app = __lookupalias(name);
3249         ap = *app;
3250         INT_OFF;
3251         if (ap) {
3252                 if (!(ap->flag & ALIASINUSE)) {
3253                         free(ap->val);
3254                 }
3255                 ap->val = ckstrdup(val);
3256                 ap->flag &= ~ALIASDEAD;
3257         } else {
3258                 /* not found */
3259                 ap = ckzalloc(sizeof(struct alias));
3260                 ap->name = ckstrdup(name);
3261                 ap->val = ckstrdup(val);
3262                 /*ap->flag = 0; - ckzalloc did it */
3263                 /*ap->next = NULL;*/
3264                 *app = ap;
3265         }
3266         INT_ON;
3267 }
3268
3269 static int
3270 unalias(const char *name)
3271 {
3272         struct alias **app;
3273
3274         app = __lookupalias(name);
3275
3276         if (*app) {
3277                 INT_OFF;
3278                 *app = freealias(*app);
3279                 INT_ON;
3280                 return 0;
3281         }
3282
3283         return 1;
3284 }
3285
3286 static void
3287 rmaliases(void)
3288 {
3289         struct alias *ap, **app;
3290         int i;
3291
3292         INT_OFF;
3293         for (i = 0; i < ATABSIZE; i++) {
3294                 app = &atab[i];
3295                 for (ap = *app; ap; ap = *app) {
3296                         *app = freealias(*app);
3297                         if (ap == *app) {
3298                                 app = &ap->next;
3299                         }
3300                 }
3301         }
3302         INT_ON;
3303 }
3304
3305 static void
3306 printalias(const struct alias *ap)
3307 {
3308         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3309 }
3310
3311 /*
3312  * TODO - sort output
3313  */
3314 static int FAST_FUNC
3315 aliascmd(int argc UNUSED_PARAM, char **argv)
3316 {
3317         char *n, *v;
3318         int ret = 0;
3319         struct alias *ap;
3320
3321         if (!argv[1]) {
3322                 int i;
3323
3324                 for (i = 0; i < ATABSIZE; i++) {
3325                         for (ap = atab[i]; ap; ap = ap->next) {
3326                                 printalias(ap);
3327                         }
3328                 }
3329                 return 0;
3330         }
3331         while ((n = *++argv) != NULL) {
3332                 v = strchr(n+1, '=');
3333                 if (v == NULL) { /* n+1: funny ksh stuff */
3334                         ap = *__lookupalias(n);
3335                         if (ap == NULL) {
3336                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3337                                 ret = 1;
3338                         } else
3339                                 printalias(ap);
3340                 } else {
3341                         *v++ = '\0';
3342                         setalias(n, v);
3343                 }
3344         }
3345
3346         return ret;
3347 }
3348
3349 static int FAST_FUNC
3350 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3351 {
3352         int i;
3353
3354         while (nextopt("a") != '\0') {
3355                 rmaliases();
3356                 return 0;
3357         }
3358         for (i = 0; *argptr; argptr++) {
3359                 if (unalias(*argptr)) {
3360                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3361                         i = 1;
3362                 }
3363         }
3364
3365         return i;
3366 }
3367
3368 #endif /* ASH_ALIAS */
3369
3370
3371 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3372 #define FORK_FG    0
3373 #define FORK_BG    1
3374 #define FORK_NOJOB 2
3375
3376 /* mode flags for showjob(s) */
3377 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3378 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3379 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3380 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3381
3382 /*
3383  * A job structure contains information about a job.  A job is either a
3384  * single process or a set of processes contained in a pipeline.  In the
3385  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3386  * array of pids.
3387  */
3388 struct procstat {
3389         pid_t   ps_pid;         /* process id */
3390         int     ps_status;      /* last process status from wait() */
3391         char    *ps_cmd;        /* text of command being run */
3392 };
3393
3394 struct job {
3395         struct procstat ps0;    /* status of process */
3396         struct procstat *ps;    /* status or processes when more than one */
3397 #if JOBS
3398         int stopstatus;         /* status of a stopped job */
3399 #endif
3400         unsigned nprocs;        /* number of processes */
3401
3402 #define JOBRUNNING      0       /* at least one proc running */
3403 #define JOBSTOPPED      1       /* all procs are stopped */
3404 #define JOBDONE         2       /* all procs are completed */
3405         unsigned
3406                 state: 8,
3407 #if JOBS
3408                 sigint: 1,      /* job was killed by SIGINT */
3409                 jobctl: 1,      /* job running under job control */
3410 #endif
3411                 waited: 1,      /* true if this entry has been waited for */
3412                 used: 1,        /* true if this entry is in used */
3413                 changed: 1;     /* true if status has changed */
3414         struct job *prev_job;   /* previous job */
3415 };
3416
3417 static struct job *makejob(/*union node *,*/ int);
3418 static int forkshell(struct job *, union node *, int);
3419 static int waitforjob(struct job *);
3420
3421 #if !JOBS
3422 enum { doing_jobctl = 0 };
3423 #define setjobctl(on) do {} while (0)
3424 #else
3425 static smallint doing_jobctl; //references:8
3426 static void setjobctl(int);
3427 #endif
3428
3429 /*
3430  * Ignore a signal.
3431  */
3432 static void
3433 ignoresig(int signo)
3434 {
3435         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3436         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3437                 /* No, need to do it */
3438                 signal(signo, SIG_IGN);
3439         }
3440         sigmode[signo - 1] = S_HARD_IGN;
3441 }
3442
3443 /*
3444  * Only one usage site - in setsignal()
3445  */
3446 static void
3447 signal_handler(int signo)
3448 {
3449         if (signo == SIGCHLD) {
3450                 got_sigchld = 1;
3451                 if (!trap[SIGCHLD])
3452                         return;
3453         }
3454
3455         gotsig[signo - 1] = 1;
3456         pending_sig = signo;
3457
3458         if (signo == SIGINT && !trap[SIGINT]) {
3459                 if (!suppress_int) {
3460                         pending_sig = 0;
3461                         raise_interrupt(); /* does not return */
3462                 }
3463                 pending_int = 1;
3464         }
3465 }
3466
3467 /*
3468  * Set the signal handler for the specified signal.  The routine figures
3469  * out what it should be set to.
3470  */
3471 static void
3472 setsignal(int signo)
3473 {
3474         char *t;
3475         char cur_act, new_act;
3476         struct sigaction act;
3477
3478         t = trap[signo];
3479         new_act = S_DFL;
3480         if (t != NULL) { /* trap for this sig is set */
3481                 new_act = S_CATCH;
3482                 if (t[0] == '\0') /* trap is "": ignore this sig */
3483                         new_act = S_IGN;
3484         }
3485
3486         if (rootshell && new_act == S_DFL) {
3487                 switch (signo) {
3488                 case SIGINT:
3489                         if (iflag || minusc || sflag == 0)
3490                                 new_act = S_CATCH;
3491                         break;
3492                 case SIGQUIT:
3493 #if DEBUG
3494                         if (debug)
3495                                 break;
3496 #endif
3497                         /* man bash:
3498                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3499                          * commands run by bash have signal handlers
3500                          * set to the values inherited by the shell
3501                          * from its parent". */
3502                         new_act = S_IGN;
3503                         break;
3504                 case SIGTERM:
3505                         if (iflag)
3506                                 new_act = S_IGN;
3507                         break;
3508 #if JOBS
3509                 case SIGTSTP:
3510                 case SIGTTOU:
3511                         if (mflag)
3512                                 new_act = S_IGN;
3513                         break;
3514 #endif
3515                 }
3516         }
3517 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3518 //whereas we have to restore it to what shell got on entry
3519 //from the parent. See comment above
3520
3521         if (signo == SIGCHLD)
3522                 new_act = S_CATCH;
3523
3524         t = &sigmode[signo - 1];
3525         cur_act = *t;
3526         if (cur_act == 0) {
3527                 /* current setting is not yet known */
3528                 if (sigaction(signo, NULL, &act)) {
3529                         /* pretend it worked; maybe we should give a warning,
3530                          * but other shells don't. We don't alter sigmode,
3531                          * so we retry every time.
3532                          * btw, in Linux it never fails. --vda */
3533                         return;
3534                 }
3535                 if (act.sa_handler == SIG_IGN) {
3536                         cur_act = S_HARD_IGN;
3537                         if (mflag
3538                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3539                         ) {
3540                                 cur_act = S_IGN;   /* don't hard ignore these */
3541                         }
3542                 }
3543         }
3544         if (cur_act == S_HARD_IGN || cur_act == new_act)
3545                 return;
3546
3547         act.sa_handler = SIG_DFL;
3548         switch (new_act) {
3549         case S_CATCH:
3550                 act.sa_handler = signal_handler;
3551                 break;
3552         case S_IGN:
3553                 act.sa_handler = SIG_IGN;
3554                 break;
3555         }
3556
3557         /* flags and mask matter only if !DFL and !IGN, but we do it
3558          * for all cases for more deterministic behavior:
3559          */
3560         act.sa_flags = 0;
3561         sigfillset(&act.sa_mask);
3562
3563         sigaction_set(signo, &act);
3564
3565         *t = new_act;
3566 }
3567
3568 /* mode flags for set_curjob */
3569 #define CUR_DELETE 2
3570 #define CUR_RUNNING 1
3571 #define CUR_STOPPED 0
3572
3573 #if JOBS
3574 /* pgrp of shell on invocation */
3575 static int initialpgrp; //references:2
3576 static int ttyfd = -1; //5
3577 #endif
3578 /* array of jobs */
3579 static struct job *jobtab; //5
3580 /* size of array */
3581 static unsigned njobs; //4
3582 /* current job */
3583 static struct job *curjob; //lots
3584 /* number of presumed living untracked jobs */
3585 static int jobless; //4
3586
3587 #if 0
3588 /* Bash has a feature: it restores termios after a successful wait for
3589  * a foreground job which had at least one stopped or sigkilled member.
3590  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3591  * properly restoring tty state. Should we do this too?
3592  * A reproducer: ^Z an interactive python:
3593  *
3594  * # python
3595  * Python 2.7.12 (...)
3596  * >>> ^Z
3597  *      { python leaves tty in -icanon -echo state. We do survive that... }
3598  *  [1]+  Stopped                    python
3599  *      { ...however, next program (python #2) does not survive it well: }
3600  * # python
3601  * Python 2.7.12 (...)
3602  * >>> Traceback (most recent call last):
3603  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3604  *   File "<stdin>", line 1, in <module>
3605  * NameError: name 'qwerty' is not defined
3606  *
3607  * The implementation below is modeled on bash code and seems to work.
3608  * However, I'm not sure we should do this. For one: what if I'd fg
3609  * the stopped python instead? It'll be confused by "restored" tty state.
3610  */
3611 static struct termios shell_tty_info;
3612 static void
3613 get_tty_state(void)
3614 {
3615         if (rootshell && ttyfd >= 0)
3616                 tcgetattr(ttyfd, &shell_tty_info);
3617 }
3618 static void
3619 set_tty_state(void)
3620 {
3621         /* if (rootshell) - caller ensures this */
3622         if (ttyfd >= 0)
3623                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3624 }
3625 static int
3626 job_signal_status(struct job *jp)
3627 {
3628         int status;
3629         unsigned i;
3630         struct procstat *ps = jp->ps;
3631         for (i = 0; i < jp->nprocs; i++) {
3632                 status = ps[i].ps_status;
3633                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3634                         return status;
3635         }
3636         return 0;
3637 }
3638 static void
3639 restore_tty_if_stopped_or_signaled(struct job *jp)
3640 {
3641 //TODO: check what happens if we come from waitforjob() in expbackq()
3642         if (rootshell) {
3643                 int s = job_signal_status(jp);
3644                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3645                         set_tty_state();
3646         }
3647 }
3648 #else
3649 # define get_tty_state() ((void)0)
3650 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3651 #endif
3652
3653 static void
3654 set_curjob(struct job *jp, unsigned mode)
3655 {
3656         struct job *jp1;
3657         struct job **jpp, **curp;
3658
3659         /* first remove from list */
3660         jpp = curp = &curjob;
3661         while (1) {
3662                 jp1 = *jpp;
3663                 if (jp1 == jp)
3664                         break;
3665                 jpp = &jp1->prev_job;
3666         }
3667         *jpp = jp1->prev_job;
3668
3669         /* Then re-insert in correct position */
3670         jpp = curp;
3671         switch (mode) {
3672         default:
3673 #if DEBUG
3674                 abort();
3675 #endif
3676         case CUR_DELETE:
3677                 /* job being deleted */
3678                 break;
3679         case CUR_RUNNING:
3680                 /* newly created job or backgrounded job,
3681                  * put after all stopped jobs.
3682                  */
3683                 while (1) {
3684                         jp1 = *jpp;
3685 #if JOBS
3686                         if (!jp1 || jp1->state != JOBSTOPPED)
3687 #endif
3688                                 break;
3689                         jpp = &jp1->prev_job;
3690                 }
3691                 /* FALLTHROUGH */
3692 #if JOBS
3693         case CUR_STOPPED:
3694 #endif
3695                 /* newly stopped job - becomes curjob */
3696                 jp->prev_job = *jpp;
3697                 *jpp = jp;
3698                 break;
3699         }
3700 }
3701
3702 #if JOBS || DEBUG
3703 static int
3704 jobno(const struct job *jp)
3705 {
3706         return jp - jobtab + 1;
3707 }
3708 #endif
3709
3710 /*
3711  * Convert a job name to a job structure.
3712  */
3713 #if !JOBS
3714 #define getjob(name, getctl) getjob(name)
3715 #endif
3716 static struct job *
3717 getjob(const char *name, int getctl)
3718 {
3719         struct job *jp;
3720         struct job *found;
3721         const char *err_msg = "%s: no such job";
3722         unsigned num;
3723         int c;
3724         const char *p;
3725         char *(*match)(const char *, const char *);
3726
3727         jp = curjob;
3728         p = name;
3729         if (!p)
3730                 goto currentjob;
3731
3732         if (*p != '%')
3733                 goto err;
3734
3735         c = *++p;
3736         if (!c)
3737                 goto currentjob;
3738
3739         if (!p[1]) {
3740                 if (c == '+' || c == '%') {
3741  currentjob:
3742                         err_msg = "No current job";
3743                         goto check;
3744                 }
3745                 if (c == '-') {
3746                         if (jp)
3747                                 jp = jp->prev_job;
3748                         err_msg = "No previous job";
3749  check:
3750                         if (!jp)
3751                                 goto err;
3752                         goto gotit;
3753                 }
3754         }
3755
3756         if (is_number(p)) {
3757                 num = atoi(p);
3758                 if (num > 0 && num <= njobs) {
3759                         jp = jobtab + num - 1;
3760                         if (jp->used)
3761                                 goto gotit;
3762                         goto err;
3763                 }
3764         }
3765
3766         match = prefix;
3767         if (*p == '?') {
3768                 match = strstr;
3769                 p++;
3770         }
3771
3772         found = NULL;
3773         while (jp) {
3774                 if (match(jp->ps[0].ps_cmd, p)) {
3775                         if (found)
3776                                 goto err;
3777                         found = jp;
3778                         err_msg = "%s: ambiguous";
3779                 }
3780                 jp = jp->prev_job;
3781         }
3782         if (!found)
3783                 goto err;
3784         jp = found;
3785
3786  gotit:
3787 #if JOBS
3788         err_msg = "job %s not created under job control";
3789         if (getctl && jp->jobctl == 0)
3790                 goto err;
3791 #endif
3792         return jp;
3793  err:
3794         ash_msg_and_raise_error(err_msg, name);
3795 }
3796
3797 /*
3798  * Mark a job structure as unused.
3799  */
3800 static void
3801 freejob(struct job *jp)
3802 {
3803         struct procstat *ps;
3804         int i;
3805
3806         INT_OFF;
3807         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3808                 if (ps->ps_cmd != nullstr)
3809                         free(ps->ps_cmd);
3810         }
3811         if (jp->ps != &jp->ps0)
3812                 free(jp->ps);
3813         jp->used = 0;
3814         set_curjob(jp, CUR_DELETE);
3815         INT_ON;
3816 }
3817
3818 #if JOBS
3819 static void
3820 xtcsetpgrp(int fd, pid_t pgrp)
3821 {
3822         if (tcsetpgrp(fd, pgrp))
3823                 ash_msg_and_raise_error("can't set tty process group (%m)");
3824 }
3825
3826 /*
3827  * Turn job control on and off.
3828  *
3829  * Note:  This code assumes that the third arg to ioctl is a character
3830  * pointer, which is true on Berkeley systems but not System V.  Since
3831  * System V doesn't have job control yet, this isn't a problem now.
3832  *
3833  * Called with interrupts off.
3834  */
3835 static void
3836 setjobctl(int on)
3837 {
3838         int fd;
3839         int pgrp;
3840
3841         if (on == doing_jobctl || rootshell == 0)
3842                 return;
3843         if (on) {
3844                 int ofd;
3845                 ofd = fd = open(_PATH_TTY, O_RDWR);
3846                 if (fd < 0) {
3847         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3848          * That sometimes helps to acquire controlling tty.
3849          * Obviously, a workaround for bugs when someone
3850          * failed to provide a controlling tty to bash! :) */
3851                         fd = 2;
3852                         while (!isatty(fd))
3853                                 if (--fd < 0)
3854                                         goto out;
3855                 }
3856                 /* fd is a tty at this point */
3857                 fd = fcntl(fd, F_DUPFD, 10);
3858                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3859                         close(ofd);
3860                 if (fd < 0)
3861                         goto out; /* F_DUPFD failed */
3862                 close_on_exec_on(fd);
3863                 while (1) { /* while we are in the background */
3864                         pgrp = tcgetpgrp(fd);
3865                         if (pgrp < 0) {
3866  out:
3867                                 ash_msg("can't access tty; job control turned off");
3868                                 mflag = on = 0;
3869                                 goto close;
3870                         }
3871                         if (pgrp == getpgrp())
3872                                 break;
3873                         killpg(0, SIGTTIN);
3874                 }
3875                 initialpgrp = pgrp;
3876
3877                 setsignal(SIGTSTP);
3878                 setsignal(SIGTTOU);
3879                 setsignal(SIGTTIN);
3880                 pgrp = rootpid;
3881                 setpgid(0, pgrp);
3882                 xtcsetpgrp(fd, pgrp);
3883         } else {
3884                 /* turning job control off */
3885                 fd = ttyfd;
3886                 pgrp = initialpgrp;
3887                 /* was xtcsetpgrp, but this can make exiting ash
3888                  * loop forever if pty is already deleted */
3889                 tcsetpgrp(fd, pgrp);
3890                 setpgid(0, pgrp);
3891                 setsignal(SIGTSTP);
3892                 setsignal(SIGTTOU);
3893                 setsignal(SIGTTIN);
3894  close:
3895                 if (fd >= 0)
3896                         close(fd);
3897                 fd = -1;
3898         }
3899         ttyfd = fd;
3900         doing_jobctl = on;
3901 }
3902
3903 static int FAST_FUNC
3904 killcmd(int argc, char **argv)
3905 {
3906         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3907                 int i = 1;
3908                 do {
3909                         if (argv[i][0] == '%') {
3910                                 /*
3911                                  * "kill %N" - job kill
3912                                  * Converting to pgrp / pid kill
3913                                  */
3914                                 struct job *jp;
3915                                 char *dst;
3916                                 int j, n;
3917
3918                                 jp = getjob(argv[i], 0);
3919                                 /*
3920                                  * In jobs started under job control, we signal
3921                                  * entire process group by kill -PGRP_ID.
3922                                  * This happens, f.e., in interactive shell.
3923                                  *
3924                                  * Otherwise, we signal each child via
3925                                  * kill PID1 PID2 PID3.
3926                                  * Testcases:
3927                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3928                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3929                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3930                                  */
3931                                 n = jp->nprocs; /* can't be 0 (I hope) */
3932                                 if (jp->jobctl)
3933                                         n = 1;
3934                                 dst = alloca(n * sizeof(int)*4);
3935                                 argv[i] = dst;
3936                                 for (j = 0; j < n; j++) {
3937                                         struct procstat *ps = &jp->ps[j];
3938                                         /* Skip non-running and not-stopped members
3939                                          * (i.e. dead members) of the job
3940                                          */
3941                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3942                                                 continue;
3943                                         /*
3944                                          * kill_main has matching code to expect
3945                                          * leading space. Needed to not confuse
3946                                          * negative pids with "kill -SIGNAL_NO" syntax
3947                                          */
3948                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3949                                 }
3950                                 *dst = '\0';
3951                         }
3952                 } while (argv[++i]);
3953         }
3954         return kill_main(argc, argv);
3955 }
3956
3957 static void
3958 showpipe(struct job *jp /*, FILE *out*/)
3959 {
3960         struct procstat *ps;
3961         struct procstat *psend;
3962
3963         psend = jp->ps + jp->nprocs;
3964         for (ps = jp->ps + 1; ps < psend; ps++)
3965                 printf(" | %s", ps->ps_cmd);
3966         newline_and_flush(stdout);
3967         flush_stdout_stderr();
3968 }
3969
3970
3971 static int
3972 restartjob(struct job *jp, int mode)
3973 {
3974         struct procstat *ps;
3975         int i;
3976         int status;
3977         pid_t pgid;
3978
3979         INT_OFF;
3980         if (jp->state == JOBDONE)
3981                 goto out;
3982         jp->state = JOBRUNNING;
3983         pgid = jp->ps[0].ps_pid;
3984         if (mode == FORK_FG) {
3985                 get_tty_state();
3986                 xtcsetpgrp(ttyfd, pgid);
3987         }
3988         killpg(pgid, SIGCONT);
3989         ps = jp->ps;
3990         i = jp->nprocs;
3991         do {
3992                 if (WIFSTOPPED(ps->ps_status)) {
3993                         ps->ps_status = -1;
3994                 }
3995                 ps++;
3996         } while (--i);
3997  out:
3998         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3999         INT_ON;
4000         return status;
4001 }
4002
4003 static int FAST_FUNC
4004 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4005 {
4006         struct job *jp;
4007         int mode;
4008         int retval;
4009
4010         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4011         nextopt(nullstr);
4012         argv = argptr;
4013         do {
4014                 jp = getjob(*argv, 1);
4015                 if (mode == FORK_BG) {
4016                         set_curjob(jp, CUR_RUNNING);
4017                         printf("[%d] ", jobno(jp));
4018                 }
4019                 out1str(jp->ps[0].ps_cmd);
4020                 showpipe(jp /*, stdout*/);
4021                 retval = restartjob(jp, mode);
4022         } while (*argv && *++argv);
4023         return retval;
4024 }
4025 #endif
4026
4027 static int
4028 sprint_status48(char *s, int status, int sigonly)
4029 {
4030         int col;
4031         int st;
4032
4033         col = 0;
4034         if (!WIFEXITED(status)) {
4035 #if JOBS
4036                 if (WIFSTOPPED(status))
4037                         st = WSTOPSIG(status);
4038                 else
4039 #endif
4040                         st = WTERMSIG(status);
4041                 if (sigonly) {
4042                         if (st == SIGINT || st == SIGPIPE)
4043                                 goto out;
4044 #if JOBS
4045                         if (WIFSTOPPED(status))
4046                                 goto out;
4047 #endif
4048                 }
4049                 st &= 0x7f;
4050 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4051                 col = fmtstr(s, 32, strsignal(st));
4052                 if (WCOREDUMP(status)) {
4053                         strcpy(s + col, " (core dumped)");
4054                         col += sizeof(" (core dumped)")-1;
4055                 }
4056         } else if (!sigonly) {
4057                 st = WEXITSTATUS(status);
4058                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4059         }
4060  out:
4061         return col;
4062 }
4063
4064 static int
4065 wait_block_or_sig(int *status)
4066 {
4067         int pid;
4068
4069         do {
4070                 sigset_t mask;
4071
4072                 /* Poll all children for changes in their state */
4073                 got_sigchld = 0;
4074                 /* if job control is active, accept stopped processes too */
4075                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4076                 if (pid != 0)
4077                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4078
4079                 /* Children exist, but none are ready. Sleep until interesting signal */
4080 #if 1
4081                 sigfillset(&mask);
4082                 sigprocmask(SIG_SETMASK, &mask, &mask);
4083                 while (!got_sigchld && !pending_sig)
4084                         sigsuspend(&mask);
4085                 sigprocmask(SIG_SETMASK, &mask, NULL);
4086 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4087                 while (!got_sigchld && !pending_sig)
4088                         pause();
4089 #endif
4090
4091                 /* If it was SIGCHLD, poll children again */
4092         } while (got_sigchld);
4093
4094         return pid;
4095 }
4096
4097 #define DOWAIT_NONBLOCK 0
4098 #define DOWAIT_BLOCK    1
4099 #define DOWAIT_BLOCK_OR_SIG 2
4100
4101 static int
4102 dowait(int block, struct job *job)
4103 {
4104         int pid;
4105         int status;
4106         struct job *jp;
4107         struct job *thisjob = NULL;
4108
4109         TRACE(("dowait(0x%x) called\n", block));
4110
4111         /* It's wrong to call waitpid() outside of INT_OFF region:
4112          * signal can arrive just after syscall return and handler can
4113          * longjmp away, losing stop/exit notification processing.
4114          * Thus, for "jobs" builtin, and for waiting for a fg job,
4115          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4116          *
4117          * However, for "wait" builtin it is wrong to simply call waitpid()
4118          * in INT_OFF region: "wait" needs to wait for any running job
4119          * to change state, but should exit on any trap too.
4120          * In INT_OFF region, a signal just before syscall entry can set
4121          * pending_sig variables, but we can't check them, and we would
4122          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4123          *
4124          * Because of this, we run inside INT_OFF, but use a special routine
4125          * which combines waitpid() and sigsuspend().
4126          * This is the reason why we need to have a handler for SIGCHLD:
4127          * SIG_DFL handler does not wake sigsuspend().
4128          */
4129         INT_OFF;
4130         if (block == DOWAIT_BLOCK_OR_SIG) {
4131                 pid = wait_block_or_sig(&status);
4132         } else {
4133                 int wait_flags = 0;
4134                 if (block == DOWAIT_NONBLOCK)
4135                         wait_flags = WNOHANG;
4136                 /* if job control is active, accept stopped processes too */
4137                 if (doing_jobctl)
4138                         wait_flags |= WUNTRACED;
4139                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4140                 pid = waitpid(-1, &status, wait_flags);
4141         }
4142         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4143                                 pid, status, errno, strerror(errno)));
4144         if (pid <= 0)
4145                 goto out;
4146
4147         thisjob = NULL;
4148         for (jp = curjob; jp; jp = jp->prev_job) {
4149                 int jobstate;
4150                 struct procstat *ps;
4151                 struct procstat *psend;
4152                 if (jp->state == JOBDONE)
4153                         continue;
4154                 jobstate = JOBDONE;
4155                 ps = jp->ps;
4156                 psend = ps + jp->nprocs;
4157                 do {
4158                         if (ps->ps_pid == pid) {
4159                                 TRACE(("Job %d: changing status of proc %d "
4160                                         "from 0x%x to 0x%x\n",
4161                                         jobno(jp), pid, ps->ps_status, status));
4162                                 ps->ps_status = status;
4163                                 thisjob = jp;
4164                         }
4165                         if (ps->ps_status == -1)
4166                                 jobstate = JOBRUNNING;
4167 #if JOBS
4168                         if (jobstate == JOBRUNNING)
4169                                 continue;
4170                         if (WIFSTOPPED(ps->ps_status)) {
4171                                 jp->stopstatus = ps->ps_status;
4172                                 jobstate = JOBSTOPPED;
4173                         }
4174 #endif
4175                 } while (++ps < psend);
4176                 if (!thisjob)
4177                         continue;
4178
4179                 /* Found the job where one of its processes changed its state.
4180                  * Is there at least one live and running process in this job? */
4181                 if (jobstate != JOBRUNNING) {
4182                         /* No. All live processes in the job are stopped
4183                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4184                          */
4185                         thisjob->changed = 1;
4186                         if (thisjob->state != jobstate) {
4187                                 TRACE(("Job %d: changing state from %d to %d\n",
4188                                         jobno(thisjob), thisjob->state, jobstate));
4189                                 thisjob->state = jobstate;
4190 #if JOBS
4191                                 if (jobstate == JOBSTOPPED)
4192                                         set_curjob(thisjob, CUR_STOPPED);
4193 #endif
4194                         }
4195                 }
4196                 goto out;
4197         }
4198         /* The process wasn't found in job list */
4199 #if JOBS
4200         if (!WIFSTOPPED(status))
4201                 jobless--;
4202 #endif
4203  out:
4204         INT_ON;
4205
4206         if (thisjob && thisjob == job) {
4207                 char s[48 + 1];
4208                 int len;
4209
4210                 len = sprint_status48(s, status, 1);
4211                 if (len) {
4212                         s[len] = '\n';
4213                         s[len + 1] = '\0';
4214                         out2str(s);
4215                 }
4216         }
4217         return pid;
4218 }
4219
4220 #if JOBS
4221 static void
4222 showjob(struct job *jp, int mode)
4223 {
4224         struct procstat *ps;
4225         struct procstat *psend;
4226         int col;
4227         int indent_col;
4228         char s[16 + 16 + 48];
4229         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4230
4231         ps = jp->ps;
4232
4233         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4234                 /* just output process (group) id of pipeline */
4235                 fprintf(out, "%d\n", ps->ps_pid);
4236                 return;
4237         }
4238
4239         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4240         indent_col = col;
4241
4242         if (jp == curjob)
4243                 s[col - 3] = '+';
4244         else if (curjob && jp == curjob->prev_job)
4245                 s[col - 3] = '-';
4246
4247         if (mode & SHOW_PIDS)
4248                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4249
4250         psend = ps + jp->nprocs;
4251
4252         if (jp->state == JOBRUNNING) {
4253                 strcpy(s + col, "Running");
4254                 col += sizeof("Running") - 1;
4255         } else {
4256                 int status = psend[-1].ps_status;
4257                 if (jp->state == JOBSTOPPED)
4258                         status = jp->stopstatus;
4259                 col += sprint_status48(s + col, status, 0);
4260         }
4261         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4262
4263         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4264          * or prints several "PID             | <cmdN>" lines,
4265          * depending on SHOW_PIDS bit.
4266          * We do not print status of individual processes
4267          * between PID and <cmdN>. bash does it, but not very well:
4268          * first line shows overall job status, not process status,
4269          * making it impossible to know 1st process status.
4270          */
4271         goto start;
4272         do {
4273                 /* for each process */
4274                 s[0] = '\0';
4275                 col = 33;
4276                 if (mode & SHOW_PIDS)
4277                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4278  start:
4279                 fprintf(out, "%s%*c%s%s",
4280                                 s,
4281                                 33 - col >= 0 ? 33 - col : 0, ' ',
4282                                 ps == jp->ps ? "" : "| ",
4283                                 ps->ps_cmd
4284                 );
4285         } while (++ps != psend);
4286         newline_and_flush(out);
4287
4288         jp->changed = 0;
4289
4290         if (jp->state == JOBDONE) {
4291                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4292                 freejob(jp);
4293         }
4294 }
4295
4296 /*
4297  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4298  * statuses have changed since the last call to showjobs.
4299  */
4300 static void
4301 showjobs(int mode)
4302 {
4303         struct job *jp;
4304
4305         TRACE(("showjobs(0x%x) called\n", mode));
4306
4307         /* Handle all finished jobs */
4308         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4309                 continue;
4310
4311         for (jp = curjob; jp; jp = jp->prev_job) {
4312                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4313                         showjob(jp, mode);
4314                 }
4315         }
4316 }
4317
4318 static int FAST_FUNC
4319 jobscmd(int argc UNUSED_PARAM, char **argv)
4320 {
4321         int mode, m;
4322
4323         mode = 0;
4324         while ((m = nextopt("lp")) != '\0') {
4325                 if (m == 'l')
4326                         mode |= SHOW_PIDS;
4327                 else
4328                         mode |= SHOW_ONLY_PGID;
4329         }
4330
4331         argv = argptr;
4332         if (*argv) {
4333                 do
4334                         showjob(getjob(*argv, 0), mode);
4335                 while (*++argv);
4336         } else {
4337                 showjobs(mode);
4338         }
4339
4340         return 0;
4341 }
4342 #endif /* JOBS */
4343
4344 /* Called only on finished or stopped jobs (no members are running) */
4345 static int
4346 getstatus(struct job *job)
4347 {
4348         int status;
4349         int retval;
4350         struct procstat *ps;
4351
4352         /* Fetch last member's status */
4353         ps = job->ps + job->nprocs - 1;
4354         status = ps->ps_status;
4355         if (pipefail) {
4356                 /* "set -o pipefail" mode: use last _nonzero_ status */
4357                 while (status == 0 && --ps >= job->ps)
4358                         status = ps->ps_status;
4359         }
4360
4361         retval = WEXITSTATUS(status);
4362         if (!WIFEXITED(status)) {
4363 #if JOBS
4364                 retval = WSTOPSIG(status);
4365                 if (!WIFSTOPPED(status))
4366 #endif
4367                 {
4368                         /* XXX: limits number of signals */
4369                         retval = WTERMSIG(status);
4370 #if JOBS
4371                         if (retval == SIGINT)
4372                                 job->sigint = 1;
4373 #endif
4374                 }
4375                 retval += 128;
4376         }
4377         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4378                 jobno(job), job->nprocs, status, retval));
4379         return retval;
4380 }
4381
4382 static int FAST_FUNC
4383 waitcmd(int argc UNUSED_PARAM, char **argv)
4384 {
4385         struct job *job;
4386         int retval;
4387         struct job *jp;
4388
4389         nextopt(nullstr);
4390         retval = 0;
4391
4392         argv = argptr;
4393         if (!*argv) {
4394                 /* wait for all jobs */
4395                 for (;;) {
4396                         jp = curjob;
4397                         while (1) {
4398                                 if (!jp) /* no running procs */
4399                                         goto ret;
4400                                 if (jp->state == JOBRUNNING)
4401                                         break;
4402                                 jp->waited = 1;
4403                                 jp = jp->prev_job;
4404                         }
4405         /* man bash:
4406          * "When bash is waiting for an asynchronous command via
4407          * the wait builtin, the reception of a signal for which a trap
4408          * has been set will cause the wait builtin to return immediately
4409          * with an exit status greater than 128, immediately after which
4410          * the trap is executed."
4411          */
4412                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4413         /* if child sends us a signal *and immediately exits*,
4414          * dowait() returns pid > 0. Check this case,
4415          * not "if (dowait() < 0)"!
4416          */
4417                         if (pending_sig)
4418                                 goto sigout;
4419                 }
4420         }
4421
4422         retval = 127;
4423         do {
4424                 if (**argv != '%') {
4425                         pid_t pid = number(*argv);
4426                         job = curjob;
4427                         while (1) {
4428                                 if (!job)
4429                                         goto repeat;
4430                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4431                                         break;
4432                                 job = job->prev_job;
4433                         }
4434                 } else {
4435                         job = getjob(*argv, 0);
4436                 }
4437                 /* loop until process terminated or stopped */
4438                 while (job->state == JOBRUNNING) {
4439                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4440                         if (pending_sig)
4441                                 goto sigout;
4442                 }
4443                 job->waited = 1;
4444                 retval = getstatus(job);
4445  repeat: ;
4446         } while (*++argv);
4447
4448  ret:
4449         return retval;
4450  sigout:
4451         retval = 128 + pending_sig;
4452         return retval;
4453 }
4454
4455 static struct job *
4456 growjobtab(void)
4457 {
4458         size_t len;
4459         ptrdiff_t offset;
4460         struct job *jp, *jq;
4461
4462         len = njobs * sizeof(*jp);
4463         jq = jobtab;
4464         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4465
4466         offset = (char *)jp - (char *)jq;
4467         if (offset) {
4468                 /* Relocate pointers */
4469                 size_t l = len;
4470
4471                 jq = (struct job *)((char *)jq + l);
4472                 while (l) {
4473                         l -= sizeof(*jp);
4474                         jq--;
4475 #define joff(p) ((struct job *)((char *)(p) + l))
4476 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4477                         if (joff(jp)->ps == &jq->ps0)
4478                                 jmove(joff(jp)->ps);
4479                         if (joff(jp)->prev_job)
4480                                 jmove(joff(jp)->prev_job);
4481                 }
4482                 if (curjob)
4483                         jmove(curjob);
4484 #undef joff
4485 #undef jmove
4486         }
4487
4488         njobs += 4;
4489         jobtab = jp;
4490         jp = (struct job *)((char *)jp + len);
4491         jq = jp + 3;
4492         do {
4493                 jq->used = 0;
4494         } while (--jq >= jp);
4495         return jp;
4496 }
4497
4498 /*
4499  * Return a new job structure.
4500  * Called with interrupts off.
4501  */
4502 static struct job *
4503 makejob(/*union node *node,*/ int nprocs)
4504 {
4505         int i;
4506         struct job *jp;
4507
4508         for (i = njobs, jp = jobtab; ; jp++) {
4509                 if (--i < 0) {
4510                         jp = growjobtab();
4511                         break;
4512                 }
4513                 if (jp->used == 0)
4514                         break;
4515                 if (jp->state != JOBDONE || !jp->waited)
4516                         continue;
4517 #if JOBS
4518                 if (doing_jobctl)
4519                         continue;
4520 #endif
4521                 freejob(jp);
4522                 break;
4523         }
4524         memset(jp, 0, sizeof(*jp));
4525 #if JOBS
4526         /* jp->jobctl is a bitfield.
4527          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4528         if (doing_jobctl)
4529                 jp->jobctl = 1;
4530 #endif
4531         jp->prev_job = curjob;
4532         curjob = jp;
4533         jp->used = 1;
4534         jp->ps = &jp->ps0;
4535         if (nprocs > 1) {
4536                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4537         }
4538         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4539                                 jobno(jp)));
4540         return jp;
4541 }
4542
4543 #if JOBS
4544 /*
4545  * Return a string identifying a command (to be printed by the
4546  * jobs command).
4547  */
4548 static char *cmdnextc;
4549
4550 static void
4551 cmdputs(const char *s)
4552 {
4553         static const char vstype[VSTYPE + 1][3] = {
4554                 "", "}", "-", "+", "?", "=",
4555                 "%", "%%", "#", "##"
4556                 IF_BASH_SUBSTR(, ":")
4557                 IF_BASH_PATTERN_SUBST(, "/", "//")
4558         };
4559
4560         const char *p, *str;
4561         char cc[2];
4562         char *nextc;
4563         unsigned char c;
4564         unsigned char subtype = 0;
4565         int quoted = 0;
4566
4567         cc[1] = '\0';
4568         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4569         p = s;
4570         while ((c = *p++) != '\0') {
4571                 str = NULL;
4572                 switch (c) {
4573                 case CTLESC:
4574                         c = *p++;
4575                         break;
4576                 case CTLVAR:
4577                         subtype = *p++;
4578                         if ((subtype & VSTYPE) == VSLENGTH)
4579                                 str = "${#";
4580                         else
4581                                 str = "${";
4582                         goto dostr;
4583                 case CTLENDVAR:
4584                         str = "\"}" + !(quoted & 1);
4585                         quoted >>= 1;
4586                         subtype = 0;
4587                         goto dostr;
4588                 case CTLBACKQ:
4589                         str = "$(...)";
4590                         goto dostr;
4591 #if ENABLE_FEATURE_SH_MATH
4592                 case CTLARI:
4593                         str = "$((";
4594                         goto dostr;
4595                 case CTLENDARI:
4596                         str = "))";
4597                         goto dostr;
4598 #endif
4599                 case CTLQUOTEMARK:
4600                         quoted ^= 1;
4601                         c = '"';
4602                         break;
4603                 case '=':
4604                         if (subtype == 0)
4605                                 break;
4606                         if ((subtype & VSTYPE) != VSNORMAL)
4607                                 quoted <<= 1;
4608                         str = vstype[subtype & VSTYPE];
4609                         if (subtype & VSNUL)
4610                                 c = ':';
4611                         else
4612                                 goto checkstr;
4613                         break;
4614                 case '\'':
4615                 case '\\':
4616                 case '"':
4617                 case '$':
4618                         /* These can only happen inside quotes */
4619                         cc[0] = c;
4620                         str = cc;
4621                         c = '\\';
4622                         break;
4623                 default:
4624                         break;
4625                 }
4626                 USTPUTC(c, nextc);
4627  checkstr:
4628                 if (!str)
4629                         continue;
4630  dostr:
4631                 while ((c = *str++) != '\0') {
4632                         USTPUTC(c, nextc);
4633                 }
4634         } /* while *p++ not NUL */
4635
4636         if (quoted & 1) {
4637                 USTPUTC('"', nextc);
4638         }
4639         *nextc = 0;
4640         cmdnextc = nextc;
4641 }
4642
4643 /* cmdtxt() and cmdlist() call each other */
4644 static void cmdtxt(union node *n);
4645
4646 static void
4647 cmdlist(union node *np, int sep)
4648 {
4649         for (; np; np = np->narg.next) {
4650                 if (!sep)
4651                         cmdputs(" ");
4652                 cmdtxt(np);
4653                 if (sep && np->narg.next)
4654                         cmdputs(" ");
4655         }
4656 }
4657
4658 static void
4659 cmdtxt(union node *n)
4660 {
4661         union node *np;
4662         struct nodelist *lp;
4663         const char *p;
4664
4665         if (!n)
4666                 return;
4667         switch (n->type) {
4668         default:
4669 #if DEBUG
4670                 abort();
4671 #endif
4672         case NPIPE:
4673                 lp = n->npipe.cmdlist;
4674                 for (;;) {
4675                         cmdtxt(lp->n);
4676                         lp = lp->next;
4677                         if (!lp)
4678                                 break;
4679                         cmdputs(" | ");
4680                 }
4681                 break;
4682         case NSEMI:
4683                 p = "; ";
4684                 goto binop;
4685         case NAND:
4686                 p = " && ";
4687                 goto binop;
4688         case NOR:
4689                 p = " || ";
4690  binop:
4691                 cmdtxt(n->nbinary.ch1);
4692                 cmdputs(p);
4693                 n = n->nbinary.ch2;
4694                 goto donode;
4695         case NREDIR:
4696         case NBACKGND:
4697                 n = n->nredir.n;
4698                 goto donode;
4699         case NNOT:
4700                 cmdputs("!");
4701                 n = n->nnot.com;
4702  donode:
4703                 cmdtxt(n);
4704                 break;
4705         case NIF:
4706                 cmdputs("if ");
4707                 cmdtxt(n->nif.test);
4708                 cmdputs("; then ");
4709                 if (n->nif.elsepart) {
4710                         cmdtxt(n->nif.ifpart);
4711                         cmdputs("; else ");
4712                         n = n->nif.elsepart;
4713                 } else {
4714                         n = n->nif.ifpart;
4715                 }
4716                 p = "; fi";
4717                 goto dotail;
4718         case NSUBSHELL:
4719                 cmdputs("(");
4720                 n = n->nredir.n;
4721                 p = ")";
4722                 goto dotail;
4723         case NWHILE:
4724                 p = "while ";
4725                 goto until;
4726         case NUNTIL:
4727                 p = "until ";
4728  until:
4729                 cmdputs(p);
4730                 cmdtxt(n->nbinary.ch1);
4731                 n = n->nbinary.ch2;
4732                 p = "; done";
4733  dodo:
4734                 cmdputs("; do ");
4735  dotail:
4736                 cmdtxt(n);
4737                 goto dotail2;
4738         case NFOR:
4739                 cmdputs("for ");
4740                 cmdputs(n->nfor.var);
4741                 cmdputs(" in ");
4742                 cmdlist(n->nfor.args, 1);
4743                 n = n->nfor.body;
4744                 p = "; done";
4745                 goto dodo;
4746         case NDEFUN:
4747                 cmdputs(n->narg.text);
4748                 p = "() { ... }";
4749                 goto dotail2;
4750         case NCMD:
4751                 cmdlist(n->ncmd.args, 1);
4752                 cmdlist(n->ncmd.redirect, 0);
4753                 break;
4754         case NARG:
4755                 p = n->narg.text;
4756  dotail2:
4757                 cmdputs(p);
4758                 break;
4759         case NHERE:
4760         case NXHERE:
4761                 p = "<<...";
4762                 goto dotail2;
4763         case NCASE:
4764                 cmdputs("case ");
4765                 cmdputs(n->ncase.expr->narg.text);
4766                 cmdputs(" in ");
4767                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4768                         cmdtxt(np->nclist.pattern);
4769                         cmdputs(") ");
4770                         cmdtxt(np->nclist.body);
4771                         cmdputs(";; ");
4772                 }
4773                 p = "esac";
4774                 goto dotail2;
4775         case NTO:
4776                 p = ">";
4777                 goto redir;
4778         case NCLOBBER:
4779                 p = ">|";
4780                 goto redir;
4781         case NAPPEND:
4782                 p = ">>";
4783                 goto redir;
4784 #if BASH_REDIR_OUTPUT
4785         case NTO2:
4786 #endif
4787         case NTOFD:
4788                 p = ">&";
4789                 goto redir;
4790         case NFROM:
4791                 p = "<";
4792                 goto redir;
4793         case NFROMFD:
4794                 p = "<&";
4795                 goto redir;
4796         case NFROMTO:
4797                 p = "<>";
4798  redir:
4799                 cmdputs(utoa(n->nfile.fd));
4800                 cmdputs(p);
4801                 if (n->type == NTOFD || n->type == NFROMFD) {
4802                         cmdputs(utoa(n->ndup.dupfd));
4803                         break;
4804                 }
4805                 n = n->nfile.fname;
4806                 goto donode;
4807         }
4808 }
4809
4810 static char *
4811 commandtext(union node *n)
4812 {
4813         char *name;
4814
4815         STARTSTACKSTR(cmdnextc);
4816         cmdtxt(n);
4817         name = stackblock();
4818         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4819         return ckstrdup(name);
4820 }
4821 #endif /* JOBS */
4822
4823 /*
4824  * Fork off a subshell.  If we are doing job control, give the subshell its
4825  * own process group.  Jp is a job structure that the job is to be added to.
4826  * N is the command that will be evaluated by the child.  Both jp and n may
4827  * be NULL.  The mode parameter can be one of the following:
4828  *      FORK_FG - Fork off a foreground process.
4829  *      FORK_BG - Fork off a background process.
4830  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4831  *                   process group even if job control is on.
4832  *
4833  * When job control is turned off, background processes have their standard
4834  * input redirected to /dev/null (except for the second and later processes
4835  * in a pipeline).
4836  *
4837  * Called with interrupts off.
4838  */
4839 /*
4840  * Clear traps on a fork.
4841  */
4842 static void
4843 clear_traps(void)
4844 {
4845         char **tp;
4846
4847         INT_OFF;
4848         for (tp = trap; tp < &trap[NSIG]; tp++) {
4849                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4850                         if (trap_ptr == trap)
4851                                 free(*tp);
4852                         /* else: it "belongs" to trap_ptr vector, don't free */
4853                         *tp = NULL;
4854                         if ((tp - trap) != 0)
4855                                 setsignal(tp - trap);
4856                 }
4857         }
4858         may_have_traps = 0;
4859         INT_ON;
4860 }
4861
4862 /* Lives far away from here, needed for forkchild */
4863 static void closescript(void);
4864
4865 /* Called after fork(), in child */
4866 /* jp and n are NULL when called by openhere() for heredoc support */
4867 static NOINLINE void
4868 forkchild(struct job *jp, union node *n, int mode)
4869 {
4870         int oldlvl;
4871
4872         TRACE(("Child shell %d\n", getpid()));
4873         oldlvl = shlvl;
4874         shlvl++;
4875
4876         /* man bash: "Non-builtin commands run by bash have signal handlers
4877          * set to the values inherited by the shell from its parent".
4878          * Do we do it correctly? */
4879
4880         closescript();
4881
4882         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4883          && n && n->type == NCMD        /* is it single cmd? */
4884         /* && n->ncmd.args->type == NARG - always true? */
4885          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4886          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4887         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4888         ) {
4889                 TRACE(("Trap hack\n"));
4890                 /* Awful hack for `trap` or $(trap).
4891                  *
4892                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4893                  * contains an example where "trap" is executed in a subshell:
4894                  *
4895                  * save_traps=$(trap)
4896                  * ...
4897                  * eval "$save_traps"
4898                  *
4899                  * Standard does not say that "trap" in subshell shall print
4900                  * parent shell's traps. It only says that its output
4901                  * must have suitable form, but then, in the above example
4902                  * (which is not supposed to be normative), it implies that.
4903                  *
4904                  * bash (and probably other shell) does implement it
4905                  * (traps are reset to defaults, but "trap" still shows them),
4906                  * but as a result, "trap" logic is hopelessly messed up:
4907                  *
4908                  * # trap
4909                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4910                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4911                  * # true | trap   <--- trap is in subshell - no output (ditto)
4912                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4913                  * trap -- 'echo Ho' SIGWINCH
4914                  * # echo `(trap)`         <--- in subshell in subshell - output
4915                  * trap -- 'echo Ho' SIGWINCH
4916                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4917                  * trap -- 'echo Ho' SIGWINCH
4918                  *
4919                  * The rules when to forget and when to not forget traps
4920                  * get really complex and nonsensical.
4921                  *
4922                  * Our solution: ONLY bare $(trap) or `trap` is special.
4923                  */
4924                 /* Save trap handler strings for trap builtin to print */
4925                 trap_ptr = xmemdup(trap, sizeof(trap));
4926                 /* Fall through into clearing traps */
4927         }
4928         clear_traps();
4929 #if JOBS
4930         /* do job control only in root shell */
4931         doing_jobctl = 0;
4932         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4933                 pid_t pgrp;
4934
4935                 if (jp->nprocs == 0)
4936                         pgrp = getpid();
4937                 else
4938                         pgrp = jp->ps[0].ps_pid;
4939                 /* this can fail because we are doing it in the parent also */
4940                 setpgid(0, pgrp);
4941                 if (mode == FORK_FG)
4942                         xtcsetpgrp(ttyfd, pgrp);
4943                 setsignal(SIGTSTP);
4944                 setsignal(SIGTTOU);
4945         } else
4946 #endif
4947         if (mode == FORK_BG) {
4948                 /* man bash: "When job control is not in effect,
4949                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4950                 ignoresig(SIGINT);
4951                 ignoresig(SIGQUIT);
4952                 if (jp->nprocs == 0) {
4953                         close(0);
4954                         if (open(bb_dev_null, O_RDONLY) != 0)
4955                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4956                 }
4957         }
4958         if (oldlvl == 0) {
4959                 if (iflag) { /* why if iflag only? */
4960                         setsignal(SIGINT);
4961                         setsignal(SIGTERM);
4962                 }
4963                 /* man bash:
4964                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4965                  * commands run by bash have signal handlers
4966                  * set to the values inherited by the shell
4967                  * from its parent".
4968                  * Take care of the second rule: */
4969                 setsignal(SIGQUIT);
4970         }
4971 #if JOBS
4972         if (n && n->type == NCMD
4973          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4974         ) {
4975                 TRACE(("Job hack\n"));
4976                 /* "jobs": we do not want to clear job list for it,
4977                  * instead we remove only _its_ own_ job from job list.
4978                  * This makes "jobs .... | cat" more useful.
4979                  */
4980                 freejob(curjob);
4981                 return;
4982         }
4983 #endif
4984         for (jp = curjob; jp; jp = jp->prev_job)
4985                 freejob(jp);
4986         jobless = 0;
4987 }
4988
4989 /* Called after fork(), in parent */
4990 #if !JOBS
4991 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4992 #endif
4993 static void
4994 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4995 {
4996         TRACE(("In parent shell: child = %d\n", pid));
4997         if (!jp) {
4998                 /* jp is NULL when called by openhere() for heredoc support */
4999                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5000                         continue;
5001                 jobless++;
5002                 return;
5003         }
5004 #if JOBS
5005         if (mode != FORK_NOJOB && jp->jobctl) {
5006                 int pgrp;
5007
5008                 if (jp->nprocs == 0)
5009                         pgrp = pid;
5010                 else
5011                         pgrp = jp->ps[0].ps_pid;
5012                 /* This can fail because we are doing it in the child also */
5013                 setpgid(pid, pgrp);
5014         }
5015 #endif
5016         if (mode == FORK_BG) {
5017                 backgndpid = pid;               /* set $! */
5018                 set_curjob(jp, CUR_RUNNING);
5019         }
5020         if (jp) {
5021                 struct procstat *ps = &jp->ps[jp->nprocs++];
5022                 ps->ps_pid = pid;
5023                 ps->ps_status = -1;
5024                 ps->ps_cmd = nullstr;
5025 #if JOBS
5026                 if (doing_jobctl && n)
5027                         ps->ps_cmd = commandtext(n);
5028 #endif
5029         }
5030 }
5031
5032 /* jp and n are NULL when called by openhere() for heredoc support */
5033 static int
5034 forkshell(struct job *jp, union node *n, int mode)
5035 {
5036         int pid;
5037
5038         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5039         pid = fork();
5040         if (pid < 0) {
5041                 TRACE(("Fork failed, errno=%d", errno));
5042                 if (jp)
5043                         freejob(jp);
5044                 ash_msg_and_raise_error("can't fork");
5045         }
5046         if (pid == 0) {
5047                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5048                 forkchild(jp, n, mode);
5049         } else {
5050                 forkparent(jp, n, mode, pid);
5051         }
5052         return pid;
5053 }
5054
5055 /*
5056  * Wait for job to finish.
5057  *
5058  * Under job control we have the problem that while a child process
5059  * is running interrupts generated by the user are sent to the child
5060  * but not to the shell.  This means that an infinite loop started by
5061  * an interactive user may be hard to kill.  With job control turned off,
5062  * an interactive user may place an interactive program inside a loop.
5063  * If the interactive program catches interrupts, the user doesn't want
5064  * these interrupts to also abort the loop.  The approach we take here
5065  * is to have the shell ignore interrupt signals while waiting for a
5066  * foreground process to terminate, and then send itself an interrupt
5067  * signal if the child process was terminated by an interrupt signal.
5068  * Unfortunately, some programs want to do a bit of cleanup and then
5069  * exit on interrupt; unless these processes terminate themselves by
5070  * sending a signal to themselves (instead of calling exit) they will
5071  * confuse this approach.
5072  *
5073  * Called with interrupts off.
5074  */
5075 static int
5076 waitforjob(struct job *jp)
5077 {
5078         int st;
5079
5080         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5081
5082         INT_OFF;
5083         while (jp->state == JOBRUNNING) {
5084                 /* In non-interactive shells, we _can_ get
5085                  * a keyboard signal here and be EINTRed,
5086                  * but we just loop back, waiting for command to complete.
5087                  *
5088                  * man bash:
5089                  * "If bash is waiting for a command to complete and receives
5090                  * a signal for which a trap has been set, the trap
5091                  * will not be executed until the command completes."
5092                  *
5093                  * Reality is that even if trap is not set, bash
5094                  * will not act on the signal until command completes.
5095                  * Try this. sleep5intoff.c:
5096                  * #include <signal.h>
5097                  * #include <unistd.h>
5098                  * int main() {
5099                  *         sigset_t set;
5100                  *         sigemptyset(&set);
5101                  *         sigaddset(&set, SIGINT);
5102                  *         sigaddset(&set, SIGQUIT);
5103                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5104                  *         sleep(5);
5105                  *         return 0;
5106                  * }
5107                  * $ bash -c './sleep5intoff; echo hi'
5108                  * ^C^C^C^C <--- pressing ^C once a second
5109                  * $ _
5110                  * $ bash -c './sleep5intoff; echo hi'
5111                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5112                  * $ _
5113                  */
5114                 dowait(DOWAIT_BLOCK, jp);
5115         }
5116         INT_ON;
5117
5118         st = getstatus(jp);
5119 #if JOBS
5120         if (jp->jobctl) {
5121                 xtcsetpgrp(ttyfd, rootpid);
5122                 restore_tty_if_stopped_or_signaled(jp);
5123
5124                 /*
5125                  * This is truly gross.
5126                  * If we're doing job control, then we did a TIOCSPGRP which
5127                  * caused us (the shell) to no longer be in the controlling
5128                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5129                  * intuit from the subprocess exit status whether a SIGINT
5130                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5131                  */
5132                 if (jp->sigint) /* TODO: do the same with all signals */
5133                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5134         }
5135         if (jp->state == JOBDONE)
5136 #endif
5137                 freejob(jp);
5138         return st;
5139 }
5140
5141 /*
5142  * return 1 if there are stopped jobs, otherwise 0
5143  */
5144 static int
5145 stoppedjobs(void)
5146 {
5147         struct job *jp;
5148         int retval;
5149
5150         retval = 0;
5151         if (job_warning)
5152                 goto out;
5153         jp = curjob;
5154         if (jp && jp->state == JOBSTOPPED) {
5155                 out2str("You have stopped jobs.\n");
5156                 job_warning = 2;
5157                 retval++;
5158         }
5159  out:
5160         return retval;
5161 }
5162
5163
5164 /*
5165  * Code for dealing with input/output redirection.
5166  */
5167
5168 #undef EMPTY
5169 #undef CLOSED
5170 #define EMPTY -2                /* marks an unused slot in redirtab */
5171 #define CLOSED -3               /* marks a slot of previously-closed fd */
5172
5173 /*
5174  * Handle here documents.  Normally we fork off a process to write the
5175  * data to a pipe.  If the document is short, we can stuff the data in
5176  * the pipe without forking.
5177  */
5178 /* openhere needs this forward reference */
5179 static void expandhere(union node *arg, int fd);
5180 static int
5181 openhere(union node *redir)
5182 {
5183         int pip[2];
5184         size_t len = 0;
5185
5186         if (pipe(pip) < 0)
5187                 ash_msg_and_raise_error("pipe call failed");
5188         if (redir->type == NHERE) {
5189                 len = strlen(redir->nhere.doc->narg.text);
5190                 if (len <= PIPE_BUF) {
5191                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5192                         goto out;
5193                 }
5194         }
5195         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5196                 /* child */
5197                 close(pip[0]);
5198                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5199                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5200                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5201                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5202                 signal(SIGPIPE, SIG_DFL);
5203                 if (redir->type == NHERE)
5204                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5205                 else /* NXHERE */
5206                         expandhere(redir->nhere.doc, pip[1]);
5207                 _exit(EXIT_SUCCESS);
5208         }
5209  out:
5210         close(pip[1]);
5211         return pip[0];
5212 }
5213
5214 static int
5215 openredirect(union node *redir)
5216 {
5217         struct stat sb;
5218         char *fname;
5219         int f;
5220
5221         switch (redir->nfile.type) {
5222 /* Can't happen, our single caller does this itself */
5223 //      case NTOFD:
5224 //      case NFROMFD:
5225 //              return -1;
5226         case NHERE:
5227         case NXHERE:
5228                 return openhere(redir);
5229         }
5230
5231         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5232          * allocated space. Do it only when we know it is safe.
5233          */
5234         fname = redir->nfile.expfname;
5235
5236         switch (redir->nfile.type) {
5237         default:
5238 #if DEBUG
5239                 abort();
5240 #endif
5241         case NFROM:
5242                 f = open(fname, O_RDONLY);
5243                 if (f < 0)
5244                         goto eopen;
5245                 break;
5246         case NFROMTO:
5247                 f = open(fname, O_RDWR|O_CREAT, 0666);
5248                 if (f < 0)
5249                         goto ecreate;
5250                 break;
5251         case NTO:
5252 #if BASH_REDIR_OUTPUT
5253         case NTO2:
5254 #endif
5255                 /* Take care of noclobber mode. */
5256                 if (Cflag) {
5257                         if (stat(fname, &sb) < 0) {
5258                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5259                                 if (f < 0)
5260                                         goto ecreate;
5261                         } else if (!S_ISREG(sb.st_mode)) {
5262                                 f = open(fname, O_WRONLY, 0666);
5263                                 if (f < 0)
5264                                         goto ecreate;
5265                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5266                                         close(f);
5267                                         errno = EEXIST;
5268                                         goto ecreate;
5269                                 }
5270                         } else {
5271                                 errno = EEXIST;
5272                                 goto ecreate;
5273                         }
5274                         break;
5275                 }
5276                 /* FALLTHROUGH */
5277         case NCLOBBER:
5278                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5279                 if (f < 0)
5280                         goto ecreate;
5281                 break;
5282         case NAPPEND:
5283                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5284                 if (f < 0)
5285                         goto ecreate;
5286                 break;
5287         }
5288
5289         return f;
5290  ecreate:
5291         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5292  eopen:
5293         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5294 }
5295
5296 /*
5297  * Copy a file descriptor to be >= 10. Throws exception on error.
5298  */
5299 static int
5300 savefd(int from)
5301 {
5302         int newfd;
5303         int err;
5304
5305         newfd = fcntl(from, F_DUPFD, 10);
5306         err = newfd < 0 ? errno : 0;
5307         if (err != EBADF) {
5308                 if (err)
5309                         ash_msg_and_raise_error("%d: %m", from);
5310                 close(from);
5311                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5312         }
5313
5314         return newfd;
5315 }
5316 static int
5317 dup2_or_raise(int from, int to)
5318 {
5319         int newfd;
5320
5321         newfd = (from != to) ? dup2(from, to) : to;
5322         if (newfd < 0) {
5323                 /* Happens when source fd is not open: try "echo >&99" */
5324                 ash_msg_and_raise_error("%d: %m", from);
5325         }
5326         return newfd;
5327 }
5328
5329 /* Struct def and variable are moved down to the first usage site */
5330 struct two_fd_t {
5331         int orig, copy;
5332 };
5333 struct redirtab {
5334         struct redirtab *next;
5335         int pair_count;
5336         struct two_fd_t two_fd[];
5337 };
5338 #define redirlist (G_var.redirlist)
5339 enum {
5340         COPYFD_RESTORE = (int)~(INT_MAX),
5341 };
5342
5343 static int
5344 need_to_remember(struct redirtab *rp, int fd)
5345 {
5346         int i;
5347
5348         if (!rp) /* remembering was not requested */
5349                 return 0;
5350
5351         for (i = 0; i < rp->pair_count; i++) {
5352                 if (rp->two_fd[i].orig == fd) {
5353                         /* already remembered */
5354                         return 0;
5355                 }
5356         }
5357         return 1;
5358 }
5359
5360 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5361 static int
5362 is_hidden_fd(struct redirtab *rp, int fd)
5363 {
5364         int i;
5365         struct parsefile *pf;
5366
5367         if (fd == -1)
5368                 return 0;
5369         /* Check open scripts' fds */
5370         pf = g_parsefile;
5371         while (pf) {
5372                 /* We skip pf_fd == 0 case because of the following case:
5373                  * $ ash  # running ash interactively
5374                  * $ . ./script.sh
5375                  * and in script.sh: "exec 9>&0".
5376                  * Even though top-level pf_fd _is_ 0,
5377                  * it's still ok to use it: "read" builtin uses it,
5378                  * why should we cripple "exec" builtin?
5379                  */
5380                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5381                         return 1;
5382                 }
5383                 pf = pf->prev;
5384         }
5385
5386         if (!rp)
5387                 return 0;
5388         /* Check saved fds of redirects */
5389         fd |= COPYFD_RESTORE;
5390         for (i = 0; i < rp->pair_count; i++) {
5391                 if (rp->two_fd[i].copy == fd) {
5392                         return 1;
5393                 }
5394         }
5395         return 0;
5396 }
5397
5398 /*
5399  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5400  * old file descriptors are stashed away so that the redirection can be
5401  * undone by calling popredir.
5402  */
5403 /* flags passed to redirect */
5404 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5405 #define REDIR_SAVEFD2 03        /* set preverrout */
5406 static void
5407 redirect(union node *redir, int flags)
5408 {
5409         struct redirtab *sv;
5410         int sv_pos;
5411         int i;
5412         int fd;
5413         int newfd;
5414         int copied_fd2 = -1;
5415
5416         if (!redir) {
5417                 return;
5418         }
5419
5420         sv = NULL;
5421         sv_pos = 0;
5422         INT_OFF;
5423         if (flags & REDIR_PUSH) {
5424                 union node *tmp = redir;
5425                 do {
5426                         sv_pos++;
5427 #if BASH_REDIR_OUTPUT
5428                         if (tmp->nfile.type == NTO2)
5429                                 sv_pos++;
5430 #endif
5431                         tmp = tmp->nfile.next;
5432                 } while (tmp);
5433                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5434                 sv->next = redirlist;
5435                 sv->pair_count = sv_pos;
5436                 redirlist = sv;
5437                 while (sv_pos > 0) {
5438                         sv_pos--;
5439                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5440                 }
5441         }
5442
5443         do {
5444                 int right_fd = -1;
5445                 fd = redir->nfile.fd;
5446                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5447                         right_fd = redir->ndup.dupfd;
5448                         //bb_error_msg("doing %d > %d", fd, right_fd);
5449                         /* redirect from/to same file descriptor? */
5450                         if (right_fd == fd)
5451                                 continue;
5452                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5453                         if (is_hidden_fd(sv, right_fd)) {
5454                                 errno = EBADF; /* as if it is closed */
5455                                 ash_msg_and_raise_error("%d: %m", right_fd);
5456                         }
5457                         newfd = -1;
5458                 } else {
5459                         newfd = openredirect(redir); /* always >= 0 */
5460                         if (fd == newfd) {
5461                                 /* Descriptor wasn't open before redirect.
5462                                  * Mark it for close in the future */
5463                                 if (need_to_remember(sv, fd)) {
5464                                         goto remember_to_close;
5465                                 }
5466                                 continue;
5467                         }
5468                 }
5469 #if BASH_REDIR_OUTPUT
5470  redirect_more:
5471 #endif
5472                 if (need_to_remember(sv, fd)) {
5473                         /* Copy old descriptor */
5474                         /* Careful to not accidentally "save"
5475                          * to the same fd as right side fd in N>&M */
5476                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5477 #if defined(F_DUPFD_CLOEXEC)
5478                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5479 #else
5480                         i = fcntl(fd, F_DUPFD, minfd);
5481 #endif
5482                         if (i == -1) {
5483                                 i = errno;
5484                                 if (i != EBADF) {
5485                                         /* Strange error (e.g. "too many files" EMFILE?) */
5486                                         if (newfd >= 0)
5487                                                 close(newfd);
5488                                         errno = i;
5489                                         ash_msg_and_raise_error("%d: %m", fd);
5490                                         /* NOTREACHED */
5491                                 }
5492                                 /* EBADF: it is not open - good, remember to close it */
5493  remember_to_close:
5494                                 i = CLOSED;
5495                         } else { /* fd is open, save its copy */
5496 #if !defined(F_DUPFD_CLOEXEC)
5497                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5498 #endif
5499                                 /* "exec fd>&-" should not close fds
5500                                  * which point to script file(s).
5501                                  * Force them to be restored afterwards */
5502                                 if (is_hidden_fd(sv, fd))
5503                                         i |= COPYFD_RESTORE;
5504                         }
5505                         if (fd == 2)
5506                                 copied_fd2 = i;
5507                         sv->two_fd[sv_pos].orig = fd;
5508                         sv->two_fd[sv_pos].copy = i;
5509                         sv_pos++;
5510                 }
5511                 if (newfd < 0) {
5512                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5513                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5514                                 /* Don't want to trigger debugging */
5515                                 if (fd != -1)
5516                                         close(fd);
5517                         } else {
5518                                 dup2_or_raise(redir->ndup.dupfd, fd);
5519                         }
5520                 } else if (fd != newfd) { /* move newfd to fd */
5521                         dup2_or_raise(newfd, fd);
5522 #if BASH_REDIR_OUTPUT
5523                         if (!(redir->nfile.type == NTO2 && fd == 2))
5524 #endif
5525                                 close(newfd);
5526                 }
5527 #if BASH_REDIR_OUTPUT
5528                 if (redir->nfile.type == NTO2 && fd == 1) {
5529                         /* We already redirected it to fd 1, now copy it to 2 */
5530                         newfd = 1;
5531                         fd = 2;
5532                         goto redirect_more;
5533                 }
5534 #endif
5535         } while ((redir = redir->nfile.next) != NULL);
5536
5537         INT_ON;
5538         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5539                 preverrout_fd = copied_fd2;
5540 }
5541
5542 /*
5543  * Undo the effects of the last redirection.
5544  */
5545 static void
5546 popredir(int drop, int restore)
5547 {
5548         struct redirtab *rp;
5549         int i;
5550
5551         if (redirlist == NULL)
5552                 return;
5553         INT_OFF;
5554         rp = redirlist;
5555         for (i = 0; i < rp->pair_count; i++) {
5556                 int fd = rp->two_fd[i].orig;
5557                 int copy = rp->two_fd[i].copy;
5558                 if (copy == CLOSED) {
5559                         if (!drop)
5560                                 close(fd);
5561                         continue;
5562                 }
5563                 if (copy != EMPTY) {
5564                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5565                                 copy &= ~COPYFD_RESTORE;
5566                                 /*close(fd);*/
5567                                 dup2_or_raise(copy, fd);
5568                         }
5569                         close(copy & ~COPYFD_RESTORE);
5570                 }
5571         }
5572         redirlist = rp->next;
5573         free(rp);
5574         INT_ON;
5575 }
5576
5577 /*
5578  * Undo all redirections.  Called on error or interrupt.
5579  */
5580
5581 static int
5582 redirectsafe(union node *redir, int flags)
5583 {
5584         int err;
5585         volatile int saveint;
5586         struct jmploc *volatile savehandler = exception_handler;
5587         struct jmploc jmploc;
5588
5589         SAVE_INT(saveint);
5590         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5591         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5592         if (!err) {
5593                 exception_handler = &jmploc;
5594                 redirect(redir, flags);
5595         }
5596         exception_handler = savehandler;
5597         if (err && exception_type != EXERROR)
5598                 longjmp(exception_handler->loc, 1);
5599         RESTORE_INT(saveint);
5600         return err;
5601 }
5602
5603
5604 /* ============ Routines to expand arguments to commands
5605  *
5606  * We have to deal with backquotes, shell variables, and file metacharacters.
5607  */
5608
5609 #if ENABLE_FEATURE_SH_MATH
5610 static arith_t
5611 ash_arith(const char *s)
5612 {
5613         arith_state_t math_state;
5614         arith_t result;
5615
5616         math_state.lookupvar = lookupvar;
5617         math_state.setvar    = setvar0;
5618         //math_state.endofname = endofname;
5619
5620         INT_OFF;
5621         result = arith(&math_state, s);
5622         if (math_state.errmsg)
5623                 ash_msg_and_raise_error(math_state.errmsg);
5624         INT_ON;
5625
5626         return result;
5627 }
5628 #endif
5629
5630 /*
5631  * expandarg flags
5632  */
5633 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5634 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5635 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5636 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5637 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5638  * POSIX says for this case:
5639  *  Pathname expansion shall not be performed on the word by a
5640  *  non-interactive shell; an interactive shell may perform it, but shall
5641  *  do so only when the expansion would result in one word.
5642  * Currently, our code complies to the above rule by never globbing
5643  * redirection filenames.
5644  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5645  * (this means that on a typical Linux distro, bash almost always
5646  * performs globbing, and thus diverges from what we do).
5647  */
5648 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5649 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5650 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5651 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5652 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5653 /*
5654  * rmescape() flags
5655  */
5656 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5657 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5658 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5659 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5660 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5661
5662 /* Add CTLESC when necessary. */
5663 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5664 /* Do not skip NUL characters. */
5665 #define QUOTES_KEEPNUL EXP_TILDE
5666
5667 /*
5668  * Structure specifying which parts of the string should be searched
5669  * for IFS characters.
5670  */
5671 struct ifsregion {
5672         struct ifsregion *next; /* next region in list */
5673         int begoff;             /* offset of start of region */
5674         int endoff;             /* offset of end of region */
5675         int nulonly;            /* search for nul bytes only */
5676 };
5677
5678 struct arglist {
5679         struct strlist *list;
5680         struct strlist **lastp;
5681 };
5682
5683 /* output of current string */
5684 static char *expdest;
5685 /* list of back quote expressions */
5686 static struct nodelist *argbackq;
5687 /* first struct in list of ifs regions */
5688 static struct ifsregion ifsfirst;
5689 /* last struct in list */
5690 static struct ifsregion *ifslastp;
5691 /* holds expanded arg list */
5692 static struct arglist exparg;
5693
5694 /*
5695  * Our own itoa().
5696  * cvtnum() is used even if math support is off (to prepare $? values and such).
5697  */
5698 static int
5699 cvtnum(arith_t num)
5700 {
5701         int len;
5702
5703         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5704         len = sizeof(arith_t) * 3;
5705         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5706         if (sizeof(arith_t) < 4) len += 2;
5707
5708         expdest = makestrspace(len, expdest);
5709         len = fmtstr(expdest, len, ARITH_FMT, num);
5710         STADJUST(len, expdest);
5711         return len;
5712 }
5713
5714 /*
5715  * Break the argument string into pieces based upon IFS and add the
5716  * strings to the argument list.  The regions of the string to be
5717  * searched for IFS characters have been stored by recordregion.
5718  */
5719 static void
5720 ifsbreakup(char *string, struct arglist *arglist)
5721 {
5722         struct ifsregion *ifsp;
5723         struct strlist *sp;
5724         char *start;
5725         char *p;
5726         char *q;
5727         const char *ifs, *realifs;
5728         int ifsspc;
5729         int nulonly;
5730
5731         start = string;
5732         if (ifslastp != NULL) {
5733                 ifsspc = 0;
5734                 nulonly = 0;
5735                 realifs = ifsset() ? ifsval() : defifs;
5736                 ifsp = &ifsfirst;
5737                 do {
5738                         p = string + ifsp->begoff;
5739                         nulonly = ifsp->nulonly;
5740                         ifs = nulonly ? nullstr : realifs;
5741                         ifsspc = 0;
5742                         while (p < string + ifsp->endoff) {
5743                                 q = p;
5744                                 if ((unsigned char)*p == CTLESC)
5745                                         p++;
5746                                 if (!strchr(ifs, *p)) {
5747                                         p++;
5748                                         continue;
5749                                 }
5750                                 if (!nulonly)
5751                                         ifsspc = (strchr(defifs, *p) != NULL);
5752                                 /* Ignore IFS whitespace at start */
5753                                 if (q == start && ifsspc) {
5754                                         p++;
5755                                         start = p;
5756                                         continue;
5757                                 }
5758                                 *q = '\0';
5759                                 sp = stzalloc(sizeof(*sp));
5760                                 sp->text = start;
5761                                 *arglist->lastp = sp;
5762                                 arglist->lastp = &sp->next;
5763                                 p++;
5764                                 if (!nulonly) {
5765                                         for (;;) {
5766                                                 if (p >= string + ifsp->endoff) {
5767                                                         break;
5768                                                 }
5769                                                 q = p;
5770                                                 if ((unsigned char)*p == CTLESC)
5771                                                         p++;
5772                                                 if (strchr(ifs, *p) == NULL) {
5773                                                         p = q;
5774                                                         break;
5775                                                 }
5776                                                 if (strchr(defifs, *p) == NULL) {
5777                                                         if (ifsspc) {
5778                                                                 p++;
5779                                                                 ifsspc = 0;
5780                                                         } else {
5781                                                                 p = q;
5782                                                                 break;
5783                                                         }
5784                                                 } else
5785                                                         p++;
5786                                         }
5787                                 }
5788                                 start = p;
5789                         } /* while */
5790                         ifsp = ifsp->next;
5791                 } while (ifsp != NULL);
5792                 if (nulonly)
5793                         goto add;
5794         }
5795
5796         if (!*start)
5797                 return;
5798
5799  add:
5800         sp = stzalloc(sizeof(*sp));
5801         sp->text = start;
5802         *arglist->lastp = sp;
5803         arglist->lastp = &sp->next;
5804 }
5805
5806 static void
5807 ifsfree(void)
5808 {
5809         struct ifsregion *p = ifsfirst.next;
5810
5811         if (!p)
5812                 goto out;
5813
5814         INT_OFF;
5815         do {
5816                 struct ifsregion *ifsp;
5817                 ifsp = p->next;
5818                 free(p);
5819                 p = ifsp;
5820         } while (p);
5821         ifsfirst.next = NULL;
5822         INT_ON;
5823  out:
5824         ifslastp = NULL;
5825 }
5826
5827 static size_t
5828 esclen(const char *start, const char *p)
5829 {
5830         size_t esc = 0;
5831
5832         while (p > start && (unsigned char)*--p == CTLESC) {
5833                 esc++;
5834         }
5835         return esc;
5836 }
5837
5838 /*
5839  * Remove any CTLESC characters from a string.
5840  */
5841 static char *
5842 rmescapes(char *str, int flag)
5843 {
5844         static const char qchars[] ALIGN1 = {
5845                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5846
5847         char *p, *q, *r;
5848         unsigned inquotes;
5849         unsigned protect_against_glob;
5850         unsigned globbing;
5851         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5852
5853         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5854         if (!p)
5855                 return str;
5856
5857         q = p;
5858         r = str;
5859         if (flag & RMESCAPE_ALLOC) {
5860                 size_t len = p - str;
5861                 size_t fulllen = len + strlen(p) + 1;
5862
5863                 if (flag & RMESCAPE_GROW) {
5864                         int strloc = str - (char *)stackblock();
5865                         r = makestrspace(fulllen, expdest);
5866                         /* p and str may be invalidated by makestrspace */
5867                         str = (char *)stackblock() + strloc;
5868                         p = str + len;
5869                 } else if (flag & RMESCAPE_HEAP) {
5870                         r = ckmalloc(fulllen);
5871                 } else {
5872                         r = stalloc(fulllen);
5873                 }
5874                 q = r;
5875                 if (len > 0) {
5876                         q = (char *)mempcpy(q, str, len);
5877                 }
5878         }
5879
5880         inquotes = 0;
5881         globbing = flag & RMESCAPE_GLOB;
5882         protect_against_glob = globbing;
5883         while (*p) {
5884                 if ((unsigned char)*p == CTLQUOTEMARK) {
5885 // Note: both inquotes and protect_against_glob only affect whether
5886 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5887                         inquotes = ~inquotes;
5888                         p++;
5889                         protect_against_glob = globbing;
5890                         continue;
5891                 }
5892                 if ((unsigned char)*p == CTLESC) {
5893                         p++;
5894 #if DEBUG
5895                         if (*p == '\0')
5896                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5897 #endif
5898                         if (protect_against_glob) {
5899                                 /*
5900                                  * We used to trust glob() and fnmatch() to eat
5901                                  * superfluous escapes (\z where z has no
5902                                  * special meaning anyway). But this causes
5903                                  * bugs such as string of one greek letter rho
5904                                  * (unicode-encoded as two bytes "cf,81")
5905                                  * getting encoded as "cf,CTLESC,81"
5906                                  * and here, converted to "cf,\,81" -
5907                                  * which does not go well with some flavors
5908                                  * of fnmatch() in unicode locales
5909                                  * (for example, glibc <= 2.22).
5910                                  *
5911                                  * Lets add "\" only on the chars which need it.
5912                                  * Testcases for less obvious chars are shown.
5913                                  */
5914                                 if (*p == '*'
5915                                  || *p == '?'
5916                                  || *p == '['
5917                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5918                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5919                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5920                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5921                                 /* Some libc support [^negate], that's why "^" also needs love */
5922                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5923                                 ) {
5924                                         *q++ = '\\';
5925                                 }
5926                         }
5927                 } else if (*p == '\\' && !inquotes) {
5928                         /* naked back slash */
5929                         protect_against_glob = 0;
5930                         goto copy;
5931                 }
5932 #if BASH_PATTERN_SUBST
5933                 else if (*p == '/' && slash) {
5934                         /* stop handling globbing and mark location of slash */
5935                         globbing = slash = 0;
5936                         *p = CTLESC;
5937                 }
5938 #endif
5939                 protect_against_glob = globbing;
5940  copy:
5941                 *q++ = *p++;
5942         }
5943         *q = '\0';
5944         if (flag & RMESCAPE_GROW) {
5945                 expdest = r;
5946                 STADJUST(q - r + 1, expdest);
5947         }
5948         return r;
5949 }
5950 #define pmatch(a, b) !fnmatch((a), (b), 0)
5951
5952 /*
5953  * Prepare a pattern for a expmeta (internal glob(3)) call.
5954  *
5955  * Returns an stalloced string.
5956  */
5957 static char *
5958 preglob(const char *pattern, int flag)
5959 {
5960         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5961 }
5962
5963 /*
5964  * Put a string on the stack.
5965  */
5966 static void
5967 memtodest(const char *p, size_t len, int syntax, int quotes)
5968 {
5969         char *q;
5970
5971         if (!len)
5972                 return;
5973
5974         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5975
5976         do {
5977                 unsigned char c = *p++;
5978                 if (c) {
5979                         if (quotes & QUOTES_ESC) {
5980                                 int n = SIT(c, syntax);
5981                                 if (n == CCTL
5982                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5983                                      && n == CBACK
5984                                     )
5985                                 ) {
5986                                         USTPUTC(CTLESC, q);
5987                                 }
5988                         }
5989                 } else if (!(quotes & QUOTES_KEEPNUL))
5990                         continue;
5991                 USTPUTC(c, q);
5992         } while (--len);
5993
5994         expdest = q;
5995 }
5996
5997 static size_t
5998 strtodest(const char *p, int syntax, int quotes)
5999 {
6000         size_t len = strlen(p);
6001         memtodest(p, len, syntax, quotes);
6002         return len;
6003 }
6004
6005 /*
6006  * Record the fact that we have to scan this region of the
6007  * string for IFS characters.
6008  */
6009 static void
6010 recordregion(int start, int end, int nulonly)
6011 {
6012         struct ifsregion *ifsp;
6013
6014         if (ifslastp == NULL) {
6015                 ifsp = &ifsfirst;
6016         } else {
6017                 INT_OFF;
6018                 ifsp = ckzalloc(sizeof(*ifsp));
6019                 /*ifsp->next = NULL; - ckzalloc did it */
6020                 ifslastp->next = ifsp;
6021                 INT_ON;
6022         }
6023         ifslastp = ifsp;
6024         ifslastp->begoff = start;
6025         ifslastp->endoff = end;
6026         ifslastp->nulonly = nulonly;
6027 }
6028
6029 static void
6030 removerecordregions(int endoff)
6031 {
6032         if (ifslastp == NULL)
6033                 return;
6034
6035         if (ifsfirst.endoff > endoff) {
6036                 while (ifsfirst.next) {
6037                         struct ifsregion *ifsp;
6038                         INT_OFF;
6039                         ifsp = ifsfirst.next->next;
6040                         free(ifsfirst.next);
6041                         ifsfirst.next = ifsp;
6042                         INT_ON;
6043                 }
6044                 if (ifsfirst.begoff > endoff) {
6045                         ifslastp = NULL;
6046                 } else {
6047                         ifslastp = &ifsfirst;
6048                         ifsfirst.endoff = endoff;
6049                 }
6050                 return;
6051         }
6052
6053         ifslastp = &ifsfirst;
6054         while (ifslastp->next && ifslastp->next->begoff < endoff)
6055                 ifslastp = ifslastp->next;
6056         while (ifslastp->next) {
6057                 struct ifsregion *ifsp;
6058                 INT_OFF;
6059                 ifsp = ifslastp->next->next;
6060                 free(ifslastp->next);
6061                 ifslastp->next = ifsp;
6062                 INT_ON;
6063         }
6064         if (ifslastp->endoff > endoff)
6065                 ifslastp->endoff = endoff;
6066 }
6067
6068 static char *
6069 exptilde(char *startp, char *p, int flags)
6070 {
6071         unsigned char c;
6072         char *name;
6073         struct passwd *pw;
6074         const char *home;
6075         int quotes = flags & QUOTES_ESC;
6076
6077         name = p + 1;
6078
6079         while ((c = *++p) != '\0') {
6080                 switch (c) {
6081                 case CTLESC:
6082                         return startp;
6083                 case CTLQUOTEMARK:
6084                         return startp;
6085                 case ':':
6086                         if (flags & EXP_VARTILDE)
6087                                 goto done;
6088                         break;
6089                 case '/':
6090                 case CTLENDVAR:
6091                         goto done;
6092                 }
6093         }
6094  done:
6095         *p = '\0';
6096         if (*name == '\0') {
6097                 home = lookupvar("HOME");
6098         } else {
6099                 pw = getpwnam(name);
6100                 if (pw == NULL)
6101                         goto lose;
6102                 home = pw->pw_dir;
6103         }
6104         if (!home || !*home)
6105                 goto lose;
6106         *p = c;
6107         strtodest(home, SQSYNTAX, quotes);
6108         return p;
6109  lose:
6110         *p = c;
6111         return startp;
6112 }
6113
6114 /*
6115  * Execute a command inside back quotes.  If it's a builtin command, we
6116  * want to save its output in a block obtained from malloc.  Otherwise
6117  * we fork off a subprocess and get the output of the command via a pipe.
6118  * Should be called with interrupts off.
6119  */
6120 struct backcmd {                /* result of evalbackcmd */
6121         int fd;                 /* file descriptor to read from */
6122         int nleft;              /* number of chars in buffer */
6123         char *buf;              /* buffer */
6124         struct job *jp;         /* job structure for command */
6125 };
6126
6127 /* These forward decls are needed to use "eval" code for backticks handling: */
6128 /* flags in argument to evaltree */
6129 #define EV_EXIT    01           /* exit after evaluating tree */
6130 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6131 static int evaltree(union node *, int);
6132
6133 static void FAST_FUNC
6134 evalbackcmd(union node *n, struct backcmd *result)
6135 {
6136         int pip[2];
6137         struct job *jp;
6138
6139         result->fd = -1;
6140         result->buf = NULL;
6141         result->nleft = 0;
6142         result->jp = NULL;
6143         if (n == NULL) {
6144                 goto out;
6145         }
6146
6147         if (pipe(pip) < 0)
6148                 ash_msg_and_raise_error("pipe call failed");
6149         jp = makejob(/*n,*/ 1);
6150         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6151                 /* child */
6152                 FORCE_INT_ON;
6153                 close(pip[0]);
6154                 if (pip[1] != 1) {
6155                         /*close(1);*/
6156                         dup2_or_raise(pip[1], 1);
6157                         close(pip[1]);
6158                 }
6159 /* TODO: eflag clearing makes the following not abort:
6160  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6161  * which is what bash does (unless it is in POSIX mode).
6162  * dash deleted "eflag = 0" line in the commit
6163  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6164  *  [EVAL] Don't clear eflag in evalbackcmd
6165  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6166  */
6167                 eflag = 0;
6168                 ifsfree();
6169                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6170                 /* NOTREACHED */
6171         }
6172         /* parent */
6173         close(pip[1]);
6174         result->fd = pip[0];
6175         result->jp = jp;
6176
6177  out:
6178         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6179                 result->fd, result->buf, result->nleft, result->jp));
6180 }
6181
6182 /*
6183  * Expand stuff in backwards quotes.
6184  */
6185 static void
6186 expbackq(union node *cmd, int flag)
6187 {
6188         struct backcmd in;
6189         int i;
6190         char buf[128];
6191         char *p;
6192         char *dest;
6193         int startloc;
6194         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6195         struct stackmark smark;
6196
6197         INT_OFF;
6198         startloc = expdest - (char *)stackblock();
6199         pushstackmark(&smark, startloc);
6200         evalbackcmd(cmd, &in);
6201         popstackmark(&smark);
6202
6203         p = in.buf;
6204         i = in.nleft;
6205         if (i == 0)
6206                 goto read;
6207         for (;;) {
6208                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6209  read:
6210                 if (in.fd < 0)
6211                         break;
6212                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6213                 TRACE(("expbackq: read returns %d\n", i));
6214                 if (i <= 0)
6215                         break;
6216                 p = buf;
6217         }
6218
6219         free(in.buf);
6220         if (in.fd >= 0) {
6221                 close(in.fd);
6222                 back_exitstatus = waitforjob(in.jp);
6223         }
6224         INT_ON;
6225
6226         /* Eat all trailing newlines */
6227         dest = expdest;
6228         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6229                 STUNPUTC(dest);
6230         expdest = dest;
6231
6232         if (!(flag & EXP_QUOTED))
6233                 recordregion(startloc, dest - (char *)stackblock(), 0);
6234         TRACE(("evalbackq: size:%d:'%.*s'\n",
6235                 (int)((dest - (char *)stackblock()) - startloc),
6236                 (int)((dest - (char *)stackblock()) - startloc),
6237                 stackblock() + startloc));
6238 }
6239
6240 #if ENABLE_FEATURE_SH_MATH
6241 /*
6242  * Expand arithmetic expression.  Backup to start of expression,
6243  * evaluate, place result in (backed up) result, adjust string position.
6244  */
6245 static void
6246 expari(int flag)
6247 {
6248         char *p, *start;
6249         int begoff;
6250         int len;
6251
6252         /* ifsfree(); */
6253
6254         /*
6255          * This routine is slightly over-complicated for
6256          * efficiency.  Next we scan backwards looking for the
6257          * start of arithmetic.
6258          */
6259         start = stackblock();
6260         p = expdest - 1;
6261         *p = '\0';
6262         p--;
6263         while (1) {
6264                 int esc;
6265
6266                 while ((unsigned char)*p != CTLARI) {
6267                         p--;
6268 #if DEBUG
6269                         if (p < start) {
6270                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6271                         }
6272 #endif
6273                 }
6274
6275                 esc = esclen(start, p);
6276                 if (!(esc % 2)) {
6277                         break;
6278                 }
6279
6280                 p -= esc + 1;
6281         }
6282
6283         begoff = p - start;
6284
6285         removerecordregions(begoff);
6286
6287         expdest = p;
6288
6289         if (flag & QUOTES_ESC)
6290                 rmescapes(p + 1, 0);
6291
6292         len = cvtnum(ash_arith(p + 1));
6293
6294         if (!(flag & EXP_QUOTED))
6295                 recordregion(begoff, begoff + len, 0);
6296 }
6297 #endif
6298
6299 /* argstr needs it */
6300 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6301
6302 /*
6303  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6304  * characters to allow for further processing.  Otherwise treat
6305  * $@ like $* since no splitting will be performed.
6306  *
6307  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6308  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6309  * for correct expansion of "B=$A" word.
6310  */
6311 static void
6312 argstr(char *p, int flags, struct strlist *var_str_list)
6313 {
6314         static const char spclchars[] ALIGN1 = {
6315                 '=',
6316                 ':',
6317                 CTLQUOTEMARK,
6318                 CTLENDVAR,
6319                 CTLESC,
6320                 CTLVAR,
6321                 CTLBACKQ,
6322 #if ENABLE_FEATURE_SH_MATH
6323                 CTLENDARI,
6324 #endif
6325                 '\0'
6326         };
6327         const char *reject = spclchars;
6328         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6329         int inquotes;
6330         size_t length;
6331         int startloc;
6332
6333         if (!(flags & EXP_VARTILDE)) {
6334                 reject += 2;
6335         } else if (flags & EXP_VARTILDE2) {
6336                 reject++;
6337         }
6338         inquotes = 0;
6339         length = 0;
6340         if (flags & EXP_TILDE) {
6341                 char *q;
6342
6343                 flags &= ~EXP_TILDE;
6344  tilde:
6345                 q = p;
6346                 if (*q == '~')
6347                         p = exptilde(p, q, flags);
6348         }
6349  start:
6350         startloc = expdest - (char *)stackblock();
6351         for (;;) {
6352                 unsigned char c;
6353
6354                 length += strcspn(p + length, reject);
6355                 c = p[length];
6356                 if (c) {
6357                         if (!(c & 0x80)
6358                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6359                         ) {
6360                                 /* c == '=' || c == ':' || c == CTLENDARI */
6361                                 length++;
6362                         }
6363                 }
6364                 if (length > 0) {
6365                         int newloc;
6366                         expdest = stack_nputstr(p, length, expdest);
6367                         newloc = expdest - (char *)stackblock();
6368                         if (breakall && !inquotes && newloc > startloc) {
6369                                 recordregion(startloc, newloc, 0);
6370                         }
6371                         startloc = newloc;
6372                 }
6373                 p += length + 1;
6374                 length = 0;
6375
6376                 switch (c) {
6377                 case '\0':
6378                         goto breakloop;
6379                 case '=':
6380                         if (flags & EXP_VARTILDE2) {
6381                                 p--;
6382                                 continue;
6383                         }
6384                         flags |= EXP_VARTILDE2;
6385                         reject++;
6386                         /* fall through */
6387                 case ':':
6388                         /*
6389                          * sort of a hack - expand tildes in variable
6390                          * assignments (after the first '=' and after ':'s).
6391                          */
6392                         if (*--p == '~') {
6393                                 goto tilde;
6394                         }
6395                         continue;
6396                 }
6397
6398                 switch (c) {
6399                 case CTLENDVAR: /* ??? */
6400                         goto breakloop;
6401                 case CTLQUOTEMARK:
6402                         inquotes ^= EXP_QUOTED;
6403                         /* "$@" syntax adherence hack */
6404                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6405                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6406                                 goto start;
6407                         }
6408  addquote:
6409                         if (flags & QUOTES_ESC) {
6410                                 p--;
6411                                 length++;
6412                                 startloc++;
6413                         }
6414                         break;
6415                 case CTLESC:
6416                         startloc++;
6417                         length++;
6418
6419                         /*
6420                          * Quoted parameter expansion pattern: remove quote
6421                          * unless inside inner quotes or we have a literal
6422                          * backslash.
6423                          */
6424                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6425                             EXP_QPAT && *p != '\\')
6426                                 break;
6427
6428                         goto addquote;
6429                 case CTLVAR:
6430                         TRACE(("argstr: evalvar('%s')\n", p));
6431                         p = evalvar(p, flags | inquotes, var_str_list);
6432                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6433                         goto start;
6434                 case CTLBACKQ:
6435                         expbackq(argbackq->n, flags | inquotes);
6436                         argbackq = argbackq->next;
6437                         goto start;
6438 #if ENABLE_FEATURE_SH_MATH
6439                 case CTLENDARI:
6440                         p--;
6441                         expari(flags | inquotes);
6442                         goto start;
6443 #endif
6444                 }
6445         }
6446  breakloop: ;
6447 }
6448
6449 static char *
6450 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6451                 char *pattern, int quotes, int zero)
6452 {
6453         char *loc, *loc2;
6454         char c;
6455
6456         loc = startp;
6457         loc2 = rmesc;
6458         do {
6459                 int match;
6460                 const char *s = loc2;
6461
6462                 c = *loc2;
6463                 if (zero) {
6464                         *loc2 = '\0';
6465                         s = rmesc;
6466                 }
6467                 match = pmatch(pattern, s);
6468
6469                 *loc2 = c;
6470                 if (match)
6471                         return loc;
6472                 if (quotes && (unsigned char)*loc == CTLESC)
6473                         loc++;
6474                 loc++;
6475                 loc2++;
6476         } while (c);
6477         return NULL;
6478 }
6479
6480 static char *
6481 scanright(char *startp, char *rmesc, char *rmescend,
6482                 char *pattern, int quotes, int match_at_start)
6483 {
6484 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6485         int try2optimize = match_at_start;
6486 #endif
6487         int esc = 0;
6488         char *loc;
6489         char *loc2;
6490
6491         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6492          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6493          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6494          * Logic:
6495          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6496          * and on each iteration they go back two/one char until they reach the beginning.
6497          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6498          */
6499         /* TODO: document in what other circumstances we are called. */
6500
6501         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6502                 int match;
6503                 char c = *loc2;
6504                 const char *s = loc2;
6505                 if (match_at_start) {
6506                         *loc2 = '\0';
6507                         s = rmesc;
6508                 }
6509                 match = pmatch(pattern, s);
6510                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6511                 *loc2 = c;
6512                 if (match)
6513                         return loc;
6514 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6515                 if (try2optimize) {
6516                         /* Maybe we can optimize this:
6517                          * if pattern ends with unescaped *, we can avoid checking
6518                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6519                          * it won't match truncated "raw_value_of_" strings too.
6520                          */
6521                         unsigned plen = strlen(pattern);
6522                         /* Does it end with "*"? */
6523                         if (plen != 0 && pattern[--plen] == '*') {
6524                                 /* "xxxx*" is not escaped */
6525                                 /* "xxx\*" is escaped */
6526                                 /* "xx\\*" is not escaped */
6527                                 /* "x\\\*" is escaped */
6528                                 int slashes = 0;
6529                                 while (plen != 0 && pattern[--plen] == '\\')
6530                                         slashes++;
6531                                 if (!(slashes & 1))
6532                                         break; /* ends with unescaped "*" */
6533                         }
6534                         try2optimize = 0;
6535                 }
6536 #endif
6537                 loc--;
6538                 if (quotes) {
6539                         if (--esc < 0) {
6540                                 esc = esclen(startp, loc);
6541                         }
6542                         if (esc % 2) {
6543                                 esc--;
6544                                 loc--;
6545                         }
6546                 }
6547         }
6548         return NULL;
6549 }
6550
6551 static void varunset(const char *, const char *, const char *, int) NORETURN;
6552 static void
6553 varunset(const char *end, const char *var, const char *umsg, int varflags)
6554 {
6555         const char *msg;
6556         const char *tail;
6557
6558         tail = nullstr;
6559         msg = "parameter not set";
6560         if (umsg) {
6561                 if ((unsigned char)*end == CTLENDVAR) {
6562                         if (varflags & VSNUL)
6563                                 tail = " or null";
6564                 } else {
6565                         msg = umsg;
6566                 }
6567         }
6568         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6569 }
6570
6571 static const char *
6572 subevalvar(char *p, char *varname, int strloc, int subtype,
6573                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6574 {
6575         struct nodelist *saveargbackq = argbackq;
6576         int quotes = flag & QUOTES_ESC;
6577         char *startp;
6578         char *loc;
6579         char *rmesc, *rmescend;
6580         char *str;
6581         int amount, resetloc;
6582         IF_BASH_PATTERN_SUBST(int workloc;)
6583         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6584         int zero;
6585         char *(*scan)(char*, char*, char*, char*, int, int);
6586
6587         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6588         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6589
6590         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6591                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6592                         var_str_list);
6593         STPUTC('\0', expdest);
6594         argbackq = saveargbackq;
6595         startp = (char *)stackblock() + startloc;
6596
6597         switch (subtype) {
6598         case VSASSIGN:
6599                 setvar0(varname, startp);
6600                 amount = startp - expdest;
6601                 STADJUST(amount, expdest);
6602                 return startp;
6603
6604         case VSQUESTION:
6605                 varunset(p, varname, startp, varflags);
6606                 /* NOTREACHED */
6607
6608 #if BASH_SUBSTR
6609         case VSSUBSTR: {
6610                 int pos, len, orig_len;
6611                 char *colon;
6612
6613                 loc = str = stackblock() + strloc;
6614
6615 # if !ENABLE_FEATURE_SH_MATH
6616 #  define ash_arith number
6617 # endif
6618                 /* Read POS in ${var:POS:LEN} */
6619                 colon = strchr(loc, ':');
6620                 if (colon) *colon = '\0';
6621                 pos = ash_arith(loc);
6622                 if (colon) *colon = ':';
6623
6624                 /* Read LEN in ${var:POS:LEN} */
6625                 len = str - startp - 1;
6626                 /* *loc != '\0', guaranteed by parser */
6627                 if (quotes) {
6628                         char *ptr;
6629
6630                         /* Adjust the length by the number of escapes */
6631                         for (ptr = startp; ptr < (str - 1); ptr++) {
6632                                 if ((unsigned char)*ptr == CTLESC) {
6633                                         len--;
6634                                         ptr++;
6635                                 }
6636                         }
6637                 }
6638                 orig_len = len;
6639                 if (*loc++ == ':') {
6640                         /* ${var::LEN} */
6641                         len = ash_arith(loc);
6642                 } else {
6643                         /* Skip POS in ${var:POS:LEN} */
6644                         len = orig_len;
6645                         while (*loc && *loc != ':') {
6646                                 loc++;
6647                         }
6648                         if (*loc++ == ':') {
6649                                 len = ash_arith(loc);
6650                         }
6651                 }
6652 #  undef ash_arith
6653
6654                 if (pos < 0) {
6655                         /* ${VAR:$((-n)):l} starts n chars from the end */
6656                         pos = orig_len + pos;
6657                 }
6658                 if ((unsigned)pos >= orig_len) {
6659                         /* apart from obvious ${VAR:999999:l},
6660                          * covers ${VAR:$((-9999999)):l} - result is ""
6661                          * (bash compat)
6662                          */
6663                         pos = 0;
6664                         len = 0;
6665                 }
6666                 if (len < 0) {
6667                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6668                         len = (orig_len - pos) + len;
6669                 }
6670                 if ((unsigned)len > (orig_len - pos))
6671                         len = orig_len - pos;
6672
6673                 for (str = startp; pos; str++, pos--) {
6674                         if (quotes && (unsigned char)*str == CTLESC)
6675                                 str++;
6676                 }
6677                 for (loc = startp; len; len--) {
6678                         if (quotes && (unsigned char)*str == CTLESC)
6679                                 *loc++ = *str++;
6680                         *loc++ = *str++;
6681                 }
6682                 *loc = '\0';
6683                 amount = loc - expdest;
6684                 STADJUST(amount, expdest);
6685                 return loc;
6686         }
6687 #endif /* BASH_SUBSTR */
6688         }
6689
6690         resetloc = expdest - (char *)stackblock();
6691
6692 #if BASH_PATTERN_SUBST
6693         /* We'll comeback here if we grow the stack while handling
6694          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6695          * stack will need rebasing, and we'll need to remove our work
6696          * areas each time
6697          */
6698  restart:
6699 #endif
6700
6701         amount = expdest - ((char *)stackblock() + resetloc);
6702         STADJUST(-amount, expdest);
6703         startp = (char *)stackblock() + startloc;
6704
6705         rmesc = startp;
6706         rmescend = (char *)stackblock() + strloc;
6707         if (quotes) {
6708                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6709                 if (rmesc != startp) {
6710                         rmescend = expdest;
6711                         startp = (char *)stackblock() + startloc;
6712                 }
6713         }
6714         rmescend--;
6715         str = (char *)stackblock() + strloc;
6716         /*
6717          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6718          * The result is a_\_z_c (not a\_\_z_c)!
6719          *
6720          * The search pattern and replace string treat backslashes differently!
6721          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6722          * and string.  It's only used on the first call.
6723          */
6724         preglob(str, IF_BASH_PATTERN_SUBST(
6725                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6726                         RMESCAPE_SLASH : ) 0);
6727
6728 #if BASH_PATTERN_SUBST
6729         workloc = expdest - (char *)stackblock();
6730         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6731                 int len;
6732                 char *idx, *end;
6733
6734                 if (!repl) {
6735                         repl = strchr(str, CTLESC);
6736                         if (repl)
6737                                 *repl++ = '\0';
6738                         else
6739                                 repl = nullstr;
6740                 }
6741                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6742
6743                 /* If there's no pattern to match, return the expansion unmolested */
6744                 if (str[0] == '\0')
6745                         return NULL;
6746
6747                 len = 0;
6748                 idx = startp;
6749                 end = str - 1;
6750                 while (idx < end) {
6751  try_to_match:
6752                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6753                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6754                         if (!loc) {
6755                                 /* No match, advance */
6756                                 char *restart_detect = stackblock();
6757  skip_matching:
6758                                 STPUTC(*idx, expdest);
6759                                 if (quotes && (unsigned char)*idx == CTLESC) {
6760                                         idx++;
6761                                         len++;
6762                                         STPUTC(*idx, expdest);
6763                                 }
6764                                 if (stackblock() != restart_detect)
6765                                         goto restart;
6766                                 idx++;
6767                                 len++;
6768                                 rmesc++;
6769                                 /* continue; - prone to quadratic behavior, smarter code: */
6770                                 if (idx >= end)
6771                                         break;
6772                                 if (str[0] == '*') {
6773                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6774                                          * it would never match "ong_string" etc, no point in trying.
6775                                          */
6776                                         goto skip_matching;
6777                                 }
6778                                 goto try_to_match;
6779                         }
6780
6781                         if (subtype == VSREPLACEALL) {
6782                                 while (idx < loc) {
6783                                         if (quotes && (unsigned char)*idx == CTLESC)
6784                                                 idx++;
6785                                         idx++;
6786                                         rmesc++;
6787                                 }
6788                         } else {
6789                                 idx = loc;
6790                         }
6791
6792                         //bb_error_msg("repl:'%s'", repl);
6793                         for (loc = (char*)repl; *loc; loc++) {
6794                                 char *restart_detect = stackblock();
6795                                 if (quotes && *loc == '\\') {
6796                                         STPUTC(CTLESC, expdest);
6797                                         len++;
6798                                 }
6799                                 STPUTC(*loc, expdest);
6800                                 if (stackblock() != restart_detect)
6801                                         goto restart;
6802                                 len++;
6803                         }
6804
6805                         if (subtype == VSREPLACE) {
6806                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6807                                 while (*idx) {
6808                                         char *restart_detect = stackblock();
6809                                         STPUTC(*idx, expdest);
6810                                         if (stackblock() != restart_detect)
6811                                                 goto restart;
6812                                         len++;
6813                                         idx++;
6814                                 }
6815                                 break;
6816                         }
6817                 }
6818
6819                 /* We've put the replaced text into a buffer at workloc, now
6820                  * move it to the right place and adjust the stack.
6821                  */
6822                 STPUTC('\0', expdest);
6823                 startp = (char *)stackblock() + startloc;
6824                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6825                 //bb_error_msg("startp:'%s'", startp);
6826                 amount = expdest - (startp + len);
6827                 STADJUST(-amount, expdest);
6828                 return startp;
6829         }
6830 #endif /* BASH_PATTERN_SUBST */
6831
6832         subtype -= VSTRIMRIGHT;
6833 #if DEBUG
6834         if (subtype < 0 || subtype > 7)
6835                 abort();
6836 #endif
6837         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6838         zero = subtype >> 1;
6839         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6840         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6841
6842         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6843         if (loc) {
6844                 if (zero) {
6845                         memmove(startp, loc, str - loc);
6846                         loc = startp + (str - loc) - 1;
6847                 }
6848                 *loc = '\0';
6849                 amount = loc - expdest;
6850                 STADJUST(amount, expdest);
6851         }
6852         return loc;
6853 }
6854
6855 /*
6856  * Add the value of a specialized variable to the stack string.
6857  * name parameter (examples):
6858  * ash -c 'echo $1'      name:'1='
6859  * ash -c 'echo $qwe'    name:'qwe='
6860  * ash -c 'echo $$'      name:'$='
6861  * ash -c 'echo ${$}'    name:'$='
6862  * ash -c 'echo ${$##q}' name:'$=q'
6863  * ash -c 'echo ${#$}'   name:'$='
6864  * note: examples with bad shell syntax:
6865  * ash -c 'echo ${#$1}'  name:'$=1'
6866  * ash -c 'echo ${#1#}'  name:'1=#'
6867  */
6868 static NOINLINE ssize_t
6869 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6870 {
6871         const char *p;
6872         int num;
6873         int i;
6874         ssize_t len = 0;
6875         int sep;
6876         int quoted = *quotedp;
6877         int subtype = varflags & VSTYPE;
6878         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6879         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6880         int syntax;
6881
6882         sep = (flags & EXP_FULL) << CHAR_BIT;
6883         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6884
6885         switch (*name) {
6886         case '$':
6887                 num = rootpid;
6888                 goto numvar;
6889         case '?':
6890                 num = exitstatus;
6891                 goto numvar;
6892         case '#':
6893                 num = shellparam.nparam;
6894                 goto numvar;
6895         case '!':
6896                 num = backgndpid;
6897                 if (num == 0)
6898                         return -1;
6899  numvar:
6900                 len = cvtnum(num);
6901                 goto check_1char_name;
6902         case '-':
6903                 expdest = makestrspace(NOPTS, expdest);
6904                 for (i = NOPTS - 1; i >= 0; i--) {
6905                         if (optlist[i]) {
6906                                 USTPUTC(optletters(i), expdest);
6907                                 len++;
6908                         }
6909                 }
6910  check_1char_name:
6911 #if 0
6912                 /* handles cases similar to ${#$1} */
6913                 if (name[2] != '\0')
6914                         raise_error_syntax("bad substitution");
6915 #endif
6916                 break;
6917         case '@':
6918                 if (quoted && sep)
6919                         goto param;
6920                 /* fall through */
6921         case '*': {
6922                 char **ap;
6923                 char sepc;
6924
6925                 if (quoted)
6926                         sep = 0;
6927                 sep |= ifsset() ? ifsval()[0] : ' ';
6928  param:
6929                 sepc = sep;
6930                 *quotedp = !sepc;
6931                 ap = shellparam.p;
6932                 if (!ap)
6933                         return -1;
6934                 while ((p = *ap++) != NULL) {
6935                         len += strtodest(p, syntax, quotes);
6936
6937                         if (*ap && sep) {
6938                                 len++;
6939                                 memtodest(&sepc, 1, syntax, quotes);
6940                         }
6941                 }
6942                 break;
6943         } /* case '*' */
6944         case '0':
6945         case '1':
6946         case '2':
6947         case '3':
6948         case '4':
6949         case '5':
6950         case '6':
6951         case '7':
6952         case '8':
6953         case '9':
6954                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6955                 if (num < 0 || num > shellparam.nparam)
6956                         return -1;
6957                 p = num ? shellparam.p[num - 1] : arg0;
6958                 goto value;
6959         default:
6960                 /* NB: name has form "VAR=..." */
6961
6962                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6963                  * which should be considered before we check variables. */
6964                 if (var_str_list) {
6965                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6966                         p = NULL;
6967                         do {
6968                                 char *str, *eq;
6969                                 str = var_str_list->text;
6970                                 eq = strchr(str, '=');
6971                                 if (!eq) /* stop at first non-assignment */
6972                                         break;
6973                                 eq++;
6974                                 if (name_len == (unsigned)(eq - str)
6975                                  && strncmp(str, name, name_len) == 0
6976                                 ) {
6977                                         p = eq;
6978                                         /* goto value; - WRONG! */
6979                                         /* think "A=1 A=2 B=$A" */
6980                                 }
6981                                 var_str_list = var_str_list->next;
6982                         } while (var_str_list);
6983                         if (p)
6984                                 goto value;
6985                 }
6986                 p = lookupvar(name);
6987  value:
6988                 if (!p)
6989                         return -1;
6990
6991                 len = strtodest(p, syntax, quotes);
6992 #if ENABLE_UNICODE_SUPPORT
6993                 if (subtype == VSLENGTH && len > 0) {
6994                         reinit_unicode_for_ash();
6995                         if (unicode_status == UNICODE_ON) {
6996                                 STADJUST(-len, expdest);
6997                                 discard = 0;
6998                                 len = unicode_strlen(p);
6999                         }
7000                 }
7001 #endif
7002                 break;
7003         }
7004
7005         if (discard)
7006                 STADJUST(-len, expdest);
7007         return len;
7008 }
7009
7010 /*
7011  * Expand a variable, and return a pointer to the next character in the
7012  * input string.
7013  */
7014 static char *
7015 evalvar(char *p, int flag, struct strlist *var_str_list)
7016 {
7017         char varflags;
7018         char subtype;
7019         int quoted;
7020         char easy;
7021         char *var;
7022         int patloc;
7023         int startloc;
7024         ssize_t varlen;
7025
7026         varflags = (unsigned char) *p++;
7027         subtype = varflags & VSTYPE;
7028
7029         if (!subtype)
7030                 raise_error_syntax("bad substitution");
7031
7032         quoted = flag & EXP_QUOTED;
7033         var = p;
7034         easy = (!quoted || (*var == '@' && shellparam.nparam));
7035         startloc = expdest - (char *)stackblock();
7036         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7037
7038  again:
7039         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7040         if (varflags & VSNUL)
7041                 varlen--;
7042
7043         if (subtype == VSPLUS) {
7044                 varlen = -1 - varlen;
7045                 goto vsplus;
7046         }
7047
7048         if (subtype == VSMINUS) {
7049  vsplus:
7050                 if (varlen < 0) {
7051                         argstr(
7052                                 p,
7053                                 flag | EXP_TILDE | EXP_WORD,
7054                                 var_str_list
7055                         );
7056                         goto end;
7057                 }
7058                 goto record;
7059         }
7060
7061         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7062                 if (varlen >= 0)
7063                         goto record;
7064
7065                 subevalvar(p, var, 0, subtype, startloc, varflags,
7066                            flag & ~QUOTES_ESC, var_str_list);
7067                 varflags &= ~VSNUL;
7068                 /*
7069                  * Remove any recorded regions beyond
7070                  * start of variable
7071                  */
7072                 removerecordregions(startloc);
7073                 goto again;
7074         }
7075
7076         if (varlen < 0 && uflag)
7077                 varunset(p, var, 0, 0);
7078
7079         if (subtype == VSLENGTH) {
7080                 cvtnum(varlen > 0 ? varlen : 0);
7081                 goto record;
7082         }
7083
7084         if (subtype == VSNORMAL) {
7085  record:
7086                 if (!easy)
7087                         goto end;
7088                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7089                 goto end;
7090         }
7091
7092 #if DEBUG
7093         switch (subtype) {
7094         case VSTRIMLEFT:
7095         case VSTRIMLEFTMAX:
7096         case VSTRIMRIGHT:
7097         case VSTRIMRIGHTMAX:
7098 #if BASH_SUBSTR
7099         case VSSUBSTR:
7100 #endif
7101 #if BASH_PATTERN_SUBST
7102         case VSREPLACE:
7103         case VSREPLACEALL:
7104 #endif
7105                 break;
7106         default:
7107                 abort();
7108         }
7109 #endif
7110
7111         if (varlen >= 0) {
7112                 /*
7113                  * Terminate the string and start recording the pattern
7114                  * right after it
7115                  */
7116                 STPUTC('\0', expdest);
7117                 patloc = expdest - (char *)stackblock();
7118                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7119                                 startloc, varflags, flag, var_str_list)) {
7120                         int amount = expdest - (
7121                                 (char *)stackblock() + patloc - 1
7122                         );
7123                         STADJUST(-amount, expdest);
7124                 }
7125                 /* Remove any recorded regions beyond start of variable */
7126                 removerecordregions(startloc);
7127                 goto record;
7128         }
7129
7130  end:
7131         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7132                 int nesting = 1;
7133                 for (;;) {
7134                         unsigned char c = *p++;
7135                         if (c == CTLESC)
7136                                 p++;
7137                         else if (c == CTLBACKQ) {
7138                                 if (varlen >= 0)
7139                                         argbackq = argbackq->next;
7140                         } else if (c == CTLVAR) {
7141                                 if ((*p++ & VSTYPE) != VSNORMAL)
7142                                         nesting++;
7143                         } else if (c == CTLENDVAR) {
7144                                 if (--nesting == 0)
7145                                         break;
7146                         }
7147                 }
7148         }
7149         return p;
7150 }
7151
7152 /*
7153  * Add a file name to the list.
7154  */
7155 static void
7156 addfname(const char *name)
7157 {
7158         struct strlist *sp;
7159
7160         sp = stzalloc(sizeof(*sp));
7161         sp->text = sstrdup(name);
7162         *exparg.lastp = sp;
7163         exparg.lastp = &sp->next;
7164 }
7165
7166 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7167 static int
7168 hasmeta(const char *p)
7169 {
7170         static const char chars[] ALIGN1 = {
7171                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7172         };
7173
7174         for (;;) {
7175                 p = strpbrk(p, chars);
7176                 if (!p)
7177                         break;
7178                 switch ((unsigned char) *p) {
7179                 case CTLQUOTEMARK:
7180                         for (;;) {
7181                                 p++;
7182                                 if (*p == CTLQUOTEMARK)
7183                                         break;
7184                                 if (*p == CTLESC)
7185                                         p++;
7186                                 if (*p == '\0') /* huh? */
7187                                         return 0;
7188                         }
7189                         break;
7190                 case '\\':
7191                 case CTLESC:
7192                         p++;
7193                         if (*p == '\0')
7194                                 return 0;
7195                         break;
7196                 case '[':
7197                         if (!strchr(p + 1, ']')) {
7198                                 /* It's not a properly closed [] pattern,
7199                                  * but other metas may follow. Continue checking.
7200                                  * my[file* _is_ globbed by bash
7201                                  * and matches filenames like "my[file1".
7202                                  */
7203                                 break;
7204                         }
7205                         /* fallthrough */
7206                 default:
7207                 /* case '*': */
7208                 /* case '?': */
7209                         return 1;
7210                 }
7211                 p++;
7212         }
7213
7214         return 0;
7215 }
7216
7217 /* If we want to use glob() from libc... */
7218 #if !ENABLE_ASH_INTERNAL_GLOB
7219
7220 /* Add the result of glob() to the list */
7221 static void
7222 addglob(const glob_t *pglob)
7223 {
7224         char **p = pglob->gl_pathv;
7225
7226         do {
7227                 addfname(*p);
7228         } while (*++p);
7229 }
7230 static void
7231 expandmeta(struct strlist *str /*, int flag*/)
7232 {
7233         /* TODO - EXP_REDIR */
7234
7235         while (str) {
7236                 char *p;
7237                 glob_t pglob;
7238                 int i;
7239
7240                 if (fflag)
7241                         goto nometa;
7242
7243                 if (!hasmeta(str->text))
7244                         goto nometa;
7245
7246                 INT_OFF;
7247                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7248 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7249 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7250 //
7251 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7252 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7253 // Which means you need to unescape the string, right? Not so fast:
7254 // if there _is_ a file named "file\?" (with backslash), it is returned
7255 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7256 // You DON'T KNOW by looking at the result whether you need to unescape it.
7257 //
7258 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7259 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7260 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7261 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7262 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7263 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7264                 i = glob(p, 0, NULL, &pglob);
7265                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7266                 if (p != str->text)
7267                         free(p);
7268                 switch (i) {
7269                 case 0:
7270 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7271                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7272                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7273                                 goto nometa2;
7274 #endif
7275                         addglob(&pglob);
7276                         globfree(&pglob);
7277                         INT_ON;
7278                         break;
7279                 case GLOB_NOMATCH:
7280  //nometa2:
7281                         globfree(&pglob);
7282                         INT_ON;
7283  nometa:
7284                         *exparg.lastp = str;
7285                         rmescapes(str->text, 0);
7286                         exparg.lastp = &str->next;
7287                         break;
7288                 default:        /* GLOB_NOSPACE */
7289                         globfree(&pglob);
7290                         INT_ON;
7291                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7292                 }
7293                 str = str->next;
7294         }
7295 }
7296
7297 #else
7298 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7299
7300 /*
7301  * Do metacharacter (i.e. *, ?, [...]) expansion.
7302  */
7303 static void
7304 expmeta(char *expdir, char *enddir, char *name)
7305 {
7306         char *p;
7307         const char *cp;
7308         char *start;
7309         char *endname;
7310         int metaflag;
7311         struct stat statb;
7312         DIR *dirp;
7313         struct dirent *dp;
7314         int atend;
7315         int matchdot;
7316         int esc;
7317
7318         metaflag = 0;
7319         start = name;
7320         for (p = name; esc = 0, *p; p += esc + 1) {
7321                 if (*p == '*' || *p == '?')
7322                         metaflag = 1;
7323                 else if (*p == '[') {
7324                         char *q = p + 1;
7325                         if (*q == '!')
7326                                 q++;
7327                         for (;;) {
7328                                 if (*q == '\\')
7329                                         q++;
7330                                 if (*q == '/' || *q == '\0')
7331                                         break;
7332                                 if (*++q == ']') {
7333                                         metaflag = 1;
7334                                         break;
7335                                 }
7336                         }
7337                 } else {
7338                         if (*p == '\\')
7339                                 esc++;
7340                         if (p[esc] == '/') {
7341                                 if (metaflag)
7342                                         break;
7343                                 start = p + esc + 1;
7344                         }
7345                 }
7346         }
7347         if (metaflag == 0) {    /* we've reached the end of the file name */
7348                 if (enddir != expdir)
7349                         metaflag++;
7350                 p = name;
7351                 do {
7352                         if (*p == '\\')
7353                                 p++;
7354                         *enddir++ = *p;
7355                 } while (*p++);
7356                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7357                         addfname(expdir);
7358                 return;
7359         }
7360         endname = p;
7361         if (name < start) {
7362                 p = name;
7363                 do {
7364                         if (*p == '\\')
7365                                 p++;
7366                         *enddir++ = *p++;
7367                 } while (p < start);
7368         }
7369         if (enddir == expdir) {
7370                 cp = ".";
7371         } else if (enddir == expdir + 1 && *expdir == '/') {
7372                 cp = "/";
7373         } else {
7374                 cp = expdir;
7375                 enddir[-1] = '\0';
7376         }
7377         dirp = opendir(cp);
7378         if (dirp == NULL)
7379                 return;
7380         if (enddir != expdir)
7381                 enddir[-1] = '/';
7382         if (*endname == 0) {
7383                 atend = 1;
7384         } else {
7385                 atend = 0;
7386                 *endname = '\0';
7387                 endname += esc + 1;
7388         }
7389         matchdot = 0;
7390         p = start;
7391         if (*p == '\\')
7392                 p++;
7393         if (*p == '.')
7394                 matchdot++;
7395         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7396                 if (dp->d_name[0] == '.' && !matchdot)
7397                         continue;
7398                 if (pmatch(start, dp->d_name)) {
7399                         if (atend) {
7400                                 strcpy(enddir, dp->d_name);
7401                                 addfname(expdir);
7402                         } else {
7403                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7404                                         continue;
7405                                 p[-1] = '/';
7406                                 expmeta(expdir, p, endname);
7407                         }
7408                 }
7409         }
7410         closedir(dirp);
7411         if (!atend)
7412                 endname[-esc - 1] = esc ? '\\' : '/';
7413 }
7414
7415 static struct strlist *
7416 msort(struct strlist *list, int len)
7417 {
7418         struct strlist *p, *q = NULL;
7419         struct strlist **lpp;
7420         int half;
7421         int n;
7422
7423         if (len <= 1)
7424                 return list;
7425         half = len >> 1;
7426         p = list;
7427         for (n = half; --n >= 0;) {
7428                 q = p;
7429                 p = p->next;
7430         }
7431         q->next = NULL;                 /* terminate first half of list */
7432         q = msort(list, half);          /* sort first half of list */
7433         p = msort(p, len - half);               /* sort second half */
7434         lpp = &list;
7435         for (;;) {
7436 #if ENABLE_LOCALE_SUPPORT
7437                 if (strcoll(p->text, q->text) < 0)
7438 #else
7439                 if (strcmp(p->text, q->text) < 0)
7440 #endif
7441                                                 {
7442                         *lpp = p;
7443                         lpp = &p->next;
7444                         p = *lpp;
7445                         if (p == NULL) {
7446                                 *lpp = q;
7447                                 break;
7448                         }
7449                 } else {
7450                         *lpp = q;
7451                         lpp = &q->next;
7452                         q = *lpp;
7453                         if (q == NULL) {
7454                                 *lpp = p;
7455                                 break;
7456                         }
7457                 }
7458         }
7459         return list;
7460 }
7461
7462 /*
7463  * Sort the results of file name expansion.  It calculates the number of
7464  * strings to sort and then calls msort (short for merge sort) to do the
7465  * work.
7466  */
7467 static struct strlist *
7468 expsort(struct strlist *str)
7469 {
7470         int len;
7471         struct strlist *sp;
7472
7473         len = 0;
7474         for (sp = str; sp; sp = sp->next)
7475                 len++;
7476         return msort(str, len);
7477 }
7478
7479 static void
7480 expandmeta(struct strlist *str /*, int flag*/)
7481 {
7482         /* TODO - EXP_REDIR */
7483
7484         while (str) {
7485                 char *expdir;
7486                 struct strlist **savelastp;
7487                 struct strlist *sp;
7488                 char *p;
7489
7490                 if (fflag)
7491                         goto nometa;
7492                 if (!hasmeta(str->text))
7493                         goto nometa;
7494                 savelastp = exparg.lastp;
7495
7496                 INT_OFF;
7497                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7498                 {
7499                         int i = strlen(str->text);
7500 //BUGGY estimation of how long expanded name can be
7501                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7502                 }
7503                 expmeta(expdir, expdir, p);
7504                 free(expdir);
7505                 if (p != str->text)
7506                         free(p);
7507                 INT_ON;
7508                 if (exparg.lastp == savelastp) {
7509                         /*
7510                          * no matches
7511                          */
7512  nometa:
7513                         *exparg.lastp = str;
7514                         rmescapes(str->text, 0);
7515                         exparg.lastp = &str->next;
7516                 } else {
7517                         *exparg.lastp = NULL;
7518                         *savelastp = sp = expsort(*savelastp);
7519                         while (sp->next != NULL)
7520                                 sp = sp->next;
7521                         exparg.lastp = &sp->next;
7522                 }
7523                 str = str->next;
7524         }
7525 }
7526 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7527
7528 /*
7529  * Perform variable substitution and command substitution on an argument,
7530  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7531  * perform splitting and file name expansion.  When arglist is NULL, perform
7532  * here document expansion.
7533  */
7534 static void
7535 expandarg(union node *arg, struct arglist *arglist, int flag)
7536 {
7537         struct strlist *sp;
7538         char *p;
7539
7540         argbackq = arg->narg.backquote;
7541         STARTSTACKSTR(expdest);
7542         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7543         argstr(arg->narg.text, flag,
7544                         /* var_str_list: */ arglist ? arglist->list : NULL);
7545         p = _STPUTC('\0', expdest);
7546         expdest = p - 1;
7547         if (arglist == NULL) {
7548                 /* here document expanded */
7549                 goto out;
7550         }
7551         p = grabstackstr(p);
7552         TRACE(("expandarg: p:'%s'\n", p));
7553         exparg.lastp = &exparg.list;
7554         /*
7555          * TODO - EXP_REDIR
7556          */
7557         if (flag & EXP_FULL) {
7558                 ifsbreakup(p, &exparg);
7559                 *exparg.lastp = NULL;
7560                 exparg.lastp = &exparg.list;
7561                 expandmeta(exparg.list /*, flag*/);
7562         } else {
7563                 sp = stzalloc(sizeof(*sp));
7564                 sp->text = p;
7565                 *exparg.lastp = sp;
7566                 exparg.lastp = &sp->next;
7567         }
7568         *exparg.lastp = NULL;
7569         if (exparg.list) {
7570                 *arglist->lastp = exparg.list;
7571                 arglist->lastp = exparg.lastp;
7572         }
7573
7574  out:
7575         ifsfree();
7576 }
7577
7578 /*
7579  * Expand shell variables and backquotes inside a here document.
7580  */
7581 static void
7582 expandhere(union node *arg, int fd)
7583 {
7584         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7585         full_write(fd, stackblock(), expdest - (char *)stackblock());
7586 }
7587
7588 /*
7589  * Returns true if the pattern matches the string.
7590  */
7591 static int
7592 patmatch(char *pattern, const char *string)
7593 {
7594         char *p = preglob(pattern, 0);
7595         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7596         return pmatch(p, string);
7597 }
7598
7599 /*
7600  * See if a pattern matches in a case statement.
7601  */
7602 static int
7603 casematch(union node *pattern, char *val)
7604 {
7605         struct stackmark smark;
7606         int result;
7607
7608         setstackmark(&smark);
7609         argbackq = pattern->narg.backquote;
7610         STARTSTACKSTR(expdest);
7611         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7612                         /* var_str_list: */ NULL);
7613         STACKSTRNUL(expdest);
7614         ifsfree();
7615         result = patmatch(stackblock(), val);
7616         popstackmark(&smark);
7617         return result;
7618 }
7619
7620
7621 /* ============ find_command */
7622
7623 struct builtincmd {
7624         const char *name;
7625         int (*builtin)(int, char **) FAST_FUNC;
7626         /* unsigned flags; */
7627 };
7628 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7629 /* "regular" builtins always take precedence over commands,
7630  * regardless of PATH=....%builtin... position */
7631 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7632 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7633
7634 struct cmdentry {
7635         smallint cmdtype;       /* CMDxxx */
7636         union param {
7637                 int index;
7638                 /* index >= 0 for commands without path (slashes) */
7639                 /* (TODO: what exactly does the value mean? PATH position?) */
7640                 /* index == -1 for commands with slashes */
7641                 /* index == (-2 - applet_no) for NOFORK applets */
7642                 const struct builtincmd *cmd;
7643                 struct funcnode *func;
7644         } u;
7645 };
7646 /* values of cmdtype */
7647 #define CMDUNKNOWN      -1      /* no entry in table for command */
7648 #define CMDNORMAL       0       /* command is an executable program */
7649 #define CMDFUNCTION     1       /* command is a shell function */
7650 #define CMDBUILTIN      2       /* command is a shell builtin */
7651
7652 /* action to find_command() */
7653 #define DO_ERR          0x01    /* prints errors */
7654 #define DO_ABS          0x02    /* checks absolute paths */
7655 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7656 #define DO_ALTPATH      0x08    /* using alternate path */
7657 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7658
7659 static void find_command(char *, struct cmdentry *, int, const char *);
7660
7661
7662 /* ============ Hashing commands */
7663
7664 /*
7665  * When commands are first encountered, they are entered in a hash table.
7666  * This ensures that a full path search will not have to be done for them
7667  * on each invocation.
7668  *
7669  * We should investigate converting to a linear search, even though that
7670  * would make the command name "hash" a misnomer.
7671  */
7672
7673 struct tblentry {
7674         struct tblentry *next;  /* next entry in hash chain */
7675         union param param;      /* definition of builtin function */
7676         smallint cmdtype;       /* CMDxxx */
7677         char rehash;            /* if set, cd done since entry created */
7678         char cmdname[1];        /* name of command */
7679 };
7680
7681 static struct tblentry **cmdtable;
7682 #define INIT_G_cmdtable() do { \
7683         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7684 } while (0)
7685
7686 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7687
7688
7689 static void
7690 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7691 {
7692 #if ENABLE_FEATURE_SH_STANDALONE
7693         if (applet_no >= 0) {
7694                 if (APPLET_IS_NOEXEC(applet_no)) {
7695                         clearenv();
7696                         while (*envp)
7697                                 putenv(*envp++);
7698                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7699                         run_applet_no_and_exit(applet_no, cmd, argv);
7700                 }
7701                 /* re-exec ourselves with the new arguments */
7702                 execve(bb_busybox_exec_path, argv, envp);
7703                 /* If they called chroot or otherwise made the binary no longer
7704                  * executable, fall through */
7705         }
7706 #endif
7707
7708  repeat:
7709 #ifdef SYSV
7710         do {
7711                 execve(cmd, argv, envp);
7712         } while (errno == EINTR);
7713 #else
7714         execve(cmd, argv, envp);
7715 #endif
7716         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7717                 /* Run "cmd" as a shell script:
7718                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7719                  * "If the execve() function fails with ENOEXEC, the shell
7720                  * shall execute a command equivalent to having a shell invoked
7721                  * with the command name as its first operand,
7722                  * with any remaining arguments passed to the new shell"
7723                  *
7724                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7725                  * just call ourselves.
7726                  *
7727                  * Note that bash reads ~80 chars of the file, and if it sees
7728                  * a zero byte before it sees newline, it doesn't try to
7729                  * interpret it, but fails with "cannot execute binary file"
7730                  * message and exit code 126. For one, this prevents attempts
7731                  * to interpret foreign ELF binaries as shell scripts.
7732                  */
7733                 argv[0] = cmd;
7734                 cmd = (char*) bb_busybox_exec_path;
7735                 /* NB: this is only possible because all callers of shellexec()
7736                  * ensure that the argv[-1] slot exists!
7737                  */
7738                 argv--;
7739                 argv[0] = (char*) "ash";
7740                 goto repeat;
7741         }
7742 }
7743
7744 /*
7745  * Exec a program.  Never returns.  If you change this routine, you may
7746  * have to change the find_command routine as well.
7747  * argv[-1] must exist and be writable! See tryexec() for why.
7748  */
7749 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7750 static void shellexec(char *prog, char **argv, const char *path, int idx)
7751 {
7752         char *cmdname;
7753         int e;
7754         char **envp;
7755         int exerrno;
7756         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7757
7758         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7759         if (strchr(prog, '/') != NULL
7760 #if ENABLE_FEATURE_SH_STANDALONE
7761          || (applet_no = find_applet_by_name(prog)) >= 0
7762 #endif
7763         ) {
7764                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7765                 if (applet_no >= 0) {
7766                         /* We tried execing ourself, but it didn't work.
7767                          * Maybe /proc/self/exe doesn't exist?
7768                          * Try $PATH search.
7769                          */
7770                         goto try_PATH;
7771                 }
7772                 e = errno;
7773         } else {
7774  try_PATH:
7775                 e = ENOENT;
7776                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7777                         if (--idx < 0 && pathopt == NULL) {
7778                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7779                                 if (errno != ENOENT && errno != ENOTDIR)
7780                                         e = errno;
7781                         }
7782                         stunalloc(cmdname);
7783                 }
7784         }
7785
7786         /* Map to POSIX errors */
7787         switch (e) {
7788         case EACCES:
7789                 exerrno = 126;
7790                 break;
7791         case ENOENT:
7792                 exerrno = 127;
7793                 break;
7794         default:
7795                 exerrno = 2;
7796                 break;
7797         }
7798         exitstatus = exerrno;
7799         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7800                 prog, e, suppress_int));
7801         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7802         /* NOTREACHED */
7803 }
7804
7805 static void
7806 printentry(struct tblentry *cmdp)
7807 {
7808         int idx;
7809         const char *path;
7810         char *name;
7811
7812         idx = cmdp->param.index;
7813         path = pathval();
7814         do {
7815                 name = path_advance(&path, cmdp->cmdname);
7816                 stunalloc(name);
7817         } while (--idx >= 0);
7818         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7819 }
7820
7821 /*
7822  * Clear out command entries.  The argument specifies the first entry in
7823  * PATH which has changed.
7824  */
7825 static void
7826 clearcmdentry(int firstchange)
7827 {
7828         struct tblentry **tblp;
7829         struct tblentry **pp;
7830         struct tblentry *cmdp;
7831
7832         INT_OFF;
7833         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7834                 pp = tblp;
7835                 while ((cmdp = *pp) != NULL) {
7836                         if ((cmdp->cmdtype == CMDNORMAL &&
7837                              cmdp->param.index >= firstchange)
7838                          || (cmdp->cmdtype == CMDBUILTIN &&
7839                              builtinloc >= firstchange)
7840                         ) {
7841                                 *pp = cmdp->next;
7842                                 free(cmdp);
7843                         } else {
7844                                 pp = &cmdp->next;
7845                         }
7846                 }
7847         }
7848         INT_ON;
7849 }
7850
7851 /*
7852  * Locate a command in the command hash table.  If "add" is nonzero,
7853  * add the command to the table if it is not already present.  The
7854  * variable "lastcmdentry" is set to point to the address of the link
7855  * pointing to the entry, so that delete_cmd_entry can delete the
7856  * entry.
7857  *
7858  * Interrupts must be off if called with add != 0.
7859  */
7860 static struct tblentry **lastcmdentry;
7861
7862 static struct tblentry *
7863 cmdlookup(const char *name, int add)
7864 {
7865         unsigned int hashval;
7866         const char *p;
7867         struct tblentry *cmdp;
7868         struct tblentry **pp;
7869
7870         p = name;
7871         hashval = (unsigned char)*p << 4;
7872         while (*p)
7873                 hashval += (unsigned char)*p++;
7874         hashval &= 0x7FFF;
7875         pp = &cmdtable[hashval % CMDTABLESIZE];
7876         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7877                 if (strcmp(cmdp->cmdname, name) == 0)
7878                         break;
7879                 pp = &cmdp->next;
7880         }
7881         if (add && cmdp == NULL) {
7882                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7883                                 + strlen(name)
7884                                 /* + 1 - already done because
7885                                  * tblentry::cmdname is char[1] */);
7886                 /*cmdp->next = NULL; - ckzalloc did it */
7887                 cmdp->cmdtype = CMDUNKNOWN;
7888                 strcpy(cmdp->cmdname, name);
7889         }
7890         lastcmdentry = pp;
7891         return cmdp;
7892 }
7893
7894 /*
7895  * Delete the command entry returned on the last lookup.
7896  */
7897 static void
7898 delete_cmd_entry(void)
7899 {
7900         struct tblentry *cmdp;
7901
7902         INT_OFF;
7903         cmdp = *lastcmdentry;
7904         *lastcmdentry = cmdp->next;
7905         if (cmdp->cmdtype == CMDFUNCTION)
7906                 freefunc(cmdp->param.func);
7907         free(cmdp);
7908         INT_ON;
7909 }
7910
7911 /*
7912  * Add a new command entry, replacing any existing command entry for
7913  * the same name - except special builtins.
7914  */
7915 static void
7916 addcmdentry(char *name, struct cmdentry *entry)
7917 {
7918         struct tblentry *cmdp;
7919
7920         cmdp = cmdlookup(name, 1);
7921         if (cmdp->cmdtype == CMDFUNCTION) {
7922                 freefunc(cmdp->param.func);
7923         }
7924         cmdp->cmdtype = entry->cmdtype;
7925         cmdp->param = entry->u;
7926         cmdp->rehash = 0;
7927 }
7928
7929 static int FAST_FUNC
7930 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7931 {
7932         struct tblentry **pp;
7933         struct tblentry *cmdp;
7934         int c;
7935         struct cmdentry entry;
7936         char *name;
7937
7938         if (nextopt("r") != '\0') {
7939                 clearcmdentry(0);
7940                 return 0;
7941         }
7942
7943         if (*argptr == NULL) {
7944                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7945                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7946                                 if (cmdp->cmdtype == CMDNORMAL)
7947                                         printentry(cmdp);
7948                         }
7949                 }
7950                 return 0;
7951         }
7952
7953         c = 0;
7954         while ((name = *argptr) != NULL) {
7955                 cmdp = cmdlookup(name, 0);
7956                 if (cmdp != NULL
7957                  && (cmdp->cmdtype == CMDNORMAL
7958                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7959                 ) {
7960                         delete_cmd_entry();
7961                 }
7962                 find_command(name, &entry, DO_ERR, pathval());
7963                 if (entry.cmdtype == CMDUNKNOWN)
7964                         c = 1;
7965                 argptr++;
7966         }
7967         return c;
7968 }
7969
7970 /*
7971  * Called when a cd is done.  Marks all commands so the next time they
7972  * are executed they will be rehashed.
7973  */
7974 static void
7975 hashcd(void)
7976 {
7977         struct tblentry **pp;
7978         struct tblentry *cmdp;
7979
7980         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7981                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7982                         if (cmdp->cmdtype == CMDNORMAL
7983                          || (cmdp->cmdtype == CMDBUILTIN
7984                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7985                              && builtinloc > 0)
7986                         ) {
7987                                 cmdp->rehash = 1;
7988                         }
7989                 }
7990         }
7991 }
7992
7993 /*
7994  * Fix command hash table when PATH changed.
7995  * Called before PATH is changed.  The argument is the new value of PATH;
7996  * pathval() still returns the old value at this point.
7997  * Called with interrupts off.
7998  */
7999 static void FAST_FUNC
8000 changepath(const char *new)
8001 {
8002         const char *old;
8003         int firstchange;
8004         int idx;
8005         int idx_bltin;
8006
8007         old = pathval();
8008         firstchange = 9999;     /* assume no change */
8009         idx = 0;
8010         idx_bltin = -1;
8011         for (;;) {
8012                 if (*old != *new) {
8013                         firstchange = idx;
8014                         if ((*old == '\0' && *new == ':')
8015                          || (*old == ':' && *new == '\0')
8016                         ) {
8017                                 firstchange++;
8018                         }
8019                         old = new;      /* ignore subsequent differences */
8020                 }
8021                 if (*new == '\0')
8022                         break;
8023                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8024                         idx_bltin = idx;
8025                 if (*new == ':')
8026                         idx++;
8027                 new++;
8028                 old++;
8029         }
8030         if (builtinloc < 0 && idx_bltin >= 0)
8031                 builtinloc = idx_bltin;             /* zap builtins */
8032         if (builtinloc >= 0 && idx_bltin < 0)
8033                 firstchange = 0;
8034         clearcmdentry(firstchange);
8035         builtinloc = idx_bltin;
8036 }
8037 enum {
8038         TEOF,
8039         TNL,
8040         TREDIR,
8041         TWORD,
8042         TSEMI,
8043         TBACKGND,
8044         TAND,
8045         TOR,
8046         TPIPE,
8047         TLP,
8048         TRP,
8049         TENDCASE,
8050         TENDBQUOTE,
8051         TNOT,
8052         TCASE,
8053         TDO,
8054         TDONE,
8055         TELIF,
8056         TELSE,
8057         TESAC,
8058         TFI,
8059         TFOR,
8060 #if BASH_FUNCTION
8061         TFUNCTION,
8062 #endif
8063         TIF,
8064         TIN,
8065         TTHEN,
8066         TUNTIL,
8067         TWHILE,
8068         TBEGIN,
8069         TEND
8070 };
8071 typedef smallint token_id_t;
8072
8073 /* Nth bit indicates if token marks the end of a list */
8074 enum {
8075         tokendlist = 0
8076         /*  0 */ | (1u << TEOF)
8077         /*  1 */ | (0u << TNL)
8078         /*  2 */ | (0u << TREDIR)
8079         /*  3 */ | (0u << TWORD)
8080         /*  4 */ | (0u << TSEMI)
8081         /*  5 */ | (0u << TBACKGND)
8082         /*  6 */ | (0u << TAND)
8083         /*  7 */ | (0u << TOR)
8084         /*  8 */ | (0u << TPIPE)
8085         /*  9 */ | (0u << TLP)
8086         /* 10 */ | (1u << TRP)
8087         /* 11 */ | (1u << TENDCASE)
8088         /* 12 */ | (1u << TENDBQUOTE)
8089         /* 13 */ | (0u << TNOT)
8090         /* 14 */ | (0u << TCASE)
8091         /* 15 */ | (1u << TDO)
8092         /* 16 */ | (1u << TDONE)
8093         /* 17 */ | (1u << TELIF)
8094         /* 18 */ | (1u << TELSE)
8095         /* 19 */ | (1u << TESAC)
8096         /* 20 */ | (1u << TFI)
8097         /* 21 */ | (0u << TFOR)
8098 #if BASH_FUNCTION
8099         /* 22 */ | (0u << TFUNCTION)
8100 #endif
8101         /* 23 */ | (0u << TIF)
8102         /* 24 */ | (0u << TIN)
8103         /* 25 */ | (1u << TTHEN)
8104         /* 26 */ | (0u << TUNTIL)
8105         /* 27 */ | (0u << TWHILE)
8106         /* 28 */ | (0u << TBEGIN)
8107         /* 29 */ | (1u << TEND)
8108         , /* thus far 29 bits used */
8109 };
8110
8111 static const char *const tokname_array[] = {
8112         "end of file",
8113         "newline",
8114         "redirection",
8115         "word",
8116         ";",
8117         "&",
8118         "&&",
8119         "||",
8120         "|",
8121         "(",
8122         ")",
8123         ";;",
8124         "`",
8125 #define KWDOFFSET 13
8126         /* the following are keywords */
8127         "!",
8128         "case",
8129         "do",
8130         "done",
8131         "elif",
8132         "else",
8133         "esac",
8134         "fi",
8135         "for",
8136 #if BASH_FUNCTION
8137         "function",
8138 #endif
8139         "if",
8140         "in",
8141         "then",
8142         "until",
8143         "while",
8144         "{",
8145         "}",
8146 };
8147
8148 /* Wrapper around strcmp for qsort/bsearch/... */
8149 static int
8150 pstrcmp(const void *a, const void *b)
8151 {
8152         return strcmp((char*)a, *(char**)b);
8153 }
8154
8155 static const char *const *
8156 findkwd(const char *s)
8157 {
8158         return bsearch(s, tokname_array + KWDOFFSET,
8159                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8160                         sizeof(tokname_array[0]), pstrcmp);
8161 }
8162
8163 /*
8164  * Locate and print what a word is...
8165  */
8166 static int
8167 describe_command(char *command, const char *path, int describe_command_verbose)
8168 {
8169         struct cmdentry entry;
8170 #if ENABLE_ASH_ALIAS
8171         const struct alias *ap;
8172 #endif
8173
8174         path = path ? path : pathval();
8175
8176         if (describe_command_verbose) {
8177                 out1str(command);
8178         }
8179
8180         /* First look at the keywords */
8181         if (findkwd(command)) {
8182                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8183                 goto out;
8184         }
8185
8186 #if ENABLE_ASH_ALIAS
8187         /* Then look at the aliases */
8188         ap = lookupalias(command, 0);
8189         if (ap != NULL) {
8190                 if (!describe_command_verbose) {
8191                         out1str("alias ");
8192                         printalias(ap);
8193                         return 0;
8194                 }
8195                 out1fmt(" is an alias for %s", ap->val);
8196                 goto out;
8197         }
8198 #endif
8199         /* Brute force */
8200         find_command(command, &entry, DO_ABS, path);
8201
8202         switch (entry.cmdtype) {
8203         case CMDNORMAL: {
8204                 int j = entry.u.index;
8205                 char *p;
8206                 if (j < 0) {
8207                         p = command;
8208                 } else {
8209                         do {
8210                                 p = path_advance(&path, command);
8211                                 stunalloc(p);
8212                         } while (--j >= 0);
8213                 }
8214                 if (describe_command_verbose) {
8215                         out1fmt(" is %s", p);
8216                 } else {
8217                         out1str(p);
8218                 }
8219                 break;
8220         }
8221
8222         case CMDFUNCTION:
8223                 if (describe_command_verbose) {
8224                         out1str(" is a shell function");
8225                 } else {
8226                         out1str(command);
8227                 }
8228                 break;
8229
8230         case CMDBUILTIN:
8231                 if (describe_command_verbose) {
8232                         out1fmt(" is a %sshell builtin",
8233                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8234                                         "special " : nullstr
8235                         );
8236                 } else {
8237                         out1str(command);
8238                 }
8239                 break;
8240
8241         default:
8242                 if (describe_command_verbose) {
8243                         out1str(": not found\n");
8244                 }
8245                 return 127;
8246         }
8247  out:
8248         out1str("\n");
8249         return 0;
8250 }
8251
8252 static int FAST_FUNC
8253 typecmd(int argc UNUSED_PARAM, char **argv)
8254 {
8255         int i = 1;
8256         int err = 0;
8257         int verbose = 1;
8258
8259         /* type -p ... ? (we don't bother checking for 'p') */
8260         if (argv[1] && argv[1][0] == '-') {
8261                 i++;
8262                 verbose = 0;
8263         }
8264         while (argv[i]) {
8265                 err |= describe_command(argv[i++], NULL, verbose);
8266         }
8267         return err;
8268 }
8269
8270 #if ENABLE_ASH_CMDCMD
8271 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8272 static char **
8273 parse_command_args(char **argv, const char **path)
8274 {
8275         char *cp, c;
8276
8277         for (;;) {
8278                 cp = *++argv;
8279                 if (!cp)
8280                         return NULL;
8281                 if (*cp++ != '-')
8282                         break;
8283                 c = *cp++;
8284                 if (!c)
8285                         break;
8286                 if (c == '-' && !*cp) {
8287                         if (!*++argv)
8288                                 return NULL;
8289                         break;
8290                 }
8291                 do {
8292                         switch (c) {
8293                         case 'p':
8294                                 *path = bb_default_path;
8295                                 break;
8296                         default:
8297                                 /* run 'typecmd' for other options */
8298                                 return NULL;
8299                         }
8300                         c = *cp++;
8301                 } while (c);
8302         }
8303         return argv;
8304 }
8305
8306 static int FAST_FUNC
8307 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8308 {
8309         char *cmd;
8310         int c;
8311         enum {
8312                 VERIFY_BRIEF = 1,
8313                 VERIFY_VERBOSE = 2,
8314         } verify = 0;
8315         const char *path = NULL;
8316
8317         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8318          * never reaches this function.
8319          */
8320
8321         while ((c = nextopt("pvV")) != '\0')
8322                 if (c == 'V')
8323                         verify |= VERIFY_VERBOSE;
8324                 else if (c == 'v')
8325                         /*verify |= VERIFY_BRIEF*/;
8326 #if DEBUG
8327                 else if (c != 'p')
8328                         abort();
8329 #endif
8330                 else
8331                         path = bb_default_path;
8332
8333         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8334         cmd = *argptr;
8335         if (/*verify && */ cmd)
8336                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8337
8338         return 0;
8339 }
8340 #endif
8341
8342
8343 /*static int funcblocksize;     // size of structures in function */
8344 /*static int funcstringsize;    // size of strings in node */
8345 static void *funcblock;         /* block to allocate function from */
8346 static char *funcstring_end;    /* end of block to allocate strings from */
8347
8348 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8349         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8350         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8351         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8352         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8353         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8354         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8355         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8356         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8357         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8358         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8359         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8360         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8361         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8362         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8363         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8364         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8365         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8366 #if BASH_REDIR_OUTPUT
8367         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8368 #endif
8369         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8370         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8371         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8372         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8373         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8374         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8375         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8376         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8377         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8378 };
8379
8380 static int calcsize(int funcblocksize, union node *n);
8381
8382 static int
8383 sizenodelist(int funcblocksize, struct nodelist *lp)
8384 {
8385         while (lp) {
8386                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8387                 funcblocksize = calcsize(funcblocksize, lp->n);
8388                 lp = lp->next;
8389         }
8390         return funcblocksize;
8391 }
8392
8393 static int
8394 calcsize(int funcblocksize, union node *n)
8395 {
8396         if (n == NULL)
8397                 return funcblocksize;
8398         funcblocksize += nodesize[n->type];
8399         switch (n->type) {
8400         case NCMD:
8401                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8402                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8403                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8404                 break;
8405         case NPIPE:
8406                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8407                 break;
8408         case NREDIR:
8409         case NBACKGND:
8410         case NSUBSHELL:
8411                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8412                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8413                 break;
8414         case NAND:
8415         case NOR:
8416         case NSEMI:
8417         case NWHILE:
8418         case NUNTIL:
8419                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8420                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8421                 break;
8422         case NIF:
8423                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8424                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8425                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8426                 break;
8427         case NFOR:
8428                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8429                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8430                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8431                 break;
8432         case NCASE:
8433                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8434                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8435                 break;
8436         case NCLIST:
8437                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8438                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8439                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8440                 break;
8441         case NDEFUN:
8442         case NARG:
8443                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8444                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8445                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8446                 break;
8447         case NTO:
8448 #if BASH_REDIR_OUTPUT
8449         case NTO2:
8450 #endif
8451         case NCLOBBER:
8452         case NFROM:
8453         case NFROMTO:
8454         case NAPPEND:
8455                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8456                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8457                 break;
8458         case NTOFD:
8459         case NFROMFD:
8460                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8461                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8462         break;
8463         case NHERE:
8464         case NXHERE:
8465                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8466                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8467                 break;
8468         case NNOT:
8469                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8470                 break;
8471         };
8472         return funcblocksize;
8473 }
8474
8475 static char *
8476 nodeckstrdup(char *s)
8477 {
8478         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8479         return strcpy(funcstring_end, s);
8480 }
8481
8482 static union node *copynode(union node *);
8483
8484 static struct nodelist *
8485 copynodelist(struct nodelist *lp)
8486 {
8487         struct nodelist *start;
8488         struct nodelist **lpp;
8489
8490         lpp = &start;
8491         while (lp) {
8492                 *lpp = funcblock;
8493                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8494                 (*lpp)->n = copynode(lp->n);
8495                 lp = lp->next;
8496                 lpp = &(*lpp)->next;
8497         }
8498         *lpp = NULL;
8499         return start;
8500 }
8501
8502 static union node *
8503 copynode(union node *n)
8504 {
8505         union node *new;
8506
8507         if (n == NULL)
8508                 return NULL;
8509         new = funcblock;
8510         funcblock = (char *) funcblock + nodesize[n->type];
8511
8512         switch (n->type) {
8513         case NCMD:
8514                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8515                 new->ncmd.args = copynode(n->ncmd.args);
8516                 new->ncmd.assign = copynode(n->ncmd.assign);
8517                 break;
8518         case NPIPE:
8519                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8520                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8521                 break;
8522         case NREDIR:
8523         case NBACKGND:
8524         case NSUBSHELL:
8525                 new->nredir.redirect = copynode(n->nredir.redirect);
8526                 new->nredir.n = copynode(n->nredir.n);
8527                 break;
8528         case NAND:
8529         case NOR:
8530         case NSEMI:
8531         case NWHILE:
8532         case NUNTIL:
8533                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8534                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8535                 break;
8536         case NIF:
8537                 new->nif.elsepart = copynode(n->nif.elsepart);
8538                 new->nif.ifpart = copynode(n->nif.ifpart);
8539                 new->nif.test = copynode(n->nif.test);
8540                 break;
8541         case NFOR:
8542                 new->nfor.var = nodeckstrdup(n->nfor.var);
8543                 new->nfor.body = copynode(n->nfor.body);
8544                 new->nfor.args = copynode(n->nfor.args);
8545                 break;
8546         case NCASE:
8547                 new->ncase.cases = copynode(n->ncase.cases);
8548                 new->ncase.expr = copynode(n->ncase.expr);
8549                 break;
8550         case NCLIST:
8551                 new->nclist.body = copynode(n->nclist.body);
8552                 new->nclist.pattern = copynode(n->nclist.pattern);
8553                 new->nclist.next = copynode(n->nclist.next);
8554                 break;
8555         case NDEFUN:
8556         case NARG:
8557                 new->narg.backquote = copynodelist(n->narg.backquote);
8558                 new->narg.text = nodeckstrdup(n->narg.text);
8559                 new->narg.next = copynode(n->narg.next);
8560                 break;
8561         case NTO:
8562 #if BASH_REDIR_OUTPUT
8563         case NTO2:
8564 #endif
8565         case NCLOBBER:
8566         case NFROM:
8567         case NFROMTO:
8568         case NAPPEND:
8569                 new->nfile.fname = copynode(n->nfile.fname);
8570                 new->nfile.fd = n->nfile.fd;
8571                 new->nfile.next = copynode(n->nfile.next);
8572                 break;
8573         case NTOFD:
8574         case NFROMFD:
8575                 new->ndup.vname = copynode(n->ndup.vname);
8576                 new->ndup.dupfd = n->ndup.dupfd;
8577                 new->ndup.fd = n->ndup.fd;
8578                 new->ndup.next = copynode(n->ndup.next);
8579                 break;
8580         case NHERE:
8581         case NXHERE:
8582                 new->nhere.doc = copynode(n->nhere.doc);
8583                 new->nhere.fd = n->nhere.fd;
8584                 new->nhere.next = copynode(n->nhere.next);
8585                 break;
8586         case NNOT:
8587                 new->nnot.com = copynode(n->nnot.com);
8588                 break;
8589         };
8590         new->type = n->type;
8591         return new;
8592 }
8593
8594 /*
8595  * Make a copy of a parse tree.
8596  */
8597 static struct funcnode *
8598 copyfunc(union node *n)
8599 {
8600         struct funcnode *f;
8601         size_t blocksize;
8602
8603         /*funcstringsize = 0;*/
8604         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8605         f = ckzalloc(blocksize /* + funcstringsize */);
8606         funcblock = (char *) f + offsetof(struct funcnode, n);
8607         funcstring_end = (char *) f + blocksize;
8608         copynode(n);
8609         /* f->count = 0; - ckzalloc did it */
8610         return f;
8611 }
8612
8613 /*
8614  * Define a shell function.
8615  */
8616 static void
8617 defun(union node *func)
8618 {
8619         struct cmdentry entry;
8620
8621         INT_OFF;
8622         entry.cmdtype = CMDFUNCTION;
8623         entry.u.func = copyfunc(func);
8624         addcmdentry(func->narg.text, &entry);
8625         INT_ON;
8626 }
8627
8628 /* Reasons for skipping commands (see comment on breakcmd routine) */
8629 #define SKIPBREAK      (1 << 0)
8630 #define SKIPCONT       (1 << 1)
8631 #define SKIPFUNC       (1 << 2)
8632 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8633 static int skipcount;           /* number of levels to skip */
8634 static int funcnest;            /* depth of function calls */
8635 static int loopnest;            /* current loop nesting level */
8636
8637 /* Forward decl way out to parsing code - dotrap needs it */
8638 static int evalstring(char *s, int flags);
8639
8640 /* Called to execute a trap.
8641  * Single callsite - at the end of evaltree().
8642  * If we return non-zero, evaltree raises EXEXIT exception.
8643  *
8644  * Perhaps we should avoid entering new trap handlers
8645  * while we are executing a trap handler. [is it a TODO?]
8646  */
8647 static void
8648 dotrap(void)
8649 {
8650         uint8_t *g;
8651         int sig;
8652         uint8_t last_status;
8653
8654         if (!pending_sig)
8655                 return;
8656
8657         last_status = exitstatus;
8658         pending_sig = 0;
8659         barrier();
8660
8661         TRACE(("dotrap entered\n"));
8662         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8663                 char *p;
8664
8665                 if (!*g)
8666                         continue;
8667
8668                 if (evalskip) {
8669                         pending_sig = sig;
8670                         break;
8671                 }
8672
8673                 p = trap[sig];
8674                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8675                  * don't upset it by resetting gotsig[SIGINT-1] */
8676                 if (sig == SIGINT && !p)
8677                         continue;
8678
8679                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8680                 *g = 0;
8681                 if (!p)
8682                         continue;
8683                 evalstring(p, 0);
8684         }
8685         exitstatus = last_status;
8686         TRACE(("dotrap returns\n"));
8687 }
8688
8689 /* forward declarations - evaluation is fairly recursive business... */
8690 static int evalloop(union node *, int);
8691 static int evalfor(union node *, int);
8692 static int evalcase(union node *, int);
8693 static int evalsubshell(union node *, int);
8694 static void expredir(union node *);
8695 static int evalpipe(union node *, int);
8696 static int evalcommand(union node *, int);
8697 static int evalbltin(const struct builtincmd *, int, char **, int);
8698 static void prehash(union node *);
8699
8700 /*
8701  * Evaluate a parse tree.  The value is left in the global variable
8702  * exitstatus.
8703  */
8704 static int
8705 evaltree(union node *n, int flags)
8706 {
8707         int checkexit = 0;
8708         int (*evalfn)(union node *, int);
8709         int status = 0;
8710
8711         if (n == NULL) {
8712                 TRACE(("evaltree(NULL) called\n"));
8713                 goto out;
8714         }
8715         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8716
8717         dotrap();
8718
8719         switch (n->type) {
8720         default:
8721 #if DEBUG
8722                 out1fmt("Node type = %d\n", n->type);
8723                 fflush_all();
8724                 break;
8725 #endif
8726         case NNOT:
8727                 status = !evaltree(n->nnot.com, EV_TESTED);
8728                 goto setstatus;
8729         case NREDIR:
8730                 expredir(n->nredir.redirect);
8731                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8732                 if (!status) {
8733                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8734                 }
8735                 if (n->nredir.redirect)
8736                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8737                 goto setstatus;
8738         case NCMD:
8739                 evalfn = evalcommand;
8740  checkexit:
8741                 if (eflag && !(flags & EV_TESTED))
8742                         checkexit = ~0;
8743                 goto calleval;
8744         case NFOR:
8745                 evalfn = evalfor;
8746                 goto calleval;
8747         case NWHILE:
8748         case NUNTIL:
8749                 evalfn = evalloop;
8750                 goto calleval;
8751         case NSUBSHELL:
8752         case NBACKGND:
8753                 evalfn = evalsubshell;
8754                 goto checkexit;
8755         case NPIPE:
8756                 evalfn = evalpipe;
8757                 goto checkexit;
8758         case NCASE:
8759                 evalfn = evalcase;
8760                 goto calleval;
8761         case NAND:
8762         case NOR:
8763         case NSEMI: {
8764
8765 #if NAND + 1 != NOR
8766 #error NAND + 1 != NOR
8767 #endif
8768 #if NOR + 1 != NSEMI
8769 #error NOR + 1 != NSEMI
8770 #endif
8771                 unsigned is_or = n->type - NAND;
8772                 status = evaltree(
8773                         n->nbinary.ch1,
8774                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8775                 );
8776                 if ((!status) == is_or || evalskip)
8777                         break;
8778                 n = n->nbinary.ch2;
8779  evaln:
8780                 evalfn = evaltree;
8781  calleval:
8782                 status = evalfn(n, flags);
8783                 goto setstatus;
8784         }
8785         case NIF:
8786                 status = evaltree(n->nif.test, EV_TESTED);
8787                 if (evalskip)
8788                         break;
8789                 if (!status) {
8790                         n = n->nif.ifpart;
8791                         goto evaln;
8792                 }
8793                 if (n->nif.elsepart) {
8794                         n = n->nif.elsepart;
8795                         goto evaln;
8796                 }
8797                 status = 0;
8798                 goto setstatus;
8799         case NDEFUN:
8800                 defun(n);
8801                 /* Not necessary. To test it:
8802                  * "false; f() { qwerty; }; echo $?" should print 0.
8803                  */
8804                 /* status = 0; */
8805  setstatus:
8806                 exitstatus = status;
8807                 break;
8808         }
8809  out:
8810         /* Order of checks below is important:
8811          * signal handlers trigger before exit caused by "set -e".
8812          */
8813         dotrap();
8814
8815         if (checkexit & status)
8816                 raise_exception(EXEXIT);
8817         if (flags & EV_EXIT)
8818                 raise_exception(EXEXIT);
8819
8820         TRACE(("leaving evaltree (no interrupts)\n"));
8821         return exitstatus;
8822 }
8823
8824 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8825 static
8826 #endif
8827 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8828
8829 static int
8830 skiploop(void)
8831 {
8832         int skip = evalskip;
8833
8834         switch (skip) {
8835         case 0:
8836                 break;
8837         case SKIPBREAK:
8838         case SKIPCONT:
8839                 if (--skipcount <= 0) {
8840                         evalskip = 0;
8841                         break;
8842                 }
8843                 skip = SKIPBREAK;
8844                 break;
8845         }
8846         return skip;
8847 }
8848
8849 static int
8850 evalloop(union node *n, int flags)
8851 {
8852         int skip;
8853         int status;
8854
8855         loopnest++;
8856         status = 0;
8857         flags &= EV_TESTED;
8858         do {
8859                 int i;
8860
8861                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8862                 skip = skiploop();
8863                 if (skip == SKIPFUNC)
8864                         status = i;
8865                 if (skip)
8866                         continue;
8867                 if (n->type != NWHILE)
8868                         i = !i;
8869                 if (i != 0)
8870                         break;
8871                 status = evaltree(n->nbinary.ch2, flags);
8872                 skip = skiploop();
8873         } while (!(skip & ~SKIPCONT));
8874         loopnest--;
8875
8876         return status;
8877 }
8878
8879 static int
8880 evalfor(union node *n, int flags)
8881 {
8882         struct arglist arglist;
8883         union node *argp;
8884         struct strlist *sp;
8885         struct stackmark smark;
8886         int status = 0;
8887
8888         setstackmark(&smark);
8889         arglist.list = NULL;
8890         arglist.lastp = &arglist.list;
8891         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8892                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8893         }
8894         *arglist.lastp = NULL;
8895
8896         loopnest++;
8897         flags &= EV_TESTED;
8898         for (sp = arglist.list; sp; sp = sp->next) {
8899                 setvar0(n->nfor.var, sp->text);
8900                 status = evaltree(n->nfor.body, flags);
8901                 if (skiploop() & ~SKIPCONT)
8902                         break;
8903         }
8904         loopnest--;
8905         popstackmark(&smark);
8906
8907         return status;
8908 }
8909
8910 static int
8911 evalcase(union node *n, int flags)
8912 {
8913         union node *cp;
8914         union node *patp;
8915         struct arglist arglist;
8916         struct stackmark smark;
8917         int status = 0;
8918
8919         setstackmark(&smark);
8920         arglist.list = NULL;
8921         arglist.lastp = &arglist.list;
8922         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8923         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8924                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8925                         if (casematch(patp, arglist.list->text)) {
8926                                 /* Ensure body is non-empty as otherwise
8927                                  * EV_EXIT may prevent us from setting the
8928                                  * exit status.
8929                                  */
8930                                 if (evalskip == 0 && cp->nclist.body) {
8931                                         status = evaltree(cp->nclist.body, flags);
8932                                 }
8933                                 goto out;
8934                         }
8935                 }
8936         }
8937  out:
8938         popstackmark(&smark);
8939
8940         return status;
8941 }
8942
8943 /*
8944  * Kick off a subshell to evaluate a tree.
8945  */
8946 static int
8947 evalsubshell(union node *n, int flags)
8948 {
8949         struct job *jp;
8950         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8951         int status;
8952
8953         expredir(n->nredir.redirect);
8954         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8955                 goto nofork;
8956         INT_OFF;
8957         if (backgnd == FORK_FG)
8958                 get_tty_state();
8959         jp = makejob(/*n,*/ 1);
8960         if (forkshell(jp, n, backgnd) == 0) {
8961                 /* child */
8962                 INT_ON;
8963                 flags |= EV_EXIT;
8964                 if (backgnd)
8965                         flags &= ~EV_TESTED;
8966  nofork:
8967                 redirect(n->nredir.redirect, 0);
8968                 evaltreenr(n->nredir.n, flags);
8969                 /* never returns */
8970         }
8971         /* parent */
8972         status = 0;
8973         if (backgnd == FORK_FG)
8974                 status = waitforjob(jp);
8975         INT_ON;
8976         return status;
8977 }
8978
8979 /*
8980  * Compute the names of the files in a redirection list.
8981  */
8982 static void fixredir(union node *, const char *, int);
8983 static void
8984 expredir(union node *n)
8985 {
8986         union node *redir;
8987
8988         for (redir = n; redir; redir = redir->nfile.next) {
8989                 struct arglist fn;
8990
8991                 fn.list = NULL;
8992                 fn.lastp = &fn.list;
8993                 switch (redir->type) {
8994                 case NFROMTO:
8995                 case NFROM:
8996                 case NTO:
8997 #if BASH_REDIR_OUTPUT
8998                 case NTO2:
8999 #endif
9000                 case NCLOBBER:
9001                 case NAPPEND:
9002                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9003                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9004 #if BASH_REDIR_OUTPUT
9005  store_expfname:
9006 #endif
9007 #if 0
9008 // By the design of stack allocator, the loop of this kind:
9009 //      while true; do while true; do break; done </dev/null; done
9010 // will look like a memory leak: ash plans to free expfname's
9011 // of "/dev/null" as soon as it finishes running the loop
9012 // (in this case, never).
9013 // This "fix" is wrong:
9014                         if (redir->nfile.expfname)
9015                                 stunalloc(redir->nfile.expfname);
9016 // It results in corrupted state of stacked allocations.
9017 #endif
9018                         redir->nfile.expfname = fn.list->text;
9019                         break;
9020                 case NFROMFD:
9021                 case NTOFD: /* >& */
9022                         if (redir->ndup.vname) {
9023                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9024                                 if (fn.list == NULL)
9025                                         ash_msg_and_raise_error("redir error");
9026 #if BASH_REDIR_OUTPUT
9027 //FIXME: we used expandarg with different args!
9028                                 if (!isdigit_str9(fn.list->text)) {
9029                                         /* >&file, not >&fd */
9030                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9031                                                 ash_msg_and_raise_error("redir error");
9032                                         redir->type = NTO2;
9033                                         goto store_expfname;
9034                                 }
9035 #endif
9036                                 fixredir(redir, fn.list->text, 1);
9037                         }
9038                         break;
9039                 }
9040         }
9041 }
9042
9043 /*
9044  * Evaluate a pipeline.  All the processes in the pipeline are children
9045  * of the process creating the pipeline.  (This differs from some versions
9046  * of the shell, which make the last process in a pipeline the parent
9047  * of all the rest.)
9048  */
9049 static int
9050 evalpipe(union node *n, int flags)
9051 {
9052         struct job *jp;
9053         struct nodelist *lp;
9054         int pipelen;
9055         int prevfd;
9056         int pip[2];
9057         int status = 0;
9058
9059         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9060         pipelen = 0;
9061         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9062                 pipelen++;
9063         flags |= EV_EXIT;
9064         INT_OFF;
9065         if (n->npipe.pipe_backgnd == 0)
9066                 get_tty_state();
9067         jp = makejob(/*n,*/ pipelen);
9068         prevfd = -1;
9069         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9070                 prehash(lp->n);
9071                 pip[1] = -1;
9072                 if (lp->next) {
9073                         if (pipe(pip) < 0) {
9074                                 close(prevfd);
9075                                 ash_msg_and_raise_error("pipe call failed");
9076                         }
9077                 }
9078                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9079                         /* child */
9080                         INT_ON;
9081                         if (pip[1] >= 0) {
9082                                 close(pip[0]);
9083                         }
9084                         if (prevfd > 0) {
9085                                 dup2(prevfd, 0);
9086                                 close(prevfd);
9087                         }
9088                         if (pip[1] > 1) {
9089                                 dup2(pip[1], 1);
9090                                 close(pip[1]);
9091                         }
9092                         evaltreenr(lp->n, flags);
9093                         /* never returns */
9094                 }
9095                 /* parent */
9096                 if (prevfd >= 0)
9097                         close(prevfd);
9098                 prevfd = pip[0];
9099                 /* Don't want to trigger debugging */
9100                 if (pip[1] != -1)
9101                         close(pip[1]);
9102         }
9103         if (n->npipe.pipe_backgnd == 0) {
9104                 status = waitforjob(jp);
9105                 TRACE(("evalpipe:  job done exit status %d\n", status));
9106         }
9107         INT_ON;
9108
9109         return status;
9110 }
9111
9112 /*
9113  * Controls whether the shell is interactive or not.
9114  */
9115 static void
9116 setinteractive(int on)
9117 {
9118         static smallint is_interactive;
9119
9120         if (++on == is_interactive)
9121                 return;
9122         is_interactive = on;
9123         setsignal(SIGINT);
9124         setsignal(SIGQUIT);
9125         setsignal(SIGTERM);
9126 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9127         if (is_interactive > 1) {
9128                 /* Looks like they want an interactive shell */
9129                 static smallint did_banner;
9130
9131                 if (!did_banner) {
9132                         /* note: ash and hush share this string */
9133                         out1fmt("\n\n%s %s\n"
9134                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9135                                 "\n",
9136                                 bb_banner,
9137                                 "built-in shell (ash)"
9138                         );
9139                         did_banner = 1;
9140                 }
9141         }
9142 #endif
9143 }
9144
9145 static void
9146 optschanged(void)
9147 {
9148 #if DEBUG
9149         opentrace();
9150 #endif
9151         setinteractive(iflag);
9152         setjobctl(mflag);
9153 #if ENABLE_FEATURE_EDITING_VI
9154         if (viflag)
9155                 line_input_state->flags |= VI_MODE;
9156         else
9157                 line_input_state->flags &= ~VI_MODE;
9158 #else
9159         viflag = 0; /* forcibly keep the option off */
9160 #endif
9161 }
9162
9163 struct localvar_list {
9164         struct localvar_list *next;
9165         struct localvar *lv;
9166 };
9167
9168 static struct localvar_list *localvar_stack;
9169
9170 /*
9171  * Called after a function returns.
9172  * Interrupts must be off.
9173  */
9174 static void
9175 poplocalvars(int keep)
9176 {
9177         struct localvar_list *ll;
9178         struct localvar *lvp, *next;
9179         struct var *vp;
9180
9181         INT_OFF;
9182         ll = localvar_stack;
9183         localvar_stack = ll->next;
9184
9185         next = ll->lv;
9186         free(ll);
9187
9188         while ((lvp = next) != NULL) {
9189                 next = lvp->next;
9190                 vp = lvp->vp;
9191                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9192                 if (keep) {
9193                         int bits = VSTRFIXED;
9194
9195                         if (lvp->flags != VUNSET) {
9196                                 if (vp->var_text == lvp->text)
9197                                         bits |= VTEXTFIXED;
9198                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9199                                         free((char*)lvp->text);
9200                         }
9201
9202                         vp->flags &= ~bits;
9203                         vp->flags |= (lvp->flags & bits);
9204
9205                         if ((vp->flags &
9206                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9207                                 unsetvar(vp->var_text);
9208                 } else if (vp == NULL) {        /* $- saved */
9209                         memcpy(optlist, lvp->text, sizeof(optlist));
9210                         free((char*)lvp->text);
9211                         optschanged();
9212                 } else if (lvp->flags == VUNSET) {
9213                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9214                         unsetvar(vp->var_text);
9215                 } else {
9216                         if (vp->var_func)
9217                                 vp->var_func(var_end(lvp->text));
9218                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9219                                 free((char*)vp->var_text);
9220                         vp->flags = lvp->flags;
9221                         vp->var_text = lvp->text;
9222                 }
9223                 free(lvp);
9224         }
9225         INT_ON;
9226 }
9227
9228 /*
9229  * Create a new localvar environment.
9230  */
9231 static struct localvar_list *
9232 pushlocalvars(void)
9233 {
9234         struct localvar_list *ll;
9235
9236         INT_OFF;
9237         ll = ckzalloc(sizeof(*ll));
9238         /*ll->lv = NULL; - zalloc did it */
9239         ll->next = localvar_stack;
9240         localvar_stack = ll;
9241         INT_ON;
9242
9243         return ll->next;
9244 }
9245
9246 static void
9247 unwindlocalvars(struct localvar_list *stop)
9248 {
9249         while (localvar_stack != stop)
9250                 poplocalvars(0);
9251 }
9252
9253 static int
9254 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9255 {
9256         volatile struct shparam saveparam;
9257         struct jmploc *volatile savehandler;
9258         struct jmploc jmploc;
9259         int e;
9260
9261         saveparam = shellparam;
9262         savehandler = exception_handler;
9263         e = setjmp(jmploc.loc);
9264         if (e) {
9265                 goto funcdone;
9266         }
9267         INT_OFF;
9268         exception_handler = &jmploc;
9269         shellparam.malloced = 0;
9270         func->count++;
9271         funcnest++;
9272         INT_ON;
9273         shellparam.nparam = argc - 1;
9274         shellparam.p = argv + 1;
9275 #if ENABLE_ASH_GETOPTS
9276         shellparam.optind = 1;
9277         shellparam.optoff = -1;
9278 #endif
9279         pushlocalvars();
9280         evaltree(func->n.narg.next, flags & EV_TESTED);
9281         poplocalvars(0);
9282  funcdone:
9283         INT_OFF;
9284         funcnest--;
9285         freefunc(func);
9286         freeparam(&shellparam);
9287         shellparam = saveparam;
9288         exception_handler = savehandler;
9289         INT_ON;
9290         evalskip &= ~SKIPFUNC;
9291         return e;
9292 }
9293
9294 /*
9295  * Make a variable a local variable.  When a variable is made local, it's
9296  * value and flags are saved in a localvar structure.  The saved values
9297  * will be restored when the shell function returns.  We handle the name
9298  * "-" as a special case: it makes changes to "set +-options" local
9299  * (options will be restored on return from the function).
9300  */
9301 static void
9302 mklocal(char *name)
9303 {
9304         struct localvar *lvp;
9305         struct var **vpp;
9306         struct var *vp;
9307         char *eq = strchr(name, '=');
9308
9309         INT_OFF;
9310         /* Cater for duplicate "local". Examples:
9311          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9312          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9313          */
9314         lvp = localvar_stack->lv;
9315         while (lvp) {
9316                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9317                         if (eq)
9318                                 setvareq(name, 0);
9319                         /* else:
9320                          * it's a duplicate "local VAR" declaration, do nothing
9321                          */
9322                         goto ret;
9323                 }
9324                 lvp = lvp->next;
9325         }
9326
9327         lvp = ckzalloc(sizeof(*lvp));
9328         if (LONE_DASH(name)) {
9329                 char *p;
9330                 p = ckmalloc(sizeof(optlist));
9331                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9332                 vp = NULL;
9333         } else {
9334                 vpp = hashvar(name);
9335                 vp = *findvar(vpp, name);
9336                 if (vp == NULL) {
9337                         /* variable did not exist yet */
9338                         if (eq)
9339                                 setvareq(name, VSTRFIXED);
9340                         else
9341                                 setvar(name, NULL, VSTRFIXED);
9342                         vp = *vpp;      /* the new variable */
9343                         lvp->flags = VUNSET;
9344                 } else {
9345                         lvp->text = vp->var_text;
9346                         lvp->flags = vp->flags;
9347                         /* make sure neither "struct var" nor string gets freed
9348                          * during (un)setting:
9349                          */
9350                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9351                         if (eq)
9352                                 setvareq(name, 0);
9353                         else
9354                                 /* "local VAR" unsets VAR: */
9355                                 setvar0(name, NULL);
9356                 }
9357         }
9358         lvp->vp = vp;
9359         lvp->next = localvar_stack->lv;
9360         localvar_stack->lv = lvp;
9361  ret:
9362         INT_ON;
9363 }
9364
9365 /*
9366  * The "local" command.
9367  */
9368 static int FAST_FUNC
9369 localcmd(int argc UNUSED_PARAM, char **argv)
9370 {
9371         char *name;
9372
9373         if (!localvar_stack)
9374                 ash_msg_and_raise_error("not in a function");
9375
9376         argv = argptr;
9377         while ((name = *argv++) != NULL) {
9378                 mklocal(name);
9379         }
9380         return 0;
9381 }
9382
9383 static int FAST_FUNC
9384 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9385 {
9386         return 1;
9387 }
9388
9389 static int FAST_FUNC
9390 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9391 {
9392         return 0;
9393 }
9394
9395 static int FAST_FUNC
9396 execcmd(int argc UNUSED_PARAM, char **argv)
9397 {
9398         optionarg = NULL;
9399         while (nextopt("a:") != '\0')
9400                 /* nextopt() sets optionarg to "-a ARGV0" */;
9401
9402         argv = argptr;
9403         if (argv[0]) {
9404                 char *prog;
9405
9406                 iflag = 0;              /* exit on error */
9407                 mflag = 0;
9408                 optschanged();
9409                 /* We should set up signals for "exec CMD"
9410                  * the same way as for "CMD" without "exec".
9411                  * But optschanged->setinteractive->setsignal
9412                  * still thought we are a root shell. Therefore, for example,
9413                  * SIGQUIT is still set to IGN. Fix it:
9414                  */
9415                 shlvl++;
9416                 setsignal(SIGQUIT);
9417                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9418                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9419                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9420
9421                 prog = argv[0];
9422                 if (optionarg)
9423                         argv[0] = optionarg;
9424                 shellexec(prog, argv, pathval(), 0);
9425                 /* NOTREACHED */
9426         }
9427         return 0;
9428 }
9429
9430 /*
9431  * The return command.
9432  */
9433 static int FAST_FUNC
9434 returncmd(int argc UNUSED_PARAM, char **argv)
9435 {
9436         /*
9437          * If called outside a function, do what ksh does;
9438          * skip the rest of the file.
9439          */
9440         evalskip = SKIPFUNC;
9441         return argv[1] ? number(argv[1]) : exitstatus;
9442 }
9443
9444 /* Forward declarations for builtintab[] */
9445 static int breakcmd(int, char **) FAST_FUNC;
9446 static int dotcmd(int, char **) FAST_FUNC;
9447 static int evalcmd(int, char **, int) FAST_FUNC;
9448 static int exitcmd(int, char **) FAST_FUNC;
9449 static int exportcmd(int, char **) FAST_FUNC;
9450 #if ENABLE_ASH_GETOPTS
9451 static int getoptscmd(int, char **) FAST_FUNC;
9452 #endif
9453 #if ENABLE_ASH_HELP
9454 static int helpcmd(int, char **) FAST_FUNC;
9455 #endif
9456 #if MAX_HISTORY
9457 static int historycmd(int, char **) FAST_FUNC;
9458 #endif
9459 #if ENABLE_FEATURE_SH_MATH
9460 static int letcmd(int, char **) FAST_FUNC;
9461 #endif
9462 static int readcmd(int, char **) FAST_FUNC;
9463 static int setcmd(int, char **) FAST_FUNC;
9464 static int shiftcmd(int, char **) FAST_FUNC;
9465 static int timescmd(int, char **) FAST_FUNC;
9466 static int trapcmd(int, char **) FAST_FUNC;
9467 static int umaskcmd(int, char **) FAST_FUNC;
9468 static int unsetcmd(int, char **) FAST_FUNC;
9469 static int ulimitcmd(int, char **) FAST_FUNC;
9470
9471 #define BUILTIN_NOSPEC          "0"
9472 #define BUILTIN_SPECIAL         "1"
9473 #define BUILTIN_REGULAR         "2"
9474 #define BUILTIN_SPEC_REG        "3"
9475 #define BUILTIN_ASSIGN          "4"
9476 #define BUILTIN_SPEC_ASSG       "5"
9477 #define BUILTIN_REG_ASSG        "6"
9478 #define BUILTIN_SPEC_REG_ASSG   "7"
9479
9480 /* Stubs for calling non-FAST_FUNC's */
9481 #if ENABLE_ASH_ECHO
9482 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9483 #endif
9484 #if ENABLE_ASH_PRINTF
9485 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9486 #endif
9487 #if ENABLE_ASH_TEST || BASH_TEST2
9488 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9489 #endif
9490
9491 /* Keep these in proper order since it is searched via bsearch() */
9492 static const struct builtincmd builtintab[] = {
9493         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9494         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9495 #if ENABLE_ASH_TEST
9496         { BUILTIN_REGULAR       "["       , testcmd    },
9497 #endif
9498 #if BASH_TEST2
9499         { BUILTIN_REGULAR       "[["      , testcmd    },
9500 #endif
9501 #if ENABLE_ASH_ALIAS
9502         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9503 #endif
9504 #if JOBS
9505         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9506 #endif
9507         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9508         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9509         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9510 #if ENABLE_ASH_CMDCMD
9511         { BUILTIN_REGULAR       "command" , commandcmd },
9512 #endif
9513         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9514 #if ENABLE_ASH_ECHO
9515         { BUILTIN_REGULAR       "echo"    , echocmd    },
9516 #endif
9517         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9518         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9519         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9520         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9521         { BUILTIN_REGULAR       "false"   , falsecmd   },
9522 #if JOBS
9523         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9524 #endif
9525 #if ENABLE_ASH_GETOPTS
9526         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9527 #endif
9528         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9529 #if ENABLE_ASH_HELP
9530         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9531 #endif
9532 #if MAX_HISTORY
9533         { BUILTIN_NOSPEC        "history" , historycmd },
9534 #endif
9535 #if JOBS
9536         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9537         { BUILTIN_REGULAR       "kill"    , killcmd    },
9538 #endif
9539 #if ENABLE_FEATURE_SH_MATH
9540         { BUILTIN_NOSPEC        "let"     , letcmd     },
9541 #endif
9542         { BUILTIN_ASSIGN        "local"   , localcmd   },
9543 #if ENABLE_ASH_PRINTF
9544         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9545 #endif
9546         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9547         { BUILTIN_REGULAR       "read"    , readcmd    },
9548         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9549         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9550         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9551         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9552 #if BASH_SOURCE
9553         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9554 #endif
9555 #if ENABLE_ASH_TEST
9556         { BUILTIN_REGULAR       "test"    , testcmd    },
9557 #endif
9558         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9559         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9560         { BUILTIN_REGULAR       "true"    , truecmd    },
9561         { BUILTIN_NOSPEC        "type"    , typecmd    },
9562         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9563         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9564 #if ENABLE_ASH_ALIAS
9565         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9566 #endif
9567         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9568         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9569 };
9570
9571 /* Should match the above table! */
9572 #define COMMANDCMD (builtintab + \
9573         /* . : */       2 + \
9574         /* [ */         1 * ENABLE_ASH_TEST + \
9575         /* [[ */        1 * BASH_TEST2 + \
9576         /* alias */     1 * ENABLE_ASH_ALIAS + \
9577         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9578         /* break cd cddir  */   3)
9579 #define EVALCMD (COMMANDCMD + \
9580         /* command */   1 * ENABLE_ASH_CMDCMD + \
9581         /* continue */  1 + \
9582         /* echo */      1 * ENABLE_ASH_ECHO + \
9583         0)
9584 #define EXECCMD (EVALCMD + \
9585         /* eval */      1)
9586
9587 /*
9588  * Search the table of builtin commands.
9589  */
9590 static int
9591 pstrcmp1(const void *a, const void *b)
9592 {
9593         return strcmp((char*)a, *(char**)b + 1);
9594 }
9595 static struct builtincmd *
9596 find_builtin(const char *name)
9597 {
9598         struct builtincmd *bp;
9599
9600         bp = bsearch(
9601                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9602                 pstrcmp1
9603         );
9604         return bp;
9605 }
9606
9607 /*
9608  * Execute a simple command.
9609  */
9610 static int
9611 isassignment(const char *p)
9612 {
9613         const char *q = endofname(p);
9614         if (p == q)
9615                 return 0;
9616         return *q == '=';
9617 }
9618 static int FAST_FUNC
9619 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9620 {
9621         /* Preserve exitstatus of a previous possible redirection
9622          * as POSIX mandates */
9623         return back_exitstatus;
9624 }
9625 static int
9626 evalcommand(union node *cmd, int flags)
9627 {
9628         static const struct builtincmd null_bltin = {
9629                 "\0\0", bltincmd /* why three NULs? */
9630         };
9631         struct localvar_list *localvar_stop;
9632         struct stackmark smark;
9633         union node *argp;
9634         struct arglist arglist;
9635         struct arglist varlist;
9636         char **argv;
9637         int argc;
9638         const struct strlist *sp;
9639         struct cmdentry cmdentry;
9640         struct job *jp;
9641         char *lastarg;
9642         const char *path;
9643         int spclbltin;
9644         int status;
9645         char **nargv;
9646         struct builtincmd *bcmd;
9647         smallint cmd_is_exec;
9648         smallint pseudovarflag = 0;
9649
9650         /* First expand the arguments. */
9651         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9652         setstackmark(&smark);
9653         localvar_stop = pushlocalvars();
9654         back_exitstatus = 0;
9655
9656         cmdentry.cmdtype = CMDBUILTIN;
9657         cmdentry.u.cmd = &null_bltin;
9658         varlist.lastp = &varlist.list;
9659         *varlist.lastp = NULL;
9660         arglist.lastp = &arglist.list;
9661         *arglist.lastp = NULL;
9662
9663         argc = 0;
9664         if (cmd->ncmd.args) {
9665                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9666                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9667         }
9668
9669         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9670                 struct strlist **spp;
9671
9672                 spp = arglist.lastp;
9673                 if (pseudovarflag && isassignment(argp->narg.text))
9674                         expandarg(argp, &arglist, EXP_VARTILDE);
9675                 else
9676                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9677
9678                 for (sp = *spp; sp; sp = sp->next)
9679                         argc++;
9680         }
9681
9682         /* Reserve one extra spot at the front for shellexec. */
9683         nargv = stalloc(sizeof(char *) * (argc + 2));
9684         argv = ++nargv;
9685         for (sp = arglist.list; sp; sp = sp->next) {
9686                 TRACE(("evalcommand arg: %s\n", sp->text));
9687                 *nargv++ = sp->text;
9688         }
9689         *nargv = NULL;
9690
9691         lastarg = NULL;
9692         if (iflag && funcnest == 0 && argc > 0)
9693                 lastarg = nargv[-1];
9694
9695         preverrout_fd = 2;
9696         expredir(cmd->ncmd.redirect);
9697         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9698
9699         path = vpath.var_text;
9700         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9701                 struct strlist **spp;
9702                 char *p;
9703
9704                 spp = varlist.lastp;
9705                 expandarg(argp, &varlist, EXP_VARTILDE);
9706
9707                 mklocal((*spp)->text);
9708
9709                 /*
9710                  * Modify the command lookup path, if a PATH= assignment
9711                  * is present
9712                  */
9713                 p = (*spp)->text;
9714                 if (varcmp(p, path) == 0)
9715                         path = p;
9716         }
9717
9718         /* Print the command if xflag is set. */
9719         if (xflag) {
9720                 const char *pfx = "";
9721
9722                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9723
9724                 sp = varlist.list;
9725                 while (sp) {
9726                         char *varval = sp->text;
9727                         char *eq = strchrnul(varval, '=');
9728                         if (*eq)
9729                                 eq++;
9730                         fdprintf(preverrout_fd, "%s%.*s%s",
9731                                 pfx,
9732                                 (int)(eq - varval), varval,
9733                                 maybe_single_quote(eq)
9734                         );
9735                         sp = sp->next;
9736                         pfx = " ";
9737                 }
9738
9739                 sp = arglist.list;
9740                 while (sp) {
9741                         fdprintf(preverrout_fd, "%s%s",
9742                                 pfx,
9743                                 /* always quote if matches reserved word: */
9744                                 findkwd(sp->text)
9745                                 ? single_quote(sp->text)
9746                                 : maybe_single_quote(sp->text)
9747                         );
9748                         sp = sp->next;
9749                         pfx = " ";
9750                 }
9751                 safe_write(preverrout_fd, "\n", 1);
9752         }
9753
9754         cmd_is_exec = 0;
9755         spclbltin = -1;
9756
9757         /* Now locate the command. */
9758         if (argc) {
9759                 int cmd_flag = DO_ERR;
9760 #if ENABLE_ASH_CMDCMD
9761                 const char *oldpath = path + 5;
9762 #endif
9763                 path += 5;
9764                 for (;;) {
9765                         find_command(argv[0], &cmdentry, cmd_flag, path);
9766                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9767                                 flush_stdout_stderr();
9768                                 status = 127;
9769                                 goto bail;
9770                         }
9771
9772                         /* implement bltin and command here */
9773                         if (cmdentry.cmdtype != CMDBUILTIN)
9774                                 break;
9775                         if (spclbltin < 0)
9776                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9777                         if (cmdentry.u.cmd == EXECCMD)
9778                                 cmd_is_exec = 1;
9779 #if ENABLE_ASH_CMDCMD
9780                         if (cmdentry.u.cmd == COMMANDCMD) {
9781                                 path = oldpath;
9782                                 nargv = parse_command_args(argv, &path);
9783                                 if (!nargv)
9784                                         break;
9785                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9786                                  * nargv => "PROG". path is updated if -p.
9787                                  */
9788                                 argc -= nargv - argv;
9789                                 argv = nargv;
9790                                 cmd_flag |= DO_NOFUNC;
9791                         } else
9792 #endif
9793                                 break;
9794                 }
9795         }
9796
9797         if (status) {
9798  bail:
9799                 exitstatus = status;
9800
9801                 /* We have a redirection error. */
9802                 if (spclbltin > 0)
9803                         raise_exception(EXERROR);
9804
9805                 goto out;
9806         }
9807
9808         /* Execute the command. */
9809         switch (cmdentry.cmdtype) {
9810         default: {
9811
9812 #if ENABLE_FEATURE_SH_NOFORK
9813 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9814  *     around run_nofork_applet() call.
9815  * (2) Should this check also be done in forkshell()?
9816  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9817  */
9818                 /* find_command() encodes applet_no as (-2 - applet_no) */
9819                 int applet_no = (- cmdentry.u.index - 2);
9820                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9821                         listsetvar(varlist.list, VEXPORT|VSTACK);
9822                         /* run <applet>_main() */
9823                         status = run_nofork_applet(applet_no, argv);
9824                         break;
9825                 }
9826 #endif
9827                 /* Can we avoid forking off? For example, very last command
9828                  * in a script or a subshell does not need forking,
9829                  * we can just exec it.
9830                  */
9831                 if (!(flags & EV_EXIT) || may_have_traps) {
9832                         /* No, forking off a child is necessary */
9833                         INT_OFF;
9834                         get_tty_state();
9835                         jp = makejob(/*cmd,*/ 1);
9836                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9837                                 /* parent */
9838                                 status = waitforjob(jp);
9839                                 INT_ON;
9840                                 TRACE(("forked child exited with %d\n", status));
9841                                 break;
9842                         }
9843                         /* child */
9844                         FORCE_INT_ON;
9845                         /* fall through to exec'ing external program */
9846                 }
9847                 listsetvar(varlist.list, VEXPORT|VSTACK);
9848                 shellexec(argv[0], argv, path, cmdentry.u.index);
9849                 /* NOTREACHED */
9850         } /* default */
9851         case CMDBUILTIN:
9852                 poplocalvars(spclbltin > 0 || argc == 0);
9853                 if (cmd_is_exec && argc > 1)
9854                         listsetvar(varlist.list, VEXPORT);
9855
9856                 /* Tight loop with builtins only:
9857                  * "while kill -0 $child; do true; done"
9858                  * will never exit even if $child died, unless we do this
9859                  * to reap the zombie and make kill detect that it's gone: */
9860                 dowait(DOWAIT_NONBLOCK, NULL);
9861
9862                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9863                         if (exception_type == EXERROR && spclbltin <= 0) {
9864                                 FORCE_INT_ON;
9865                                 goto readstatus;
9866                         }
9867  raise:
9868                         longjmp(exception_handler->loc, 1);
9869                 }
9870                 goto readstatus;
9871
9872         case CMDFUNCTION:
9873                 poplocalvars(1);
9874                 /* See above for the rationale */
9875                 dowait(DOWAIT_NONBLOCK, NULL);
9876                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9877                         goto raise;
9878  readstatus:
9879                 status = exitstatus;
9880                 break;
9881         } /* switch */
9882
9883  out:
9884         if (cmd->ncmd.redirect)
9885                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9886         unwindlocalvars(localvar_stop);
9887         if (lastarg) {
9888                 /* dsl: I think this is intended to be used to support
9889                  * '_' in 'vi' command mode during line editing...
9890                  * However I implemented that within libedit itself.
9891                  */
9892                 setvar0("_", lastarg);
9893         }
9894         popstackmark(&smark);
9895
9896         return status;
9897 }
9898
9899 static int
9900 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9901 {
9902         char *volatile savecmdname;
9903         struct jmploc *volatile savehandler;
9904         struct jmploc jmploc;
9905         int status;
9906         int i;
9907
9908         savecmdname = commandname;
9909         savehandler = exception_handler;
9910         i = setjmp(jmploc.loc);
9911         if (i)
9912                 goto cmddone;
9913         exception_handler = &jmploc;
9914         commandname = argv[0];
9915         argptr = argv + 1;
9916         optptr = NULL;                  /* initialize nextopt */
9917         if (cmd == EVALCMD)
9918                 status = evalcmd(argc, argv, flags);
9919         else
9920                 status = (*cmd->builtin)(argc, argv);
9921         flush_stdout_stderr();
9922         status |= ferror(stdout);
9923         exitstatus = status;
9924  cmddone:
9925         clearerr(stdout);
9926         commandname = savecmdname;
9927         exception_handler = savehandler;
9928
9929         return i;
9930 }
9931
9932 static int
9933 goodname(const char *p)
9934 {
9935         return endofname(p)[0] == '\0';
9936 }
9937
9938
9939 /*
9940  * Search for a command.  This is called before we fork so that the
9941  * location of the command will be available in the parent as well as
9942  * the child.  The check for "goodname" is an overly conservative
9943  * check that the name will not be subject to expansion.
9944  */
9945 static void
9946 prehash(union node *n)
9947 {
9948         struct cmdentry entry;
9949
9950         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9951                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9952 }
9953
9954
9955 /* ============ Builtin commands
9956  *
9957  * Builtin commands whose functions are closely tied to evaluation
9958  * are implemented here.
9959  */
9960
9961 /*
9962  * Handle break and continue commands.  Break, continue, and return are
9963  * all handled by setting the evalskip flag.  The evaluation routines
9964  * above all check this flag, and if it is set they start skipping
9965  * commands rather than executing them.  The variable skipcount is
9966  * the number of loops to break/continue, or the number of function
9967  * levels to return.  (The latter is always 1.)  It should probably
9968  * be an error to break out of more loops than exist, but it isn't
9969  * in the standard shell so we don't make it one here.
9970  */
9971 static int FAST_FUNC
9972 breakcmd(int argc UNUSED_PARAM, char **argv)
9973 {
9974         int n = argv[1] ? number(argv[1]) : 1;
9975
9976         if (n <= 0)
9977                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9978         if (n > loopnest)
9979                 n = loopnest;
9980         if (n > 0) {
9981                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9982                 skipcount = n;
9983         }
9984         return 0;
9985 }
9986
9987
9988 /*
9989  * This implements the input routines used by the parser.
9990  */
9991
9992 enum {
9993         INPUT_PUSH_FILE = 1,
9994         INPUT_NOFILE_OK = 2,
9995 };
9996
9997 static smallint checkkwd;
9998 /* values of checkkwd variable */
9999 #define CHKALIAS        0x1
10000 #define CHKKWD          0x2
10001 #define CHKNL           0x4
10002
10003 /*
10004  * Push a string back onto the input at this current parsefile level.
10005  * We handle aliases this way.
10006  */
10007 #if !ENABLE_ASH_ALIAS
10008 #define pushstring(s, ap) pushstring(s)
10009 #endif
10010 static void
10011 pushstring(char *s, struct alias *ap)
10012 {
10013         struct strpush *sp;
10014         int len;
10015
10016         len = strlen(s);
10017         INT_OFF;
10018         if (g_parsefile->strpush) {
10019                 sp = ckzalloc(sizeof(*sp));
10020                 sp->prev = g_parsefile->strpush;
10021         } else {
10022                 sp = &(g_parsefile->basestrpush);
10023         }
10024         g_parsefile->strpush = sp;
10025         sp->prev_string = g_parsefile->next_to_pgetc;
10026         sp->prev_left_in_line = g_parsefile->left_in_line;
10027         sp->unget = g_parsefile->unget;
10028         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10029 #if ENABLE_ASH_ALIAS
10030         sp->ap = ap;
10031         if (ap) {
10032                 ap->flag |= ALIASINUSE;
10033                 sp->string = s;
10034         }
10035 #endif
10036         g_parsefile->next_to_pgetc = s;
10037         g_parsefile->left_in_line = len;
10038         g_parsefile->unget = 0;
10039         INT_ON;
10040 }
10041
10042 static void
10043 popstring(void)
10044 {
10045         struct strpush *sp = g_parsefile->strpush;
10046
10047         INT_OFF;
10048 #if ENABLE_ASH_ALIAS
10049         if (sp->ap) {
10050                 if (g_parsefile->next_to_pgetc[-1] == ' '
10051                  || g_parsefile->next_to_pgetc[-1] == '\t'
10052                 ) {
10053                         checkkwd |= CHKALIAS;
10054                 }
10055                 if (sp->string != sp->ap->val) {
10056                         free(sp->string);
10057                 }
10058                 sp->ap->flag &= ~ALIASINUSE;
10059                 if (sp->ap->flag & ALIASDEAD) {
10060                         unalias(sp->ap->name);
10061                 }
10062         }
10063 #endif
10064         g_parsefile->next_to_pgetc = sp->prev_string;
10065         g_parsefile->left_in_line = sp->prev_left_in_line;
10066         g_parsefile->unget = sp->unget;
10067         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10068         g_parsefile->strpush = sp->prev;
10069         if (sp != &(g_parsefile->basestrpush))
10070                 free(sp);
10071         INT_ON;
10072 }
10073
10074 static int
10075 preadfd(void)
10076 {
10077         int nr;
10078         char *buf = g_parsefile->buf;
10079
10080         g_parsefile->next_to_pgetc = buf;
10081 #if ENABLE_FEATURE_EDITING
10082  retry:
10083         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10084                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10085         else {
10086                 int timeout = -1;
10087 # if ENABLE_ASH_IDLE_TIMEOUT
10088                 if (iflag) {
10089                         const char *tmout_var = lookupvar("TMOUT");
10090                         if (tmout_var) {
10091                                 timeout = atoi(tmout_var) * 1000;
10092                                 if (timeout <= 0)
10093                                         timeout = -1;
10094                         }
10095                 }
10096 # endif
10097 # if ENABLE_FEATURE_TAB_COMPLETION
10098                 line_input_state->path_lookup = pathval();
10099 # endif
10100                 reinit_unicode_for_ash();
10101                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10102                 if (nr == 0) {
10103                         /* ^C pressed, "convert" to SIGINT */
10104                         write(STDOUT_FILENO, "^C", 2);
10105                         if (trap[SIGINT]) {
10106                                 buf[0] = '\n';
10107                                 buf[1] = '\0';
10108                                 raise(SIGINT);
10109                                 return 1;
10110                         }
10111                         exitstatus = 128 + SIGINT;
10112                         bb_putchar('\n');
10113                         goto retry;
10114                 }
10115                 if (nr < 0) {
10116                         if (errno == 0) {
10117                                 /* Ctrl+D pressed */
10118                                 nr = 0;
10119                         }
10120 # if ENABLE_ASH_IDLE_TIMEOUT
10121                         else if (errno == EAGAIN && timeout > 0) {
10122                                 puts("\007timed out waiting for input: auto-logout");
10123                                 exitshell();
10124                         }
10125 # endif
10126                 }
10127         }
10128 #else
10129         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10130 #endif
10131
10132 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10133         if (nr < 0) {
10134                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10135                         int flags = fcntl(0, F_GETFL);
10136                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10137                                 flags &= ~O_NONBLOCK;
10138                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10139                                         out2str("sh: turning off NDELAY mode\n");
10140                                         goto retry;
10141                                 }
10142                         }
10143                 }
10144         }
10145 #endif
10146         return nr;
10147 }
10148
10149 /*
10150  * Refill the input buffer and return the next input character:
10151  *
10152  * 1) If a string was pushed back on the input, pop it;
10153  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10154  *    or we are reading from a string so we can't refill the buffer,
10155  *    return EOF.
10156  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10157  * 4) Process input up to the next newline, deleting nul characters.
10158  */
10159 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10160 #define pgetc_debug(...) ((void)0)
10161 static int pgetc(void);
10162 static int
10163 preadbuffer(void)
10164 {
10165         char *q;
10166         int more;
10167
10168         if (g_parsefile->strpush) {
10169 #if ENABLE_ASH_ALIAS
10170                 if (g_parsefile->left_in_line == -1
10171                  && g_parsefile->strpush->ap
10172                  && g_parsefile->next_to_pgetc[-1] != ' '
10173                  && g_parsefile->next_to_pgetc[-1] != '\t'
10174                 ) {
10175                         pgetc_debug("preadbuffer PEOA");
10176                         return PEOA;
10177                 }
10178 #endif
10179                 popstring();
10180                 return pgetc();
10181         }
10182         /* on both branches above g_parsefile->left_in_line < 0.
10183          * "pgetc" needs refilling.
10184          */
10185
10186         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10187          * pungetc() may increment it a few times.
10188          * Assuming it won't increment it to less than -90.
10189          */
10190         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10191                 pgetc_debug("preadbuffer PEOF1");
10192                 /* even in failure keep left_in_line and next_to_pgetc
10193                  * in lock step, for correct multi-layer pungetc.
10194                  * left_in_line was decremented before preadbuffer(),
10195                  * must inc next_to_pgetc: */
10196                 g_parsefile->next_to_pgetc++;
10197                 return PEOF;
10198         }
10199
10200         more = g_parsefile->left_in_buffer;
10201         if (more <= 0) {
10202                 flush_stdout_stderr();
10203  again:
10204                 more = preadfd();
10205                 if (more <= 0) {
10206                         /* don't try reading again */
10207                         g_parsefile->left_in_line = -99;
10208                         pgetc_debug("preadbuffer PEOF2");
10209                         g_parsefile->next_to_pgetc++;
10210                         return PEOF;
10211                 }
10212         }
10213
10214         /* Find out where's the end of line.
10215          * Set g_parsefile->left_in_line
10216          * and g_parsefile->left_in_buffer acordingly.
10217          * NUL chars are deleted.
10218          */
10219         q = g_parsefile->next_to_pgetc;
10220         for (;;) {
10221                 char c;
10222
10223                 more--;
10224
10225                 c = *q;
10226                 if (c == '\0') {
10227                         memmove(q, q + 1, more);
10228                 } else {
10229                         q++;
10230                         if (c == '\n') {
10231                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10232                                 break;
10233                         }
10234                 }
10235
10236                 if (more <= 0) {
10237                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10238                         if (g_parsefile->left_in_line < 0)
10239                                 goto again;
10240                         break;
10241                 }
10242         }
10243         g_parsefile->left_in_buffer = more;
10244
10245         if (vflag) {
10246                 char save = *q;
10247                 *q = '\0';
10248                 out2str(g_parsefile->next_to_pgetc);
10249                 *q = save;
10250         }
10251
10252         pgetc_debug("preadbuffer at %d:%p'%s'",
10253                         g_parsefile->left_in_line,
10254                         g_parsefile->next_to_pgetc,
10255                         g_parsefile->next_to_pgetc);
10256         return (unsigned char)*g_parsefile->next_to_pgetc++;
10257 }
10258
10259 static void
10260 nlprompt(void)
10261 {
10262         g_parsefile->linno++;
10263         setprompt_if(doprompt, 2);
10264 }
10265 static void
10266 nlnoprompt(void)
10267 {
10268         g_parsefile->linno++;
10269         needprompt = doprompt;
10270 }
10271
10272 static int
10273 pgetc(void)
10274 {
10275         int c;
10276
10277         pgetc_debug("pgetc at %d:%p'%s'",
10278                         g_parsefile->left_in_line,
10279                         g_parsefile->next_to_pgetc,
10280                         g_parsefile->next_to_pgetc);
10281         if (g_parsefile->unget)
10282                 return g_parsefile->lastc[--g_parsefile->unget];
10283
10284         if (--g_parsefile->left_in_line >= 0)
10285                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10286         else
10287                 c = preadbuffer();
10288
10289         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10290         g_parsefile->lastc[0] = c;
10291
10292         return c;
10293 }
10294
10295 #if ENABLE_ASH_ALIAS
10296 static int
10297 pgetc_without_PEOA(void)
10298 {
10299         int c;
10300         do {
10301                 pgetc_debug("pgetc at %d:%p'%s'",
10302                                 g_parsefile->left_in_line,
10303                                 g_parsefile->next_to_pgetc,
10304                                 g_parsefile->next_to_pgetc);
10305                 c = pgetc();
10306         } while (c == PEOA);
10307         return c;
10308 }
10309 #else
10310 # define pgetc_without_PEOA() pgetc()
10311 #endif
10312
10313 /*
10314  * Read a line from the script.
10315  */
10316 static char *
10317 pfgets(char *line, int len)
10318 {
10319         char *p = line;
10320         int nleft = len;
10321         int c;
10322
10323         while (--nleft > 0) {
10324                 c = pgetc_without_PEOA();
10325                 if (c == PEOF) {
10326                         if (p == line)
10327                                 return NULL;
10328                         break;
10329                 }
10330                 *p++ = c;
10331                 if (c == '\n')
10332                         break;
10333         }
10334         *p = '\0';
10335         return line;
10336 }
10337
10338 /*
10339  * Undo a call to pgetc.  Only two characters may be pushed back.
10340  * PEOF may be pushed back.
10341  */
10342 static void
10343 pungetc(void)
10344 {
10345         g_parsefile->unget++;
10346 }
10347
10348 /* This one eats backslash+newline */
10349 static int
10350 pgetc_eatbnl(void)
10351 {
10352         int c;
10353
10354         while ((c = pgetc()) == '\\') {
10355                 if (pgetc() != '\n') {
10356                         pungetc();
10357                         break;
10358                 }
10359
10360                 nlprompt();
10361         }
10362
10363         return c;
10364 }
10365
10366 /*
10367  * To handle the "." command, a stack of input files is used.  Pushfile
10368  * adds a new entry to the stack and popfile restores the previous level.
10369  */
10370 static void
10371 pushfile(void)
10372 {
10373         struct parsefile *pf;
10374
10375         pf = ckzalloc(sizeof(*pf));
10376         pf->prev = g_parsefile;
10377         pf->pf_fd = -1;
10378         /*pf->strpush = NULL; - ckzalloc did it */
10379         /*pf->basestrpush.prev = NULL;*/
10380         /*pf->unget = 0;*/
10381         g_parsefile = pf;
10382 }
10383
10384 static void
10385 popfile(void)
10386 {
10387         struct parsefile *pf = g_parsefile;
10388
10389         if (pf == &basepf)
10390                 return;
10391
10392         INT_OFF;
10393         if (pf->pf_fd >= 0)
10394                 close(pf->pf_fd);
10395         free(pf->buf);
10396         while (pf->strpush)
10397                 popstring();
10398         g_parsefile = pf->prev;
10399         free(pf);
10400         INT_ON;
10401 }
10402
10403 /*
10404  * Return to top level.
10405  */
10406 static void
10407 popallfiles(void)
10408 {
10409         while (g_parsefile != &basepf)
10410                 popfile();
10411 }
10412
10413 /*
10414  * Close the file(s) that the shell is reading commands from.  Called
10415  * after a fork is done.
10416  */
10417 static void
10418 closescript(void)
10419 {
10420         popallfiles();
10421         if (g_parsefile->pf_fd > 0) {
10422                 close(g_parsefile->pf_fd);
10423                 g_parsefile->pf_fd = 0;
10424         }
10425 }
10426
10427 /*
10428  * Like setinputfile, but takes an open file descriptor.  Call this with
10429  * interrupts off.
10430  */
10431 static void
10432 setinputfd(int fd, int push)
10433 {
10434         if (push) {
10435                 pushfile();
10436                 g_parsefile->buf = NULL;
10437         }
10438         g_parsefile->pf_fd = fd;
10439         if (g_parsefile->buf == NULL)
10440                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10441         g_parsefile->left_in_buffer = 0;
10442         g_parsefile->left_in_line = 0;
10443         g_parsefile->linno = 1;
10444 }
10445
10446 /*
10447  * Set the input to take input from a file.  If push is set, push the
10448  * old input onto the stack first.
10449  */
10450 static int
10451 setinputfile(const char *fname, int flags)
10452 {
10453         int fd;
10454
10455         INT_OFF;
10456         fd = open(fname, O_RDONLY);
10457         if (fd < 0) {
10458                 if (flags & INPUT_NOFILE_OK)
10459                         goto out;
10460                 exitstatus = 127;
10461                 ash_msg_and_raise_error("can't open '%s'", fname);
10462         }
10463         if (fd < 10)
10464                 fd = savefd(fd);
10465         else
10466                 close_on_exec_on(fd);
10467         setinputfd(fd, flags & INPUT_PUSH_FILE);
10468  out:
10469         INT_ON;
10470         return fd;
10471 }
10472
10473 /*
10474  * Like setinputfile, but takes input from a string.
10475  */
10476 static void
10477 setinputstring(char *string)
10478 {
10479         INT_OFF;
10480         pushfile();
10481         g_parsefile->next_to_pgetc = string;
10482         g_parsefile->left_in_line = strlen(string);
10483         g_parsefile->buf = NULL;
10484         g_parsefile->linno = 1;
10485         INT_ON;
10486 }
10487
10488
10489 /*
10490  * Routines to check for mail.
10491  */
10492
10493 #if ENABLE_ASH_MAIL
10494
10495 /* Hash of mtimes of mailboxes */
10496 static unsigned mailtime_hash;
10497 /* Set if MAIL or MAILPATH is changed. */
10498 static smallint mail_var_path_changed;
10499
10500 /*
10501  * Print appropriate message(s) if mail has arrived.
10502  * If mail_var_path_changed is set,
10503  * then the value of MAIL has mail_var_path_changed,
10504  * so we just update the values.
10505  */
10506 static void
10507 chkmail(void)
10508 {
10509         const char *mpath;
10510         char *p;
10511         char *q;
10512         unsigned new_hash;
10513         struct stackmark smark;
10514         struct stat statb;
10515
10516         setstackmark(&smark);
10517         mpath = mpathset() ? mpathval() : mailval();
10518         new_hash = 0;
10519         for (;;) {
10520                 p = path_advance(&mpath, nullstr);
10521                 if (p == NULL)
10522                         break;
10523                 if (*p == '\0')
10524                         continue;
10525                 for (q = p; *q; q++)
10526                         continue;
10527 #if DEBUG
10528                 if (q[-1] != '/')
10529                         abort();
10530 #endif
10531                 q[-1] = '\0';                   /* delete trailing '/' */
10532                 if (stat(p, &statb) < 0) {
10533                         continue;
10534                 }
10535                 /* Very simplistic "hash": just a sum of all mtimes */
10536                 new_hash += (unsigned)statb.st_mtime;
10537         }
10538         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10539                 if (mailtime_hash != 0)
10540                         out2str("you have mail\n");
10541                 mailtime_hash = new_hash;
10542         }
10543         mail_var_path_changed = 0;
10544         popstackmark(&smark);
10545 }
10546
10547 static void FAST_FUNC
10548 changemail(const char *val UNUSED_PARAM)
10549 {
10550         mail_var_path_changed = 1;
10551 }
10552
10553 #endif /* ASH_MAIL */
10554
10555
10556 /* ============ ??? */
10557
10558 /*
10559  * Set the shell parameters.
10560  */
10561 static void
10562 setparam(char **argv)
10563 {
10564         char **newparam;
10565         char **ap;
10566         int nparam;
10567
10568         for (nparam = 0; argv[nparam]; nparam++)
10569                 continue;
10570         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10571         while (*argv) {
10572                 *ap++ = ckstrdup(*argv++);
10573         }
10574         *ap = NULL;
10575         freeparam(&shellparam);
10576         shellparam.malloced = 1;
10577         shellparam.nparam = nparam;
10578         shellparam.p = newparam;
10579 #if ENABLE_ASH_GETOPTS
10580         shellparam.optind = 1;
10581         shellparam.optoff = -1;
10582 #endif
10583 }
10584
10585 /*
10586  * Process shell options.  The global variable argptr contains a pointer
10587  * to the argument list; we advance it past the options.
10588  *
10589  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10590  * For a non-interactive shell, an error condition encountered
10591  * by a special built-in ... shall cause the shell to write a diagnostic message
10592  * to standard error and exit as shown in the following table:
10593  * Error                                           Special Built-In
10594  * ...
10595  * Utility syntax error (option or operand error)  Shall exit
10596  * ...
10597  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10598  * we see that bash does not do that (set "finishes" with error code 1 instead,
10599  * and shell continues), and people rely on this behavior!
10600  * Testcase:
10601  * set -o barfoo 2>/dev/null
10602  * echo $?
10603  *
10604  * Oh well. Let's mimic that.
10605  */
10606 static int
10607 plus_minus_o(char *name, int val)
10608 {
10609         int i;
10610
10611         if (name) {
10612                 for (i = 0; i < NOPTS; i++) {
10613                         if (strcmp(name, optnames(i)) == 0) {
10614                                 optlist[i] = val;
10615                                 return 0;
10616                         }
10617                 }
10618                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10619                 return 1;
10620         }
10621         for (i = 0; i < NOPTS; i++) {
10622                 if (val) {
10623                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10624                 } else {
10625                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10626                 }
10627         }
10628         return 0;
10629 }
10630 static void
10631 setoption(int flag, int val)
10632 {
10633         int i;
10634
10635         for (i = 0; i < NOPTS; i++) {
10636                 if (optletters(i) == flag) {
10637                         optlist[i] = val;
10638                         return;
10639                 }
10640         }
10641         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10642         /* NOTREACHED */
10643 }
10644 static int
10645 options(int cmdline)
10646 {
10647         char *p;
10648         int val;
10649         int c;
10650
10651         if (cmdline)
10652                 minusc = NULL;
10653         while ((p = *argptr) != NULL) {
10654                 c = *p++;
10655                 if (c != '-' && c != '+')
10656                         break;
10657                 argptr++;
10658                 val = 0; /* val = 0 if c == '+' */
10659                 if (c == '-') {
10660                         val = 1;
10661                         if (p[0] == '\0' || LONE_DASH(p)) {
10662                                 if (!cmdline) {
10663                                         /* "-" means turn off -x and -v */
10664                                         if (p[0] == '\0')
10665                                                 xflag = vflag = 0;
10666                                         /* "--" means reset params */
10667                                         else if (*argptr == NULL)
10668                                                 setparam(argptr);
10669                                 }
10670                                 break;    /* "-" or "--" terminates options */
10671                         }
10672                 }
10673                 /* first char was + or - */
10674                 while ((c = *p++) != '\0') {
10675                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10676                         if (c == 'c' && cmdline) {
10677                                 minusc = p;     /* command is after shell args */
10678                         } else if (c == 'o') {
10679                                 if (plus_minus_o(*argptr, val)) {
10680                                         /* it already printed err message */
10681                                         return 1; /* error */
10682                                 }
10683                                 if (*argptr)
10684                                         argptr++;
10685                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10686                                 isloginsh = 1;
10687                         /* bash does not accept +-login, we also won't */
10688                         } else if (cmdline && val && (c == '-')) { /* long options */
10689                                 if (strcmp(p, "login") == 0)
10690                                         isloginsh = 1;
10691                                 break;
10692                         } else {
10693                                 setoption(c, val);
10694                         }
10695                 }
10696         }
10697         return 0;
10698 }
10699
10700 /*
10701  * The shift builtin command.
10702  */
10703 static int FAST_FUNC
10704 shiftcmd(int argc UNUSED_PARAM, char **argv)
10705 {
10706         int n;
10707         char **ap1, **ap2;
10708
10709         n = 1;
10710         if (argv[1])
10711                 n = number(argv[1]);
10712         if (n > shellparam.nparam)
10713                 n = 0; /* bash compat, was = shellparam.nparam; */
10714         INT_OFF;
10715         shellparam.nparam -= n;
10716         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10717                 if (shellparam.malloced)
10718                         free(*ap1);
10719         }
10720         ap2 = shellparam.p;
10721         while ((*ap2++ = *ap1++) != NULL)
10722                 continue;
10723 #if ENABLE_ASH_GETOPTS
10724         shellparam.optind = 1;
10725         shellparam.optoff = -1;
10726 #endif
10727         INT_ON;
10728         return 0;
10729 }
10730
10731 /*
10732  * POSIX requires that 'set' (but not export or readonly) output the
10733  * variables in lexicographic order - by the locale's collating order (sigh).
10734  * Maybe we could keep them in an ordered balanced binary tree
10735  * instead of hashed lists.
10736  * For now just roll 'em through qsort for printing...
10737  */
10738 static int
10739 showvars(const char *sep_prefix, int on, int off)
10740 {
10741         const char *sep;
10742         char **ep, **epend;
10743
10744         ep = listvars(on, off, &epend);
10745         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10746
10747         sep = *sep_prefix ? " " : sep_prefix;
10748
10749         for (; ep < epend; ep++) {
10750                 const char *p;
10751                 const char *q;
10752
10753                 p = strchrnul(*ep, '=');
10754                 q = nullstr;
10755                 if (*p)
10756                         q = single_quote(++p);
10757                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10758         }
10759         return 0;
10760 }
10761
10762 /*
10763  * The set command builtin.
10764  */
10765 static int FAST_FUNC
10766 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10767 {
10768         int retval;
10769
10770         if (!argv[1])
10771                 return showvars(nullstr, 0, VUNSET);
10772
10773         INT_OFF;
10774         retval = options(/*cmdline:*/ 0);
10775         if (retval == 0) { /* if no parse error... */
10776                 optschanged();
10777                 if (*argptr != NULL) {
10778                         setparam(argptr);
10779                 }
10780         }
10781         INT_ON;
10782         return retval;
10783 }
10784
10785 #if ENABLE_ASH_RANDOM_SUPPORT
10786 static void FAST_FUNC
10787 change_random(const char *value)
10788 {
10789         uint32_t t;
10790
10791         if (value == NULL) {
10792                 /* "get", generate */
10793                 t = next_random(&random_gen);
10794                 /* set without recursion */
10795                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10796                 vrandom.flags &= ~VNOFUNC;
10797         } else {
10798                 /* set/reset */
10799                 t = strtoul(value, NULL, 10);
10800                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10801         }
10802 }
10803 #endif
10804
10805 #if ENABLE_ASH_GETOPTS
10806 static int
10807 getopts(char *optstr, char *optvar, char **optfirst)
10808 {
10809         char *p, *q;
10810         char c = '?';
10811         int done = 0;
10812         char sbuf[2];
10813         char **optnext;
10814         int ind = shellparam.optind;
10815         int off = shellparam.optoff;
10816
10817         sbuf[1] = '\0';
10818
10819         shellparam.optind = -1;
10820         optnext = optfirst + ind - 1;
10821
10822         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10823                 p = NULL;
10824         else
10825                 p = optnext[-1] + off;
10826         if (p == NULL || *p == '\0') {
10827                 /* Current word is done, advance */
10828                 p = *optnext;
10829                 if (p == NULL || *p != '-' || *++p == '\0') {
10830  atend:
10831                         p = NULL;
10832                         done = 1;
10833                         goto out;
10834                 }
10835                 optnext++;
10836                 if (LONE_DASH(p))        /* check for "--" */
10837                         goto atend;
10838         }
10839
10840         c = *p++;
10841         for (q = optstr; *q != c;) {
10842                 if (*q == '\0') {
10843                         if (optstr[0] == ':') {
10844                                 sbuf[0] = c;
10845                                 /*sbuf[1] = '\0'; - already is */
10846                                 setvar0("OPTARG", sbuf);
10847                         } else {
10848                                 fprintf(stderr, "Illegal option -%c\n", c);
10849                                 unsetvar("OPTARG");
10850                         }
10851                         c = '?';
10852                         goto out;
10853                 }
10854                 if (*++q == ':')
10855                         q++;
10856         }
10857
10858         if (*++q == ':') {
10859                 if (*p == '\0' && (p = *optnext) == NULL) {
10860                         if (optstr[0] == ':') {
10861                                 sbuf[0] = c;
10862                                 /*sbuf[1] = '\0'; - already is */
10863                                 setvar0("OPTARG", sbuf);
10864                                 c = ':';
10865                         } else {
10866                                 fprintf(stderr, "No arg for -%c option\n", c);
10867                                 unsetvar("OPTARG");
10868                                 c = '?';
10869                         }
10870                         goto out;
10871                 }
10872
10873                 if (p == *optnext)
10874                         optnext++;
10875                 setvar0("OPTARG", p);
10876                 p = NULL;
10877         } else
10878                 setvar0("OPTARG", nullstr);
10879  out:
10880         ind = optnext - optfirst + 1;
10881         setvar("OPTIND", itoa(ind), VNOFUNC);
10882         sbuf[0] = c;
10883         /*sbuf[1] = '\0'; - already is */
10884         setvar0(optvar, sbuf);
10885
10886         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10887         shellparam.optind = ind;
10888
10889         return done;
10890 }
10891
10892 /*
10893  * The getopts builtin.  Shellparam.optnext points to the next argument
10894  * to be processed.  Shellparam.optptr points to the next character to
10895  * be processed in the current argument.  If shellparam.optnext is NULL,
10896  * then it's the first time getopts has been called.
10897  */
10898 static int FAST_FUNC
10899 getoptscmd(int argc, char **argv)
10900 {
10901         char **optbase;
10902
10903         if (argc < 3)
10904                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10905         if (argc == 3) {
10906                 optbase = shellparam.p;
10907                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10908                         shellparam.optind = 1;
10909                         shellparam.optoff = -1;
10910                 }
10911         } else {
10912                 optbase = &argv[3];
10913                 if ((unsigned)shellparam.optind > argc - 2) {
10914                         shellparam.optind = 1;
10915                         shellparam.optoff = -1;
10916                 }
10917         }
10918
10919         return getopts(argv[1], argv[2], optbase);
10920 }
10921 #endif /* ASH_GETOPTS */
10922
10923
10924 /* ============ Shell parser */
10925
10926 struct heredoc {
10927         struct heredoc *next;   /* next here document in list */
10928         union node *here;       /* redirection node */
10929         char *eofmark;          /* string indicating end of input */
10930         smallint striptabs;     /* if set, strip leading tabs */
10931 };
10932
10933 static smallint tokpushback;           /* last token pushed back */
10934 static smallint quoteflag;             /* set if (part of) last token was quoted */
10935 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10936 static struct heredoc *heredoclist;    /* list of here documents to read */
10937 static char *wordtext;                 /* text of last word returned by readtoken */
10938 static struct nodelist *backquotelist;
10939 static union node *redirnode;
10940 static struct heredoc *heredoc;
10941
10942 static const char *
10943 tokname(char *buf, int tok)
10944 {
10945         if (tok < TSEMI)
10946                 return tokname_array[tok];
10947         sprintf(buf, "\"%s\"", tokname_array[tok]);
10948         return buf;
10949 }
10950
10951 /* raise_error_unexpected_syntax:
10952  * Called when an unexpected token is read during the parse.  The argument
10953  * is the token that is expected, or -1 if more than one type of token can
10954  * occur at this point.
10955  */
10956 static void raise_error_unexpected_syntax(int) NORETURN;
10957 static void
10958 raise_error_unexpected_syntax(int token)
10959 {
10960         char msg[64];
10961         char buf[16];
10962         int l;
10963
10964         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10965         if (token >= 0)
10966                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10967         raise_error_syntax(msg);
10968         /* NOTREACHED */
10969 }
10970
10971 #define EOFMARKLEN 79
10972
10973 /* parsing is heavily cross-recursive, need these forward decls */
10974 static union node *andor(void);
10975 static union node *pipeline(void);
10976 static union node *parse_command(void);
10977 static void parseheredoc(void);
10978 static int peektoken(void);
10979 static int readtoken(void);
10980
10981 static union node *
10982 list(int nlflag)
10983 {
10984         union node *n1, *n2, *n3;
10985         int tok;
10986
10987         n1 = NULL;
10988         for (;;) {
10989                 switch (peektoken()) {
10990                 case TNL:
10991                         if (!(nlflag & 1))
10992                                 break;
10993                         parseheredoc();
10994                         return n1;
10995
10996                 case TEOF:
10997                         if (!n1 && (nlflag & 1))
10998                                 n1 = NODE_EOF;
10999                         parseheredoc();
11000                         return n1;
11001                 }
11002
11003                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11004                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11005                         return n1;
11006                 nlflag |= 2;
11007
11008                 n2 = andor();
11009                 tok = readtoken();
11010                 if (tok == TBACKGND) {
11011                         if (n2->type == NPIPE) {
11012                                 n2->npipe.pipe_backgnd = 1;
11013                         } else {
11014                                 if (n2->type != NREDIR) {
11015                                         n3 = stzalloc(sizeof(struct nredir));
11016                                         n3->nredir.n = n2;
11017                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11018                                         n2 = n3;
11019                                 }
11020                                 n2->type = NBACKGND;
11021                         }
11022                 }
11023                 if (n1 == NULL) {
11024                         n1 = n2;
11025                 } else {
11026                         n3 = stzalloc(sizeof(struct nbinary));
11027                         n3->type = NSEMI;
11028                         n3->nbinary.ch1 = n1;
11029                         n3->nbinary.ch2 = n2;
11030                         n1 = n3;
11031                 }
11032                 switch (tok) {
11033                 case TNL:
11034                 case TEOF:
11035                         tokpushback = 1;
11036                         /* fall through */
11037                 case TBACKGND:
11038                 case TSEMI:
11039                         break;
11040                 default:
11041                         if ((nlflag & 1))
11042                                 raise_error_unexpected_syntax(-1);
11043                         tokpushback = 1;
11044                         return n1;
11045                 }
11046         }
11047 }
11048
11049 static union node *
11050 andor(void)
11051 {
11052         union node *n1, *n2, *n3;
11053         int t;
11054
11055         n1 = pipeline();
11056         for (;;) {
11057                 t = readtoken();
11058                 if (t == TAND) {
11059                         t = NAND;
11060                 } else if (t == TOR) {
11061                         t = NOR;
11062                 } else {
11063                         tokpushback = 1;
11064                         return n1;
11065                 }
11066                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11067                 n2 = pipeline();
11068                 n3 = stzalloc(sizeof(struct nbinary));
11069                 n3->type = t;
11070                 n3->nbinary.ch1 = n1;
11071                 n3->nbinary.ch2 = n2;
11072                 n1 = n3;
11073         }
11074 }
11075
11076 static union node *
11077 pipeline(void)
11078 {
11079         union node *n1, *n2, *pipenode;
11080         struct nodelist *lp, *prev;
11081         int negate;
11082
11083         negate = 0;
11084         TRACE(("pipeline: entered\n"));
11085         if (readtoken() == TNOT) {
11086                 negate = !negate;
11087                 checkkwd = CHKKWD | CHKALIAS;
11088         } else
11089                 tokpushback = 1;
11090         n1 = parse_command();
11091         if (readtoken() == TPIPE) {
11092                 pipenode = stzalloc(sizeof(struct npipe));
11093                 pipenode->type = NPIPE;
11094                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11095                 lp = stzalloc(sizeof(struct nodelist));
11096                 pipenode->npipe.cmdlist = lp;
11097                 lp->n = n1;
11098                 do {
11099                         prev = lp;
11100                         lp = stzalloc(sizeof(struct nodelist));
11101                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11102                         lp->n = parse_command();
11103                         prev->next = lp;
11104                 } while (readtoken() == TPIPE);
11105                 lp->next = NULL;
11106                 n1 = pipenode;
11107         }
11108         tokpushback = 1;
11109         if (negate) {
11110                 n2 = stzalloc(sizeof(struct nnot));
11111                 n2->type = NNOT;
11112                 n2->nnot.com = n1;
11113                 return n2;
11114         }
11115         return n1;
11116 }
11117
11118 static union node *
11119 makename(void)
11120 {
11121         union node *n;
11122
11123         n = stzalloc(sizeof(struct narg));
11124         n->type = NARG;
11125         /*n->narg.next = NULL; - stzalloc did it */
11126         n->narg.text = wordtext;
11127         n->narg.backquote = backquotelist;
11128         return n;
11129 }
11130
11131 static void
11132 fixredir(union node *n, const char *text, int err)
11133 {
11134         int fd;
11135
11136         TRACE(("Fix redir %s %d\n", text, err));
11137         if (!err)
11138                 n->ndup.vname = NULL;
11139
11140         fd = bb_strtou(text, NULL, 10);
11141         if (!errno && fd >= 0)
11142                 n->ndup.dupfd = fd;
11143         else if (LONE_DASH(text))
11144                 n->ndup.dupfd = -1;
11145         else {
11146                 if (err)
11147                         raise_error_syntax("bad fd number");
11148                 n->ndup.vname = makename();
11149         }
11150 }
11151
11152 /*
11153  * Returns true if the text contains nothing to expand (no dollar signs
11154  * or backquotes).
11155  */
11156 static int
11157 noexpand(const char *text)
11158 {
11159         unsigned char c;
11160
11161         while ((c = *text++) != '\0') {
11162                 if (c == CTLQUOTEMARK)
11163                         continue;
11164                 if (c == CTLESC)
11165                         text++;
11166                 else if (SIT(c, BASESYNTAX) == CCTL)
11167                         return 0;
11168         }
11169         return 1;
11170 }
11171
11172 static void
11173 parsefname(void)
11174 {
11175         union node *n = redirnode;
11176
11177         if (readtoken() != TWORD)
11178                 raise_error_unexpected_syntax(-1);
11179         if (n->type == NHERE) {
11180                 struct heredoc *here = heredoc;
11181                 struct heredoc *p;
11182                 int i;
11183
11184                 if (quoteflag == 0)
11185                         n->type = NXHERE;
11186                 TRACE(("Here document %d\n", n->type));
11187                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11188                         raise_error_syntax("illegal eof marker for << redirection");
11189                 rmescapes(wordtext, 0);
11190                 here->eofmark = wordtext;
11191                 here->next = NULL;
11192                 if (heredoclist == NULL)
11193                         heredoclist = here;
11194                 else {
11195                         for (p = heredoclist; p->next; p = p->next)
11196                                 continue;
11197                         p->next = here;
11198                 }
11199         } else if (n->type == NTOFD || n->type == NFROMFD) {
11200                 fixredir(n, wordtext, 0);
11201         } else {
11202                 n->nfile.fname = makename();
11203         }
11204 }
11205
11206 static union node *
11207 simplecmd(void)
11208 {
11209         union node *args, **app;
11210         union node *n = NULL;
11211         union node *vars, **vpp;
11212         union node **rpp, *redir;
11213         int savecheckkwd;
11214 #if BASH_TEST2
11215         smallint double_brackets_flag = 0;
11216 #endif
11217         IF_BASH_FUNCTION(smallint function_flag = 0;)
11218
11219         args = NULL;
11220         app = &args;
11221         vars = NULL;
11222         vpp = &vars;
11223         redir = NULL;
11224         rpp = &redir;
11225
11226         savecheckkwd = CHKALIAS;
11227         for (;;) {
11228                 int t;
11229                 checkkwd = savecheckkwd;
11230                 t = readtoken();
11231                 switch (t) {
11232 #if BASH_FUNCTION
11233                 case TFUNCTION:
11234                         if (peektoken() != TWORD)
11235                                 raise_error_unexpected_syntax(TWORD);
11236                         function_flag = 1;
11237                         break;
11238 #endif
11239 #if BASH_TEST2
11240                 case TAND: /* "&&" */
11241                 case TOR: /* "||" */
11242                         if (!double_brackets_flag) {
11243                                 tokpushback = 1;
11244                                 goto out;
11245                         }
11246                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11247 #endif
11248                 case TWORD:
11249                         n = stzalloc(sizeof(struct narg));
11250                         n->type = NARG;
11251                         /*n->narg.next = NULL; - stzalloc did it */
11252                         n->narg.text = wordtext;
11253 #if BASH_TEST2
11254                         if (strcmp("[[", wordtext) == 0)
11255                                 double_brackets_flag = 1;
11256                         else if (strcmp("]]", wordtext) == 0)
11257                                 double_brackets_flag = 0;
11258 #endif
11259                         n->narg.backquote = backquotelist;
11260                         if (savecheckkwd && isassignment(wordtext)) {
11261                                 *vpp = n;
11262                                 vpp = &n->narg.next;
11263                         } else {
11264                                 *app = n;
11265                                 app = &n->narg.next;
11266                                 savecheckkwd = 0;
11267                         }
11268 #if BASH_FUNCTION
11269                         if (function_flag) {
11270                                 checkkwd = CHKNL | CHKKWD;
11271                                 switch (peektoken()) {
11272                                 case TBEGIN:
11273                                 case TIF:
11274                                 case TCASE:
11275                                 case TUNTIL:
11276                                 case TWHILE:
11277                                 case TFOR:
11278                                         goto do_func;
11279                                 case TLP:
11280                                         function_flag = 0;
11281                                         break;
11282                                 case TWORD:
11283                                         if (strcmp("[[", wordtext) == 0)
11284                                                 goto do_func;
11285                                         /* fall through */
11286                                 default:
11287                                         raise_error_unexpected_syntax(-1);
11288                                 }
11289                         }
11290 #endif
11291                         break;
11292                 case TREDIR:
11293                         *rpp = n = redirnode;
11294                         rpp = &n->nfile.next;
11295                         parsefname();   /* read name of redirection file */
11296                         break;
11297                 case TLP:
11298  IF_BASH_FUNCTION(do_func:)
11299                         if (args && app == &args->narg.next
11300                          && !vars && !redir
11301                         ) {
11302                                 struct builtincmd *bcmd;
11303                                 const char *name;
11304
11305                                 /* We have a function */
11306                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11307                                         raise_error_unexpected_syntax(TRP);
11308                                 name = n->narg.text;
11309                                 if (!goodname(name)
11310                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11311                                 ) {
11312                                         raise_error_syntax("bad function name");
11313                                 }
11314                                 n->type = NDEFUN;
11315                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11316                                 n->narg.next = parse_command();
11317                                 return n;
11318                         }
11319                         IF_BASH_FUNCTION(function_flag = 0;)
11320                         /* fall through */
11321                 default:
11322                         tokpushback = 1;
11323                         goto out;
11324                 }
11325         }
11326  out:
11327         *app = NULL;
11328         *vpp = NULL;
11329         *rpp = NULL;
11330         n = stzalloc(sizeof(struct ncmd));
11331         n->type = NCMD;
11332         n->ncmd.args = args;
11333         n->ncmd.assign = vars;
11334         n->ncmd.redirect = redir;
11335         return n;
11336 }
11337
11338 static union node *
11339 parse_command(void)
11340 {
11341         union node *n1, *n2;
11342         union node *ap, **app;
11343         union node *cp, **cpp;
11344         union node *redir, **rpp;
11345         union node **rpp2;
11346         int t;
11347
11348         redir = NULL;
11349         rpp2 = &redir;
11350
11351         switch (readtoken()) {
11352         default:
11353                 raise_error_unexpected_syntax(-1);
11354                 /* NOTREACHED */
11355         case TIF:
11356                 n1 = stzalloc(sizeof(struct nif));
11357                 n1->type = NIF;
11358                 n1->nif.test = list(0);
11359                 if (readtoken() != TTHEN)
11360                         raise_error_unexpected_syntax(TTHEN);
11361                 n1->nif.ifpart = list(0);
11362                 n2 = n1;
11363                 while (readtoken() == TELIF) {
11364                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11365                         n2 = n2->nif.elsepart;
11366                         n2->type = NIF;
11367                         n2->nif.test = list(0);
11368                         if (readtoken() != TTHEN)
11369                                 raise_error_unexpected_syntax(TTHEN);
11370                         n2->nif.ifpart = list(0);
11371                 }
11372                 if (lasttoken == TELSE)
11373                         n2->nif.elsepart = list(0);
11374                 else {
11375                         n2->nif.elsepart = NULL;
11376                         tokpushback = 1;
11377                 }
11378                 t = TFI;
11379                 break;
11380         case TWHILE:
11381         case TUNTIL: {
11382                 int got;
11383                 n1 = stzalloc(sizeof(struct nbinary));
11384                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11385                 n1->nbinary.ch1 = list(0);
11386                 got = readtoken();
11387                 if (got != TDO) {
11388                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11389                                         got == TWORD ? wordtext : ""));
11390                         raise_error_unexpected_syntax(TDO);
11391                 }
11392                 n1->nbinary.ch2 = list(0);
11393                 t = TDONE;
11394                 break;
11395         }
11396         case TFOR:
11397                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11398                         raise_error_syntax("bad for loop variable");
11399                 n1 = stzalloc(sizeof(struct nfor));
11400                 n1->type = NFOR;
11401                 n1->nfor.var = wordtext;
11402                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11403                 if (readtoken() == TIN) {
11404                         app = &ap;
11405                         while (readtoken() == TWORD) {
11406                                 n2 = stzalloc(sizeof(struct narg));
11407                                 n2->type = NARG;
11408                                 /*n2->narg.next = NULL; - stzalloc did it */
11409                                 n2->narg.text = wordtext;
11410                                 n2->narg.backquote = backquotelist;
11411                                 *app = n2;
11412                                 app = &n2->narg.next;
11413                         }
11414                         *app = NULL;
11415                         n1->nfor.args = ap;
11416                         if (lasttoken != TNL && lasttoken != TSEMI)
11417                                 raise_error_unexpected_syntax(-1);
11418                 } else {
11419                         n2 = stzalloc(sizeof(struct narg));
11420                         n2->type = NARG;
11421                         /*n2->narg.next = NULL; - stzalloc did it */
11422                         n2->narg.text = (char *)dolatstr;
11423                         /*n2->narg.backquote = NULL;*/
11424                         n1->nfor.args = n2;
11425                         /*
11426                          * Newline or semicolon here is optional (but note
11427                          * that the original Bourne shell only allowed NL).
11428                          */
11429                         if (lasttoken != TSEMI)
11430                                 tokpushback = 1;
11431                 }
11432                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11433                 if (readtoken() != TDO)
11434                         raise_error_unexpected_syntax(TDO);
11435                 n1->nfor.body = list(0);
11436                 t = TDONE;
11437                 break;
11438         case TCASE:
11439                 n1 = stzalloc(sizeof(struct ncase));
11440                 n1->type = NCASE;
11441                 if (readtoken() != TWORD)
11442                         raise_error_unexpected_syntax(TWORD);
11443                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11444                 n2->type = NARG;
11445                 /*n2->narg.next = NULL; - stzalloc did it */
11446                 n2->narg.text = wordtext;
11447                 n2->narg.backquote = backquotelist;
11448                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11449                 if (readtoken() != TIN)
11450                         raise_error_unexpected_syntax(TIN);
11451                 cpp = &n1->ncase.cases;
11452  next_case:
11453                 checkkwd = CHKNL | CHKKWD;
11454                 t = readtoken();
11455                 while (t != TESAC) {
11456                         if (lasttoken == TLP)
11457                                 readtoken();
11458                         *cpp = cp = stzalloc(sizeof(struct nclist));
11459                         cp->type = NCLIST;
11460                         app = &cp->nclist.pattern;
11461                         for (;;) {
11462                                 *app = ap = stzalloc(sizeof(struct narg));
11463                                 ap->type = NARG;
11464                                 /*ap->narg.next = NULL; - stzalloc did it */
11465                                 ap->narg.text = wordtext;
11466                                 ap->narg.backquote = backquotelist;
11467                                 if (readtoken() != TPIPE)
11468                                         break;
11469                                 app = &ap->narg.next;
11470                                 readtoken();
11471                         }
11472                         //ap->narg.next = NULL;
11473                         if (lasttoken != TRP)
11474                                 raise_error_unexpected_syntax(TRP);
11475                         cp->nclist.body = list(2);
11476
11477                         cpp = &cp->nclist.next;
11478
11479                         checkkwd = CHKNL | CHKKWD;
11480                         t = readtoken();
11481                         if (t != TESAC) {
11482                                 if (t != TENDCASE)
11483                                         raise_error_unexpected_syntax(TENDCASE);
11484                                 goto next_case;
11485                         }
11486                 }
11487                 *cpp = NULL;
11488                 goto redir;
11489         case TLP:
11490                 n1 = stzalloc(sizeof(struct nredir));
11491                 n1->type = NSUBSHELL;
11492                 n1->nredir.n = list(0);
11493                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11494                 t = TRP;
11495                 break;
11496         case TBEGIN:
11497                 n1 = list(0);
11498                 t = TEND;
11499                 break;
11500         IF_BASH_FUNCTION(case TFUNCTION:)
11501         case TWORD:
11502         case TREDIR:
11503                 tokpushback = 1;
11504                 return simplecmd();
11505         }
11506
11507         if (readtoken() != t)
11508                 raise_error_unexpected_syntax(t);
11509
11510  redir:
11511         /* Now check for redirection which may follow command */
11512         checkkwd = CHKKWD | CHKALIAS;
11513         rpp = rpp2;
11514         while (readtoken() == TREDIR) {
11515                 *rpp = n2 = redirnode;
11516                 rpp = &n2->nfile.next;
11517                 parsefname();
11518         }
11519         tokpushback = 1;
11520         *rpp = NULL;
11521         if (redir) {
11522                 if (n1->type != NSUBSHELL) {
11523                         n2 = stzalloc(sizeof(struct nredir));
11524                         n2->type = NREDIR;
11525                         n2->nredir.n = n1;
11526                         n1 = n2;
11527                 }
11528                 n1->nredir.redirect = redir;
11529         }
11530         return n1;
11531 }
11532
11533 #if BASH_DOLLAR_SQUOTE
11534 static int
11535 decode_dollar_squote(void)
11536 {
11537         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11538         int c, cnt;
11539         char *p;
11540         char buf[4];
11541
11542         c = pgetc();
11543         p = strchr(C_escapes, c);
11544         if (p) {
11545                 buf[0] = c;
11546                 p = buf;
11547                 cnt = 3;
11548                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11549                         do {
11550                                 c = pgetc();
11551                                 *++p = c;
11552                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11553                         pungetc();
11554                 } else if (c == 'x') { /* \xHH */
11555                         do {
11556                                 c = pgetc();
11557                                 *++p = c;
11558                         } while (isxdigit(c) && --cnt);
11559                         pungetc();
11560                         if (cnt == 3) { /* \x but next char is "bad" */
11561                                 c = 'x';
11562                                 goto unrecognized;
11563                         }
11564                 } else { /* simple seq like \\ or \t */
11565                         p++;
11566                 }
11567                 *p = '\0';
11568                 p = buf;
11569                 c = bb_process_escape_sequence((void*)&p);
11570         } else { /* unrecognized "\z": print both chars unless ' or " */
11571                 if (c != '\'' && c != '"') {
11572  unrecognized:
11573                         c |= 0x100; /* "please encode \, then me" */
11574                 }
11575         }
11576         return c;
11577 }
11578 #endif
11579
11580 /*
11581  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11582  * is not NULL, read a here document.  In the latter case, eofmark is the
11583  * word which marks the end of the document and striptabs is true if
11584  * leading tabs should be stripped from the document.  The argument c
11585  * is the first character of the input token or document.
11586  *
11587  * Because C does not have internal subroutines, I have simulated them
11588  * using goto's to implement the subroutine linkage.  The following macros
11589  * will run code that appears at the end of readtoken1.
11590  */
11591 #define CHECKEND()      {goto checkend; checkend_return:;}
11592 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11593 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11594 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11595 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11596 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11597 static int
11598 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11599 {
11600         /* NB: syntax parameter fits into smallint */
11601         /* c parameter is an unsigned char or PEOF or PEOA */
11602         char *out;
11603         size_t len;
11604         char line[EOFMARKLEN + 1];
11605         struct nodelist *bqlist;
11606         smallint quotef;
11607         smallint dblquote;
11608         smallint oldstyle;
11609         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11610         smallint pssyntax;   /* we are expanding a prompt string */
11611         int varnest;         /* levels of variables expansion */
11612         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11613         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11614         int dqvarnest;       /* levels of variables expansion within double quotes */
11615
11616         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11617
11618         startlinno = g_parsefile->linno;
11619         bqlist = NULL;
11620         quotef = 0;
11621         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11622         pssyntax = (syntax == PSSYNTAX);
11623         if (pssyntax)
11624                 syntax = DQSYNTAX;
11625         dblquote = (syntax == DQSYNTAX);
11626         varnest = 0;
11627         IF_FEATURE_SH_MATH(arinest = 0;)
11628         IF_FEATURE_SH_MATH(parenlevel = 0;)
11629         dqvarnest = 0;
11630
11631         STARTSTACKSTR(out);
11632  loop:
11633         /* For each line, until end of word */
11634         CHECKEND();     /* set c to PEOF if at end of here document */
11635         for (;;) {      /* until end of line or end of word */
11636                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11637                 switch (SIT(c, syntax)) {
11638                 case CNL:       /* '\n' */
11639                         if (syntax == BASESYNTAX)
11640                                 goto endword;   /* exit outer loop */
11641                         USTPUTC(c, out);
11642                         nlprompt();
11643                         c = pgetc();
11644                         goto loop;              /* continue outer loop */
11645                 case CWORD:
11646                         USTPUTC(c, out);
11647                         break;
11648                 case CCTL:
11649 #if BASH_DOLLAR_SQUOTE
11650                         if (c == '\\' && bash_dollar_squote) {
11651                                 c = decode_dollar_squote();
11652                                 if (c == '\0') {
11653                                         /* skip $'\000', $'\x00' (like bash) */
11654                                         break;
11655                                 }
11656                                 if (c & 0x100) {
11657                                         /* Unknown escape. Encode as '\z' */
11658                                         c = (unsigned char)c;
11659                                         if (eofmark == NULL || dblquote)
11660                                                 USTPUTC(CTLESC, out);
11661                                         USTPUTC('\\', out);
11662                                 }
11663                         }
11664 #endif
11665                         if (eofmark == NULL || dblquote)
11666                                 USTPUTC(CTLESC, out);
11667                         USTPUTC(c, out);
11668                         break;
11669                 case CBACK:     /* backslash */
11670                         c = pgetc_without_PEOA();
11671                         if (c == PEOF) {
11672                                 USTPUTC(CTLESC, out);
11673                                 USTPUTC('\\', out);
11674                                 pungetc();
11675                         } else if (c == '\n') {
11676                                 nlprompt();
11677                         } else {
11678                                 if (c == '$' && pssyntax) {
11679                                         USTPUTC(CTLESC, out);
11680                                         USTPUTC('\\', out);
11681                                 }
11682                                 /* Backslash is retained if we are in "str" and next char isn't special */
11683                                 if (dblquote
11684                                  && c != '\\'
11685                                  && c != '`'
11686                                  && c != '$'
11687                                  && (c != '"' || eofmark != NULL)
11688                                 ) {
11689                                         USTPUTC('\\', out);
11690                                 }
11691                                 USTPUTC(CTLESC, out);
11692                                 USTPUTC(c, out);
11693                                 quotef = 1;
11694                         }
11695                         break;
11696                 case CSQUOTE:
11697                         syntax = SQSYNTAX;
11698  quotemark:
11699                         if (eofmark == NULL) {
11700                                 USTPUTC(CTLQUOTEMARK, out);
11701                         }
11702                         break;
11703                 case CDQUOTE:
11704                         syntax = DQSYNTAX;
11705                         dblquote = 1;
11706                         goto quotemark;
11707                 case CENDQUOTE:
11708                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11709                         if (eofmark != NULL && varnest == 0) {
11710                                 USTPUTC(c, out);
11711                         } else {
11712                                 if (dqvarnest == 0) {
11713                                         syntax = BASESYNTAX;
11714                                         dblquote = 0;
11715                                 }
11716                                 quotef = 1;
11717                                 goto quotemark;
11718                         }
11719                         break;
11720                 case CVAR:      /* '$' */
11721                         PARSESUB();             /* parse substitution */
11722                         break;
11723                 case CENDVAR:   /* '}' */
11724                         if (varnest > 0) {
11725                                 varnest--;
11726                                 if (dqvarnest > 0) {
11727                                         dqvarnest--;
11728                                 }
11729                                 c = CTLENDVAR;
11730                         }
11731                         USTPUTC(c, out);
11732                         break;
11733 #if ENABLE_FEATURE_SH_MATH
11734                 case CLP:       /* '(' in arithmetic */
11735                         parenlevel++;
11736                         USTPUTC(c, out);
11737                         break;
11738                 case CRP:       /* ')' in arithmetic */
11739                         if (parenlevel > 0) {
11740                                 parenlevel--;
11741                         } else {
11742                                 if (pgetc_eatbnl() == ')') {
11743                                         c = CTLENDARI;
11744                                         if (--arinest == 0) {
11745                                                 syntax = prevsyntax;
11746                                         }
11747                                 } else {
11748                                         /*
11749                                          * unbalanced parens
11750                                          * (don't 2nd guess - no error)
11751                                          */
11752                                         pungetc();
11753                                 }
11754                         }
11755                         USTPUTC(c, out);
11756                         break;
11757 #endif
11758                 case CBQUOTE:   /* '`' */
11759                         PARSEBACKQOLD();
11760                         break;
11761                 case CENDFILE:
11762                         goto endword;           /* exit outer loop */
11763                 case CIGN:
11764                         break;
11765                 default:
11766                         if (varnest == 0) {
11767 #if BASH_REDIR_OUTPUT
11768                                 if (c == '&') {
11769 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11770                                         if (pgetc() == '>')
11771                                                 c = 0x100 + '>'; /* flag &> */
11772                                         pungetc();
11773                                 }
11774 #endif
11775                                 goto endword;   /* exit outer loop */
11776                         }
11777                         IF_ASH_ALIAS(if (c != PEOA))
11778                                 USTPUTC(c, out);
11779                 }
11780                 c = pgetc();
11781         } /* for (;;) */
11782  endword:
11783
11784 #if ENABLE_FEATURE_SH_MATH
11785         if (syntax == ARISYNTAX)
11786                 raise_error_syntax("missing '))'");
11787 #endif
11788         if (syntax != BASESYNTAX && eofmark == NULL)
11789                 raise_error_syntax("unterminated quoted string");
11790         if (varnest != 0) {
11791                 startlinno = g_parsefile->linno;
11792                 /* { */
11793                 raise_error_syntax("missing '}'");
11794         }
11795         USTPUTC('\0', out);
11796         len = out - (char *)stackblock();
11797         out = stackblock();
11798         if (eofmark == NULL) {
11799                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11800                  && quotef == 0
11801                 ) {
11802                         if (isdigit_str9(out)) {
11803                                 PARSEREDIR(); /* passed as params: out, c */
11804                                 lasttoken = TREDIR;
11805                                 return lasttoken;
11806                         }
11807                         /* else: non-number X seen, interpret it
11808                          * as "NNNX>file" = "NNNX >file" */
11809                 }
11810                 pungetc();
11811         }
11812         quoteflag = quotef;
11813         backquotelist = bqlist;
11814         grabstackblock(len);
11815         wordtext = out;
11816         lasttoken = TWORD;
11817         return lasttoken;
11818 /* end of readtoken routine */
11819
11820 /*
11821  * Check to see whether we are at the end of the here document.  When this
11822  * is called, c is set to the first character of the next input line.  If
11823  * we are at the end of the here document, this routine sets the c to PEOF.
11824  */
11825 checkend: {
11826         if (eofmark) {
11827 #if ENABLE_ASH_ALIAS
11828                 if (c == PEOA)
11829                         c = pgetc_without_PEOA();
11830 #endif
11831                 if (striptabs) {
11832                         while (c == '\t') {
11833                                 c = pgetc_without_PEOA();
11834                         }
11835                 }
11836                 if (c == *eofmark) {
11837                         if (pfgets(line, sizeof(line)) != NULL) {
11838                                 char *p, *q;
11839                                 int cc;
11840
11841                                 p = line;
11842                                 for (q = eofmark + 1;; p++, q++) {
11843                                         cc = *p;
11844                                         if (cc == '\n')
11845                                                 cc = 0;
11846                                         if (!*q || cc != *q)
11847                                                 break;
11848                                 }
11849                                 if (cc == *q) {
11850                                         c = PEOF;
11851                                         nlnoprompt();
11852                                 } else {
11853                                         pushstring(line, NULL);
11854                                 }
11855                         }
11856                 }
11857         }
11858         goto checkend_return;
11859 }
11860
11861 /*
11862  * Parse a redirection operator.  The variable "out" points to a string
11863  * specifying the fd to be redirected.  The variable "c" contains the
11864  * first character of the redirection operator.
11865  */
11866 parseredir: {
11867         /* out is already checked to be a valid number or "" */
11868         int fd = (*out == '\0' ? -1 : atoi(out));
11869         union node *np;
11870
11871         np = stzalloc(sizeof(struct nfile));
11872         if (c == '>') {
11873                 np->nfile.fd = 1;
11874                 c = pgetc();
11875                 if (c == '>')
11876                         np->type = NAPPEND;
11877                 else if (c == '|')
11878                         np->type = NCLOBBER;
11879                 else if (c == '&')
11880                         np->type = NTOFD;
11881                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11882                 else {
11883                         np->type = NTO;
11884                         pungetc();
11885                 }
11886         }
11887 #if BASH_REDIR_OUTPUT
11888         else if (c == 0x100 + '>') { /* this flags &> redirection */
11889                 np->nfile.fd = 1;
11890                 pgetc(); /* this is '>', no need to check */
11891                 np->type = NTO2;
11892         }
11893 #endif
11894         else { /* c == '<' */
11895                 /*np->nfile.fd = 0; - stzalloc did it */
11896                 c = pgetc();
11897                 switch (c) {
11898                 case '<':
11899                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11900                                 np = stzalloc(sizeof(struct nhere));
11901                                 /*np->nfile.fd = 0; - stzalloc did it */
11902                         }
11903                         np->type = NHERE;
11904                         heredoc = stzalloc(sizeof(struct heredoc));
11905                         heredoc->here = np;
11906                         c = pgetc();
11907                         if (c == '-') {
11908                                 heredoc->striptabs = 1;
11909                         } else {
11910                                 /*heredoc->striptabs = 0; - stzalloc did it */
11911                                 pungetc();
11912                         }
11913                         break;
11914
11915                 case '&':
11916                         np->type = NFROMFD;
11917                         break;
11918
11919                 case '>':
11920                         np->type = NFROMTO;
11921                         break;
11922
11923                 default:
11924                         np->type = NFROM;
11925                         pungetc();
11926                         break;
11927                 }
11928         }
11929         if (fd >= 0)
11930                 np->nfile.fd = fd;
11931         redirnode = np;
11932         goto parseredir_return;
11933 }
11934
11935 /*
11936  * Parse a substitution.  At this point, we have read the dollar sign
11937  * and nothing else.
11938  */
11939
11940 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11941  * (assuming ascii char codes, as the original implementation did) */
11942 #define is_special(c) \
11943         (((unsigned)(c) - 33 < 32) \
11944                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11945 parsesub: {
11946         unsigned char subtype;
11947         int typeloc;
11948
11949         c = pgetc_eatbnl();
11950         if (c > 255 /* PEOA or PEOF */
11951          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11952         ) {
11953 #if BASH_DOLLAR_SQUOTE
11954                 if (syntax != DQSYNTAX && c == '\'')
11955                         bash_dollar_squote = 1;
11956                 else
11957 #endif
11958                         USTPUTC('$', out);
11959                 pungetc();
11960         } else if (c == '(') {
11961                 /* $(command) or $((arith)) */
11962                 if (pgetc_eatbnl() == '(') {
11963 #if ENABLE_FEATURE_SH_MATH
11964                         PARSEARITH();
11965 #else
11966                         raise_error_syntax("support for $((arith)) is disabled");
11967 #endif
11968                 } else {
11969                         pungetc();
11970                         PARSEBACKQNEW();
11971                 }
11972         } else {
11973                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11974                 USTPUTC(CTLVAR, out);
11975                 typeloc = out - (char *)stackblock();
11976                 STADJUST(1, out);
11977                 subtype = VSNORMAL;
11978                 if (c == '{') {
11979                         c = pgetc_eatbnl();
11980                         subtype = 0;
11981                 }
11982  varname:
11983                 if (is_name(c)) {
11984                         /* $[{[#]]NAME[}] */
11985                         do {
11986                                 STPUTC(c, out);
11987                                 c = pgetc_eatbnl();
11988                         } while (is_in_name(c));
11989                 } else if (isdigit(c)) {
11990                         /* $[{[#]]NUM[}] */
11991                         do {
11992                                 STPUTC(c, out);
11993                                 c = pgetc_eatbnl();
11994                         } while (isdigit(c));
11995                 } else if (is_special(c)) {
11996                         /* $[{[#]]<specialchar>[}] */
11997                         int cc = c;
11998
11999                         c = pgetc_eatbnl();
12000                         if (!subtype && cc == '#') {
12001                                 subtype = VSLENGTH;
12002                                 if (c == '_' || isalnum(c))
12003                                         goto varname;
12004                                 cc = c;
12005                                 c = pgetc_eatbnl();
12006                                 if (cc == '}' || c != '}') {
12007                                         pungetc();
12008                                         subtype = 0;
12009                                         c = cc;
12010                                         cc = '#';
12011                                 }
12012                         }
12013                         USTPUTC(cc, out);
12014                 } else {
12015                         goto badsub;
12016                 }
12017                 if (c != '}' && subtype == VSLENGTH) {
12018                         /* ${#VAR didn't end with } */
12019                         goto badsub;
12020                 }
12021
12022                 if (subtype == 0) {
12023                         static const char types[] ALIGN1 = "}-+?=";
12024                         /* ${VAR...} but not $VAR or ${#VAR} */
12025                         /* c == first char after VAR */
12026                         switch (c) {
12027                         case ':':
12028                                 c = pgetc_eatbnl();
12029 #if BASH_SUBSTR
12030                                 /* This check is only needed to not misinterpret
12031                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12032                                  * constructs.
12033                                  */
12034                                 if (!strchr(types, c)) {
12035                                         subtype = VSSUBSTR;
12036                                         pungetc();
12037                                         break; /* "goto badsub" is bigger (!) */
12038                                 }
12039 #endif
12040                                 subtype = VSNUL;
12041                                 /*FALLTHROUGH*/
12042                         default: {
12043                                 const char *p = strchr(types, c);
12044                                 if (p == NULL)
12045                                         break;
12046                                 subtype |= p - types + VSNORMAL;
12047                                 break;
12048                         }
12049                         case '%':
12050                         case '#': {
12051                                 int cc = c;
12052                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12053                                 c = pgetc_eatbnl();
12054                                 if (c != cc)
12055                                         goto badsub;
12056                                 subtype++;
12057                                 break;
12058                         }
12059 #if BASH_PATTERN_SUBST
12060                         case '/':
12061                                 /* ${v/[/]pattern/repl} */
12062 //TODO: encode pattern and repl separately.
12063 // Currently ${v/$var_with_slash/repl} is horribly broken
12064                                 subtype = VSREPLACE;
12065                                 c = pgetc_eatbnl();
12066                                 if (c != '/')
12067                                         goto badsub;
12068                                 subtype++; /* VSREPLACEALL */
12069                                 break;
12070 #endif
12071                         }
12072                 } else {
12073  badsub:
12074                         pungetc();
12075                 }
12076                 ((unsigned char *)stackblock())[typeloc] = subtype;
12077                 if (subtype != VSNORMAL) {
12078                         varnest++;
12079                         if (dblquote)
12080                                 dqvarnest++;
12081                 }
12082                 STPUTC('=', out);
12083         }
12084         goto parsesub_return;
12085 }
12086
12087 /*
12088  * Called to parse command substitutions.  Newstyle is set if the command
12089  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12090  * list of commands (passed by reference), and savelen is the number of
12091  * characters on the top of the stack which must be preserved.
12092  */
12093 parsebackq: {
12094         struct nodelist **nlpp;
12095         union node *n;
12096         char *str;
12097         size_t savelen;
12098         smallint saveprompt = 0;
12099
12100         str = NULL;
12101         savelen = out - (char *)stackblock();
12102         if (savelen > 0) {
12103                 /*
12104                  * FIXME: this can allocate very large block on stack and SEGV.
12105                  * Example:
12106                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12107                  * allocates 100kb for every command subst. With about
12108                  * a hundred command substitutions stack overflows.
12109                  * With larger prepended string, SEGV happens sooner.
12110                  */
12111                 str = alloca(savelen);
12112                 memcpy(str, stackblock(), savelen);
12113         }
12114
12115         if (oldstyle) {
12116                 /* We must read until the closing backquote, giving special
12117                  * treatment to some slashes, and then push the string and
12118                  * reread it as input, interpreting it normally.
12119                  */
12120                 char *pout;
12121                 size_t psavelen;
12122                 char *pstr;
12123
12124                 STARTSTACKSTR(pout);
12125                 for (;;) {
12126                         int pc;
12127
12128                         setprompt_if(needprompt, 2);
12129                         pc = pgetc();
12130                         switch (pc) {
12131                         case '`':
12132                                 goto done;
12133
12134                         case '\\':
12135                                 pc = pgetc();
12136                                 if (pc == '\n') {
12137                                         nlprompt();
12138                                         /*
12139                                          * If eating a newline, avoid putting
12140                                          * the newline into the new character
12141                                          * stream (via the STPUTC after the
12142                                          * switch).
12143                                          */
12144                                         continue;
12145                                 }
12146                                 if (pc != '\\' && pc != '`' && pc != '$'
12147                                  && (!dblquote || pc != '"')
12148                                 ) {
12149                                         STPUTC('\\', pout);
12150                                 }
12151                                 if (pc <= 255 /* not PEOA or PEOF */) {
12152                                         break;
12153                                 }
12154                                 /* fall through */
12155
12156                         case PEOF:
12157                         IF_ASH_ALIAS(case PEOA:)
12158                                 startlinno = g_parsefile->linno;
12159                                 raise_error_syntax("EOF in backquote substitution");
12160
12161                         case '\n':
12162                                 nlnoprompt();
12163                                 break;
12164
12165                         default:
12166                                 break;
12167                         }
12168                         STPUTC(pc, pout);
12169                 }
12170  done:
12171                 STPUTC('\0', pout);
12172                 psavelen = pout - (char *)stackblock();
12173                 if (psavelen > 0) {
12174                         pstr = grabstackstr(pout);
12175                         setinputstring(pstr);
12176                 }
12177         }
12178         nlpp = &bqlist;
12179         while (*nlpp)
12180                 nlpp = &(*nlpp)->next;
12181         *nlpp = stzalloc(sizeof(**nlpp));
12182         /* (*nlpp)->next = NULL; - stzalloc did it */
12183
12184         if (oldstyle) {
12185                 saveprompt = doprompt;
12186                 doprompt = 0;
12187         }
12188
12189         n = list(2);
12190
12191         if (oldstyle)
12192                 doprompt = saveprompt;
12193         else if (readtoken() != TRP)
12194                 raise_error_unexpected_syntax(TRP);
12195
12196         (*nlpp)->n = n;
12197         if (oldstyle) {
12198                 /*
12199                  * Start reading from old file again, ignoring any pushed back
12200                  * tokens left from the backquote parsing
12201                  */
12202                 popfile();
12203                 tokpushback = 0;
12204         }
12205         while (stackblocksize() <= savelen)
12206                 growstackblock();
12207         STARTSTACKSTR(out);
12208         if (str) {
12209                 memcpy(out, str, savelen);
12210                 STADJUST(savelen, out);
12211         }
12212         USTPUTC(CTLBACKQ, out);
12213         if (oldstyle)
12214                 goto parsebackq_oldreturn;
12215         goto parsebackq_newreturn;
12216 }
12217
12218 #if ENABLE_FEATURE_SH_MATH
12219 /*
12220  * Parse an arithmetic expansion (indicate start of one and set state)
12221  */
12222 parsearith: {
12223         if (++arinest == 1) {
12224                 prevsyntax = syntax;
12225                 syntax = ARISYNTAX;
12226         }
12227         USTPUTC(CTLARI, out);
12228         goto parsearith_return;
12229 }
12230 #endif
12231 } /* end of readtoken */
12232
12233 /*
12234  * Read the next input token.
12235  * If the token is a word, we set backquotelist to the list of cmds in
12236  *      backquotes.  We set quoteflag to true if any part of the word was
12237  *      quoted.
12238  * If the token is TREDIR, then we set redirnode to a structure containing
12239  *      the redirection.
12240  * In all cases, the variable startlinno is set to the number of the line
12241  *      on which the token starts.
12242  *
12243  * [Change comment:  here documents and internal procedures]
12244  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12245  *  word parsing code into a separate routine.  In this case, readtoken
12246  *  doesn't need to have any internal procedures, but parseword does.
12247  *  We could also make parseoperator in essence the main routine, and
12248  *  have parseword (readtoken1?) handle both words and redirection.]
12249  */
12250 #define NEW_xxreadtoken
12251 #ifdef NEW_xxreadtoken
12252 /* singles must be first! */
12253 static const char xxreadtoken_chars[7] ALIGN1 = {
12254         '\n', '(', ')', /* singles */
12255         '&', '|', ';',  /* doubles */
12256         0
12257 };
12258
12259 #define xxreadtoken_singles 3
12260 #define xxreadtoken_doubles 3
12261
12262 static const char xxreadtoken_tokens[] ALIGN1 = {
12263         TNL, TLP, TRP,          /* only single occurrence allowed */
12264         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12265         TEOF,                   /* corresponds to trailing nul */
12266         TAND, TOR, TENDCASE     /* if double occurrence */
12267 };
12268
12269 static int
12270 xxreadtoken(void)
12271 {
12272         int c;
12273
12274         if (tokpushback) {
12275                 tokpushback = 0;
12276                 return lasttoken;
12277         }
12278         setprompt_if(needprompt, 2);
12279         startlinno = g_parsefile->linno;
12280         for (;;) {                      /* until token or start of word found */
12281                 c = pgetc();
12282                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12283                         continue;
12284
12285                 if (c == '#') {
12286                         while ((c = pgetc()) != '\n' && c != PEOF)
12287                                 continue;
12288                         pungetc();
12289                 } else if (c == '\\') {
12290                         if (pgetc() != '\n') {
12291                                 pungetc();
12292                                 break; /* return readtoken1(...) */
12293                         }
12294                         nlprompt();
12295                 } else {
12296                         const char *p;
12297
12298                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12299                         if (c != PEOF) {
12300                                 if (c == '\n') {
12301                                         nlnoprompt();
12302                                 }
12303
12304                                 p = strchr(xxreadtoken_chars, c);
12305                                 if (p == NULL)
12306                                         break; /* return readtoken1(...) */
12307
12308                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12309                                         int cc = pgetc();
12310                                         if (cc == c) {    /* double occurrence? */
12311                                                 p += xxreadtoken_doubles + 1;
12312                                         } else {
12313                                                 pungetc();
12314 #if BASH_REDIR_OUTPUT
12315                                                 if (c == '&' && cc == '>') /* &> */
12316                                                         break; /* return readtoken1(...) */
12317 #endif
12318                                         }
12319                                 }
12320                         }
12321                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12322                         return lasttoken;
12323                 }
12324         } /* for (;;) */
12325
12326         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12327 }
12328 #else /* old xxreadtoken */
12329 #define RETURN(token)   return lasttoken = token
12330 static int
12331 xxreadtoken(void)
12332 {
12333         int c;
12334
12335         if (tokpushback) {
12336                 tokpushback = 0;
12337                 return lasttoken;
12338         }
12339         setprompt_if(needprompt, 2);
12340         startlinno = g_parsefile->linno;
12341         for (;;) {      /* until token or start of word found */
12342                 c = pgetc();
12343                 switch (c) {
12344                 case ' ': case '\t':
12345                 IF_ASH_ALIAS(case PEOA:)
12346                         continue;
12347                 case '#':
12348                         while ((c = pgetc()) != '\n' && c != PEOF)
12349                                 continue;
12350                         pungetc();
12351                         continue;
12352                 case '\\':
12353                         if (pgetc() == '\n') {
12354                                 nlprompt();
12355                                 continue;
12356                         }
12357                         pungetc();
12358                         goto breakloop;
12359                 case '\n':
12360                         nlnoprompt();
12361                         RETURN(TNL);
12362                 case PEOF:
12363                         RETURN(TEOF);
12364                 case '&':
12365                         if (pgetc() == '&')
12366                                 RETURN(TAND);
12367                         pungetc();
12368                         RETURN(TBACKGND);
12369                 case '|':
12370                         if (pgetc() == '|')
12371                                 RETURN(TOR);
12372                         pungetc();
12373                         RETURN(TPIPE);
12374                 case ';':
12375                         if (pgetc() == ';')
12376                                 RETURN(TENDCASE);
12377                         pungetc();
12378                         RETURN(TSEMI);
12379                 case '(':
12380                         RETURN(TLP);
12381                 case ')':
12382                         RETURN(TRP);
12383                 default:
12384                         goto breakloop;
12385                 }
12386         }
12387  breakloop:
12388         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12389 #undef RETURN
12390 }
12391 #endif /* old xxreadtoken */
12392
12393 static int
12394 readtoken(void)
12395 {
12396         int t;
12397         int kwd = checkkwd;
12398 #if DEBUG
12399         smallint alreadyseen = tokpushback;
12400 #endif
12401
12402 #if ENABLE_ASH_ALIAS
12403  top:
12404 #endif
12405
12406         t = xxreadtoken();
12407
12408         /*
12409          * eat newlines
12410          */
12411         if (kwd & CHKNL) {
12412                 while (t == TNL) {
12413                         parseheredoc();
12414                         t = xxreadtoken();
12415                 }
12416         }
12417
12418         if (t != TWORD || quoteflag) {
12419                 goto out;
12420         }
12421
12422         /*
12423          * check for keywords
12424          */
12425         if (kwd & CHKKWD) {
12426                 const char *const *pp;
12427
12428                 pp = findkwd(wordtext);
12429                 if (pp) {
12430                         lasttoken = t = pp - tokname_array;
12431                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12432                         goto out;
12433                 }
12434         }
12435
12436         if (checkkwd & CHKALIAS) {
12437 #if ENABLE_ASH_ALIAS
12438                 struct alias *ap;
12439                 ap = lookupalias(wordtext, 1);
12440                 if (ap != NULL) {
12441                         if (*ap->val) {
12442                                 pushstring(ap->val, ap);
12443                         }
12444                         goto top;
12445                 }
12446 #endif
12447         }
12448  out:
12449         checkkwd = 0;
12450 #if DEBUG
12451         if (!alreadyseen)
12452                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12453         else
12454                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12455 #endif
12456         return t;
12457 }
12458
12459 static int
12460 peektoken(void)
12461 {
12462         int t;
12463
12464         t = readtoken();
12465         tokpushback = 1;
12466         return t;
12467 }
12468
12469 /*
12470  * Read and parse a command.  Returns NODE_EOF on end of file.
12471  * (NULL is a valid parse tree indicating a blank line.)
12472  */
12473 static union node *
12474 parsecmd(int interact)
12475 {
12476         tokpushback = 0;
12477         checkkwd = 0;
12478         heredoclist = 0;
12479         doprompt = interact;
12480         setprompt_if(doprompt, doprompt);
12481         needprompt = 0;
12482         return list(1);
12483 }
12484
12485 /*
12486  * Input any here documents.
12487  */
12488 static void
12489 parseheredoc(void)
12490 {
12491         struct heredoc *here;
12492         union node *n;
12493
12494         here = heredoclist;
12495         heredoclist = NULL;
12496
12497         while (here) {
12498                 setprompt_if(needprompt, 2);
12499                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12500                                 here->eofmark, here->striptabs);
12501                 n = stzalloc(sizeof(struct narg));
12502                 n->narg.type = NARG;
12503                 /*n->narg.next = NULL; - stzalloc did it */
12504                 n->narg.text = wordtext;
12505                 n->narg.backquote = backquotelist;
12506                 here->here->nhere.doc = n;
12507                 here = here->next;
12508         }
12509 }
12510
12511
12512 /*
12513  * called by editline -- any expansions to the prompt should be added here.
12514  */
12515 static const char *
12516 expandstr(const char *ps)
12517 {
12518         union node n;
12519         int saveprompt;
12520
12521         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12522          * and token processing _can_ alter it (delete NULs etc). */
12523         setinputstring((char *)ps);
12524
12525         saveprompt = doprompt;
12526         doprompt = 0;
12527         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12528         doprompt = saveprompt;
12529
12530         popfile();
12531
12532         n.narg.type = NARG;
12533         n.narg.next = NULL;
12534         n.narg.text = wordtext;
12535         n.narg.backquote = backquotelist;
12536
12537         expandarg(&n, NULL, EXP_QUOTED);
12538         return stackblock();
12539 }
12540
12541 static inline int
12542 parser_eof(void)
12543 {
12544         return tokpushback && lasttoken == TEOF;
12545 }
12546
12547 /*
12548  * Execute a command or commands contained in a string.
12549  */
12550 static int
12551 evalstring(char *s, int flags)
12552 {
12553         struct jmploc *volatile savehandler;
12554         struct jmploc jmploc;
12555         int ex;
12556
12557         union node *n;
12558         struct stackmark smark;
12559         int status;
12560
12561         s = sstrdup(s);
12562         setinputstring(s);
12563         setstackmark(&smark);
12564
12565         status = 0;
12566         /* On exception inside execution loop, we must popfile().
12567          * Try interactively:
12568          *      readonly a=a
12569          *      command eval "a=b"  # throws "is read only" error
12570          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12571          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12572          */
12573         savehandler = exception_handler;
12574         ex = setjmp(jmploc.loc);
12575         if (ex)
12576                 goto out;
12577         exception_handler = &jmploc;
12578
12579         while ((n = parsecmd(0)) != NODE_EOF) {
12580                 int i;
12581
12582                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12583                 if (n)
12584                         status = i;
12585                 popstackmark(&smark);
12586                 if (evalskip)
12587                         break;
12588         }
12589  out:
12590         popstackmark(&smark);
12591         popfile();
12592         stunalloc(s);
12593
12594         exception_handler = savehandler;
12595         if (ex)
12596                 longjmp(exception_handler->loc, ex);
12597
12598         return status;
12599 }
12600
12601 /*
12602  * The eval command.
12603  */
12604 static int FAST_FUNC
12605 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12606 {
12607         char *p;
12608         char *concat;
12609
12610         if (argv[1]) {
12611                 p = argv[1];
12612                 argv += 2;
12613                 if (argv[0]) {
12614                         STARTSTACKSTR(concat);
12615                         for (;;) {
12616                                 concat = stack_putstr(p, concat);
12617                                 p = *argv++;
12618                                 if (p == NULL)
12619                                         break;
12620                                 STPUTC(' ', concat);
12621                         }
12622                         STPUTC('\0', concat);
12623                         p = grabstackstr(concat);
12624                 }
12625                 return evalstring(p, flags & EV_TESTED);
12626         }
12627         return 0;
12628 }
12629
12630 /*
12631  * Read and execute commands.
12632  * "Top" is nonzero for the top level command loop;
12633  * it turns on prompting if the shell is interactive.
12634  */
12635 static int
12636 cmdloop(int top)
12637 {
12638         union node *n;
12639         struct stackmark smark;
12640         int inter;
12641         int status = 0;
12642         int numeof = 0;
12643
12644         TRACE(("cmdloop(%d) called\n", top));
12645         for (;;) {
12646                 int skip;
12647
12648                 setstackmark(&smark);
12649 #if JOBS
12650                 if (doing_jobctl)
12651                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12652 #endif
12653                 inter = 0;
12654                 if (iflag && top) {
12655                         inter++;
12656                         chkmail();
12657                 }
12658                 n = parsecmd(inter);
12659 #if DEBUG
12660                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12661                         showtree(n);
12662 #endif
12663                 if (n == NODE_EOF) {
12664                         if (!top || numeof >= 50)
12665                                 break;
12666                         if (!stoppedjobs()) {
12667                                 if (!Iflag)
12668                                         break;
12669                                 out2str("\nUse \"exit\" to leave shell.\n");
12670                         }
12671                         numeof++;
12672                 } else if (nflag == 0) {
12673                         int i;
12674
12675                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12676                         job_warning >>= 1;
12677                         numeof = 0;
12678                         i = evaltree(n, 0);
12679                         if (n)
12680                                 status = i;
12681                 }
12682                 popstackmark(&smark);
12683                 skip = evalskip;
12684
12685                 if (skip) {
12686                         evalskip &= ~SKIPFUNC;
12687                         break;
12688                 }
12689         }
12690         return status;
12691 }
12692
12693 /*
12694  * Take commands from a file.  To be compatible we should do a path
12695  * search for the file, which is necessary to find sub-commands.
12696  */
12697 static char *
12698 find_dot_file(char *name)
12699 {
12700         char *fullname;
12701         const char *path = pathval();
12702         struct stat statb;
12703
12704         /* don't try this for absolute or relative paths */
12705         if (strchr(name, '/'))
12706                 return name;
12707
12708         while ((fullname = path_advance(&path, name)) != NULL) {
12709                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12710                         /*
12711                          * Don't bother freeing here, since it will
12712                          * be freed by the caller.
12713                          */
12714                         return fullname;
12715                 }
12716                 if (fullname != name)
12717                         stunalloc(fullname);
12718         }
12719
12720         /* not found in the PATH */
12721         ash_msg_and_raise_error("%s: not found", name);
12722         /* NOTREACHED */
12723 }
12724
12725 static int FAST_FUNC
12726 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12727 {
12728         /* "false; . empty_file; echo $?" should print 0, not 1: */
12729         int status = 0;
12730         char *fullname;
12731         char **argv;
12732         char *args_need_save;
12733         volatile struct shparam saveparam;
12734
12735 //???
12736 //      struct strlist *sp;
12737 //      for (sp = cmdenviron; sp; sp = sp->next)
12738 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12739
12740         nextopt(nullstr); /* handle possible "--" */
12741         argv = argptr;
12742
12743         if (!argv[0]) {
12744                 /* bash says: "bash: .: filename argument required" */
12745                 return 2; /* bash compat */
12746         }
12747
12748         /* This aborts if file isn't found, which is POSIXly correct.
12749          * bash returns exitcode 1 instead.
12750          */
12751         fullname = find_dot_file(argv[0]);
12752         argv++;
12753         args_need_save = argv[0];
12754         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12755                 int argc;
12756                 saveparam = shellparam;
12757                 shellparam.malloced = 0;
12758                 argc = 1;
12759                 while (argv[argc])
12760                         argc++;
12761                 shellparam.nparam = argc;
12762                 shellparam.p = argv;
12763         };
12764
12765         /* This aborts if file can't be opened, which is POSIXly correct.
12766          * bash returns exitcode 1 instead.
12767          */
12768         setinputfile(fullname, INPUT_PUSH_FILE);
12769         commandname = fullname;
12770         status = cmdloop(0);
12771         popfile();
12772
12773         if (args_need_save) {
12774                 freeparam(&shellparam);
12775                 shellparam = saveparam;
12776         };
12777
12778         return status;
12779 }
12780
12781 static int FAST_FUNC
12782 exitcmd(int argc UNUSED_PARAM, char **argv)
12783 {
12784         if (stoppedjobs())
12785                 return 0;
12786         if (argv[1])
12787                 exitstatus = number(argv[1]);
12788         raise_exception(EXEXIT);
12789         /* NOTREACHED */
12790 }
12791
12792 /*
12793  * Read a file containing shell functions.
12794  */
12795 static void
12796 readcmdfile(char *name)
12797 {
12798         setinputfile(name, INPUT_PUSH_FILE);
12799         cmdloop(0);
12800         popfile();
12801 }
12802
12803
12804 /* ============ find_command inplementation */
12805
12806 /*
12807  * Resolve a command name.  If you change this routine, you may have to
12808  * change the shellexec routine as well.
12809  */
12810 static void
12811 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12812 {
12813         struct tblentry *cmdp;
12814         int idx;
12815         int prev;
12816         char *fullname;
12817         struct stat statb;
12818         int e;
12819         int updatetbl;
12820         struct builtincmd *bcmd;
12821
12822         /* If name contains a slash, don't use PATH or hash table */
12823         if (strchr(name, '/') != NULL) {
12824                 entry->u.index = -1;
12825                 if (act & DO_ABS) {
12826                         while (stat(name, &statb) < 0) {
12827 #ifdef SYSV
12828                                 if (errno == EINTR)
12829                                         continue;
12830 #endif
12831                                 entry->cmdtype = CMDUNKNOWN;
12832                                 return;
12833                         }
12834                 }
12835                 entry->cmdtype = CMDNORMAL;
12836                 return;
12837         }
12838
12839 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12840
12841         updatetbl = (path == pathval());
12842         if (!updatetbl) {
12843                 act |= DO_ALTPATH;
12844                 if (strstr(path, "%builtin") != NULL)
12845                         act |= DO_ALTBLTIN;
12846         }
12847
12848         /* If name is in the table, check answer will be ok */
12849         cmdp = cmdlookup(name, 0);
12850         if (cmdp != NULL) {
12851                 int bit;
12852
12853                 switch (cmdp->cmdtype) {
12854                 default:
12855 #if DEBUG
12856                         abort();
12857 #endif
12858                 case CMDNORMAL:
12859                         bit = DO_ALTPATH;
12860                         break;
12861                 case CMDFUNCTION:
12862                         bit = DO_NOFUNC;
12863                         break;
12864                 case CMDBUILTIN:
12865                         bit = DO_ALTBLTIN;
12866                         break;
12867                 }
12868                 if (act & bit) {
12869                         updatetbl = 0;
12870                         cmdp = NULL;
12871                 } else if (cmdp->rehash == 0)
12872                         /* if not invalidated by cd, we're done */
12873                         goto success;
12874         }
12875
12876         /* If %builtin not in path, check for builtin next */
12877         bcmd = find_builtin(name);
12878         if (bcmd) {
12879                 if (IS_BUILTIN_REGULAR(bcmd))
12880                         goto builtin_success;
12881                 if (act & DO_ALTPATH) {
12882                         if (!(act & DO_ALTBLTIN))
12883                                 goto builtin_success;
12884                 } else if (builtinloc <= 0) {
12885                         goto builtin_success;
12886                 }
12887         }
12888
12889 #if ENABLE_FEATURE_SH_STANDALONE
12890         {
12891                 int applet_no = find_applet_by_name(name);
12892                 if (applet_no >= 0) {
12893                         entry->cmdtype = CMDNORMAL;
12894                         entry->u.index = -2 - applet_no;
12895                         return;
12896                 }
12897         }
12898 #endif
12899
12900         /* We have to search path. */
12901         prev = -1;              /* where to start */
12902         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12903                 if (cmdp->cmdtype == CMDBUILTIN)
12904                         prev = builtinloc;
12905                 else
12906                         prev = cmdp->param.index;
12907         }
12908
12909         e = ENOENT;
12910         idx = -1;
12911  loop:
12912         while ((fullname = path_advance(&path, name)) != NULL) {
12913                 stunalloc(fullname);
12914                 /* NB: code below will still use fullname
12915                  * despite it being "unallocated" */
12916                 idx++;
12917                 if (pathopt) {
12918                         if (prefix(pathopt, "builtin")) {
12919                                 if (bcmd)
12920                                         goto builtin_success;
12921                                 continue;
12922                         }
12923                         if ((act & DO_NOFUNC)
12924                          || !prefix(pathopt, "func")
12925                         ) {     /* ignore unimplemented options */
12926                                 continue;
12927                         }
12928                 }
12929                 /* if rehash, don't redo absolute path names */
12930                 if (fullname[0] == '/' && idx <= prev) {
12931                         if (idx < prev)
12932                                 continue;
12933                         TRACE(("searchexec \"%s\": no change\n", name));
12934                         goto success;
12935                 }
12936                 while (stat(fullname, &statb) < 0) {
12937 #ifdef SYSV
12938                         if (errno == EINTR)
12939                                 continue;
12940 #endif
12941                         if (errno != ENOENT && errno != ENOTDIR)
12942                                 e = errno;
12943                         goto loop;
12944                 }
12945                 e = EACCES;     /* if we fail, this will be the error */
12946                 if (!S_ISREG(statb.st_mode))
12947                         continue;
12948                 if (pathopt) {          /* this is a %func directory */
12949                         stalloc(strlen(fullname) + 1);
12950                         /* NB: stalloc will return space pointed by fullname
12951                          * (because we don't have any intervening allocations
12952                          * between stunalloc above and this stalloc) */
12953                         readcmdfile(fullname);
12954                         cmdp = cmdlookup(name, 0);
12955                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12956                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12957                         stunalloc(fullname);
12958                         goto success;
12959                 }
12960                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12961                 if (!updatetbl) {
12962                         entry->cmdtype = CMDNORMAL;
12963                         entry->u.index = idx;
12964                         return;
12965                 }
12966                 INT_OFF;
12967                 cmdp = cmdlookup(name, 1);
12968                 cmdp->cmdtype = CMDNORMAL;
12969                 cmdp->param.index = idx;
12970                 INT_ON;
12971                 goto success;
12972         }
12973
12974         /* We failed.  If there was an entry for this command, delete it */
12975         if (cmdp && updatetbl)
12976                 delete_cmd_entry();
12977         if (act & DO_ERR)
12978                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12979         entry->cmdtype = CMDUNKNOWN;
12980         return;
12981
12982  builtin_success:
12983         if (!updatetbl) {
12984                 entry->cmdtype = CMDBUILTIN;
12985                 entry->u.cmd = bcmd;
12986                 return;
12987         }
12988         INT_OFF;
12989         cmdp = cmdlookup(name, 1);
12990         cmdp->cmdtype = CMDBUILTIN;
12991         cmdp->param.cmd = bcmd;
12992         INT_ON;
12993  success:
12994         cmdp->rehash = 0;
12995         entry->cmdtype = cmdp->cmdtype;
12996         entry->u = cmdp->param;
12997 }
12998
12999
13000 /*
13001  * The trap builtin.
13002  */
13003 static int FAST_FUNC
13004 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13005 {
13006         char *action;
13007         char **ap;
13008         int signo, exitcode;
13009
13010         nextopt(nullstr);
13011         ap = argptr;
13012         if (!*ap) {
13013                 for (signo = 0; signo < NSIG; signo++) {
13014                         char *tr = trap_ptr[signo];
13015                         if (tr) {
13016                                 /* note: bash adds "SIG", but only if invoked
13017                                  * as "bash". If called as "sh", or if set -o posix,
13018                                  * then it prints short signal names.
13019                                  * We are printing short names: */
13020                                 out1fmt("trap -- %s %s\n",
13021                                                 single_quote(tr),
13022                                                 get_signame(signo));
13023                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13024                  * In this case, we will exit very soon, no need to free(). */
13025                                 /* if (trap_ptr != trap && tp[0]) */
13026                                 /*      free(tr); */
13027                         }
13028                 }
13029                 /*
13030                 if (trap_ptr != trap) {
13031                         free(trap_ptr);
13032                         trap_ptr = trap;
13033                 }
13034                 */
13035                 return 0;
13036         }
13037
13038         /* Why the second check?
13039          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13040          * In this case, NUM is signal no, not an action.
13041          */
13042         action = NULL;
13043         if (ap[1] && !is_number(ap[0]))
13044                 action = *ap++;
13045
13046         exitcode = 0;
13047         while (*ap) {
13048                 signo = get_signum(*ap);
13049                 if (signo < 0) {
13050                         /* Mimic bash message exactly */
13051                         ash_msg("%s: invalid signal specification", *ap);
13052                         exitcode = 1;
13053                         goto next;
13054                 }
13055                 INT_OFF;
13056                 if (action) {
13057                         if (LONE_DASH(action))
13058                                 action = NULL;
13059                         else {
13060                                 if (action[0]) /* not NULL and not "" and not "-" */
13061                                         may_have_traps = 1;
13062                                 action = ckstrdup(action);
13063                         }
13064                 }
13065                 free(trap[signo]);
13066                 trap[signo] = action;
13067                 if (signo != 0)
13068                         setsignal(signo);
13069                 INT_ON;
13070  next:
13071                 ap++;
13072         }
13073         return exitcode;
13074 }
13075
13076
13077 /* ============ Builtins */
13078
13079 #if ENABLE_ASH_HELP
13080 static int FAST_FUNC
13081 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13082 {
13083         unsigned col;
13084         unsigned i;
13085
13086         out1fmt(
13087                 "Built-in commands:\n"
13088                 "------------------\n");
13089         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13090                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13091                                         builtintab[i].name + 1);
13092                 if (col > 60) {
13093                         out1fmt("\n");
13094                         col = 0;
13095                 }
13096         }
13097 # if ENABLE_FEATURE_SH_STANDALONE
13098         {
13099                 const char *a = applet_names;
13100                 while (*a) {
13101                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13102                         if (col > 60) {
13103                                 out1fmt("\n");
13104                                 col = 0;
13105                         }
13106                         while (*a++ != '\0')
13107                                 continue;
13108                 }
13109         }
13110 # endif
13111         newline_and_flush(stdout);
13112         return EXIT_SUCCESS;
13113 }
13114 #endif
13115
13116 #if MAX_HISTORY
13117 static int FAST_FUNC
13118 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13119 {
13120         show_history(line_input_state);
13121         return EXIT_SUCCESS;
13122 }
13123 #endif
13124
13125 /*
13126  * The export and readonly commands.
13127  */
13128 static int FAST_FUNC
13129 exportcmd(int argc UNUSED_PARAM, char **argv)
13130 {
13131         struct var *vp;
13132         char *name;
13133         const char *p;
13134         char **aptr;
13135         char opt;
13136         int flag;
13137         int flag_off;
13138
13139         /* "readonly" in bash accepts, but ignores -n.
13140          * We do the same: it saves a conditional in nextopt's param.
13141          */
13142         flag_off = 0;
13143         while ((opt = nextopt("np")) != '\0') {
13144                 if (opt == 'n')
13145                         flag_off = VEXPORT;
13146         }
13147         flag = VEXPORT;
13148         if (argv[0][0] == 'r') {
13149                 flag = VREADONLY;
13150                 flag_off = 0; /* readonly ignores -n */
13151         }
13152         flag_off = ~flag_off;
13153
13154         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13155         {
13156                 aptr = argptr;
13157                 name = *aptr;
13158                 if (name) {
13159                         do {
13160                                 p = strchr(name, '=');
13161                                 if (p != NULL) {
13162                                         p++;
13163                                 } else {
13164                                         vp = *findvar(hashvar(name), name);
13165                                         if (vp) {
13166                                                 vp->flags = ((vp->flags | flag) & flag_off);
13167                                                 continue;
13168                                         }
13169                                 }
13170                                 setvar(name, p, (flag & flag_off));
13171                         } while ((name = *++aptr) != NULL);
13172                         return 0;
13173                 }
13174         }
13175
13176         /* No arguments. Show the list of exported or readonly vars.
13177          * -n is ignored.
13178          */
13179         showvars(argv[0], flag, 0);
13180         return 0;
13181 }
13182
13183 /*
13184  * Delete a function if it exists.
13185  */
13186 static void
13187 unsetfunc(const char *name)
13188 {
13189         struct tblentry *cmdp;
13190
13191         cmdp = cmdlookup(name, 0);
13192         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13193                 delete_cmd_entry();
13194 }
13195
13196 /*
13197  * The unset builtin command.  We unset the function before we unset the
13198  * variable to allow a function to be unset when there is a readonly variable
13199  * with the same name.
13200  */
13201 static int FAST_FUNC
13202 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13203 {
13204         char **ap;
13205         int i;
13206         int flag = 0;
13207
13208         while ((i = nextopt("vf")) != 0) {
13209                 flag = i;
13210         }
13211
13212         for (ap = argptr; *ap; ap++) {
13213                 if (flag != 'f') {
13214                         unsetvar(*ap);
13215                         continue;
13216                 }
13217                 if (flag != 'v')
13218                         unsetfunc(*ap);
13219         }
13220         return 0;
13221 }
13222
13223 static const unsigned char timescmd_str[] ALIGN1 = {
13224         ' ',  offsetof(struct tms, tms_utime),
13225         '\n', offsetof(struct tms, tms_stime),
13226         ' ',  offsetof(struct tms, tms_cutime),
13227         '\n', offsetof(struct tms, tms_cstime),
13228         0
13229 };
13230 static int FAST_FUNC
13231 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13232 {
13233         unsigned long clk_tck, s, t;
13234         const unsigned char *p;
13235         struct tms buf;
13236
13237         clk_tck = bb_clk_tck();
13238         times(&buf);
13239
13240         p = timescmd_str;
13241         do {
13242                 t = *(clock_t *)(((char *) &buf) + p[1]);
13243                 s = t / clk_tck;
13244                 t = t % clk_tck;
13245                 out1fmt("%lum%lu.%03lus%c",
13246                         s / 60, s % 60,
13247                         (t * 1000) / clk_tck,
13248                         p[0]);
13249                 p += 2;
13250         } while (*p);
13251
13252         return 0;
13253 }
13254
13255 #if ENABLE_FEATURE_SH_MATH
13256 /*
13257  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13258  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13259  *
13260  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13261  */
13262 static int FAST_FUNC
13263 letcmd(int argc UNUSED_PARAM, char **argv)
13264 {
13265         arith_t i;
13266
13267         argv++;
13268         if (!*argv)
13269                 ash_msg_and_raise_error("expression expected");
13270         do {
13271                 i = ash_arith(*argv);
13272         } while (*++argv);
13273
13274         return !i;
13275 }
13276 #endif
13277
13278 /*
13279  * The read builtin. Options:
13280  *      -r              Do not interpret '\' specially
13281  *      -s              Turn off echo (tty only)
13282  *      -n NCHARS       Read NCHARS max
13283  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13284  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13285  *      -u FD           Read from given FD instead of fd 0
13286  * This uses unbuffered input, which may be avoidable in some cases.
13287  * TODO: bash also has:
13288  *      -a ARRAY        Read into array[0],[1],etc
13289  *      -d DELIM        End on DELIM char, not newline
13290  *      -e              Use line editing (tty only)
13291  */
13292 static int FAST_FUNC
13293 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13294 {
13295         char *opt_n = NULL;
13296         char *opt_p = NULL;
13297         char *opt_t = NULL;
13298         char *opt_u = NULL;
13299         int read_flags = 0;
13300         const char *r;
13301         int i;
13302
13303         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13304                 switch (i) {
13305                 case 'p':
13306                         opt_p = optionarg;
13307                         break;
13308                 case 'n':
13309                         opt_n = optionarg;
13310                         break;
13311                 case 's':
13312                         read_flags |= BUILTIN_READ_SILENT;
13313                         break;
13314                 case 't':
13315                         opt_t = optionarg;
13316                         break;
13317                 case 'r':
13318                         read_flags |= BUILTIN_READ_RAW;
13319                         break;
13320                 case 'u':
13321                         opt_u = optionarg;
13322                         break;
13323                 default:
13324                         break;
13325                 }
13326         }
13327
13328         /* "read -s" needs to save/restore termios, can't allow ^C
13329          * to jump out of it.
13330          */
13331  again:
13332         INT_OFF;
13333         r = shell_builtin_read(setvar0,
13334                 argptr,
13335                 bltinlookup("IFS"), /* can be NULL */
13336                 read_flags,
13337                 opt_n,
13338                 opt_p,
13339                 opt_t,
13340                 opt_u
13341         );
13342         INT_ON;
13343
13344         if ((uintptr_t)r == 1 && errno == EINTR) {
13345                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13346                 if (pending_sig == 0)
13347                         goto again;
13348         }
13349
13350         if ((uintptr_t)r > 1)
13351                 ash_msg_and_raise_error(r);
13352
13353         return (uintptr_t)r;
13354 }
13355
13356 static int FAST_FUNC
13357 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13358 {
13359         static const char permuser[3] ALIGN1 = "ogu";
13360
13361         mode_t mask;
13362         int symbolic_mode = 0;
13363
13364         while (nextopt("S") != '\0') {
13365                 symbolic_mode = 1;
13366         }
13367
13368         INT_OFF;
13369         mask = umask(0);
13370         umask(mask);
13371         INT_ON;
13372
13373         if (*argptr == NULL) {
13374                 if (symbolic_mode) {
13375                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13376                         char *p = buf;
13377                         int i;
13378
13379                         i = 2;
13380                         for (;;) {
13381                                 *p++ = ',';
13382                                 *p++ = permuser[i];
13383                                 *p++ = '=';
13384                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13385                                 if (!(mask & 0400)) *p++ = 'r';
13386                                 if (!(mask & 0200)) *p++ = 'w';
13387                                 if (!(mask & 0100)) *p++ = 'x';
13388                                 mask <<= 3;
13389                                 if (--i < 0)
13390                                         break;
13391                         }
13392                         *p = '\0';
13393                         puts(buf + 1);
13394                 } else {
13395                         out1fmt("%04o\n", mask);
13396                 }
13397         } else {
13398                 char *modestr = *argptr;
13399                 /* numeric umasks are taken as-is */
13400                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13401                 if (!isdigit(modestr[0]))
13402                         mask ^= 0777;
13403                 mask = bb_parse_mode(modestr, mask);
13404                 if ((unsigned)mask > 0777) {
13405                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13406                 }
13407                 if (!isdigit(modestr[0]))
13408                         mask ^= 0777;
13409                 umask(mask);
13410         }
13411         return 0;
13412 }
13413
13414 static int FAST_FUNC
13415 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13416 {
13417         return shell_builtin_ulimit(argv);
13418 }
13419
13420 /* ============ main() and helpers */
13421
13422 /*
13423  * Called to exit the shell.
13424  */
13425 static void
13426 exitshell(void)
13427 {
13428         struct jmploc loc;
13429         char *p;
13430         int status;
13431
13432 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13433         save_history(line_input_state);
13434 #endif
13435         status = exitstatus;
13436         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13437         if (setjmp(loc.loc)) {
13438                 if (exception_type == EXEXIT)
13439                         status = exitstatus;
13440                 goto out;
13441         }
13442         exception_handler = &loc;
13443         p = trap[0];
13444         if (p) {
13445                 trap[0] = NULL;
13446                 evalskip = 0;
13447                 evalstring(p, 0);
13448                 /*free(p); - we'll exit soon */
13449         }
13450  out:
13451         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13452          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13453          */
13454         setjobctl(0);
13455         flush_stdout_stderr();
13456         _exit(status);
13457         /* NOTREACHED */
13458 }
13459
13460 static void
13461 init(void)
13462 {
13463         /* we will never free this */
13464         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13465
13466         sigmode[SIGCHLD - 1] = S_DFL;
13467         setsignal(SIGCHLD);
13468
13469         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13470          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13471          */
13472         signal(SIGHUP, SIG_DFL);
13473
13474         {
13475                 char **envp;
13476                 const char *p;
13477                 struct stat st1, st2;
13478
13479                 initvar();
13480                 for (envp = environ; envp && *envp; envp++) {
13481                         p = endofname(*envp);
13482                         if (p != *envp && *p == '=') {
13483                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13484                         }
13485                 }
13486
13487                 setvareq((char*)defoptindvar, VTEXTFIXED);
13488
13489                 setvar0("PPID", utoa(getppid()));
13490 #if BASH_SHLVL_VAR
13491                 p = lookupvar("SHLVL");
13492                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13493 #endif
13494 #if BASH_HOSTNAME_VAR
13495                 if (!lookupvar("HOSTNAME")) {
13496                         struct utsname uts;
13497                         uname(&uts);
13498                         setvar0("HOSTNAME", uts.nodename);
13499                 }
13500 #endif
13501                 p = lookupvar("PWD");
13502                 if (p) {
13503                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13504                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13505                         ) {
13506                                 p = NULL;
13507                         }
13508                 }
13509                 setpwd(p, 0);
13510         }
13511 }
13512
13513
13514 //usage:#define ash_trivial_usage
13515 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13516 //usage:#define ash_full_usage "\n\n"
13517 //usage:        "Unix shell interpreter"
13518
13519 /*
13520  * Process the shell command line arguments.
13521  */
13522 static void
13523 procargs(char **argv)
13524 {
13525         int i;
13526         const char *xminusc;
13527         char **xargv;
13528
13529         xargv = argv;
13530         arg0 = xargv[0];
13531         /* if (xargv[0]) - mmm, this is always true! */
13532                 xargv++;
13533         for (i = 0; i < NOPTS; i++)
13534                 optlist[i] = 2;
13535         argptr = xargv;
13536         if (options(/*cmdline:*/ 1)) {
13537                 /* it already printed err message */
13538                 raise_exception(EXERROR);
13539         }
13540         xargv = argptr;
13541         xminusc = minusc;
13542         if (*xargv == NULL) {
13543                 if (xminusc)
13544                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13545                 sflag = 1;
13546         }
13547         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13548                 iflag = 1;
13549         if (mflag == 2)
13550                 mflag = iflag;
13551         for (i = 0; i < NOPTS; i++)
13552                 if (optlist[i] == 2)
13553                         optlist[i] = 0;
13554 #if DEBUG == 2
13555         debug = 1;
13556 #endif
13557         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13558         if (xminusc) {
13559                 minusc = *xargv++;
13560                 if (*xargv)
13561                         goto setarg0;
13562         } else if (!sflag) {
13563                 setinputfile(*xargv, 0);
13564  setarg0:
13565                 arg0 = *xargv++;
13566                 commandname = arg0;
13567         }
13568
13569         shellparam.p = xargv;
13570 #if ENABLE_ASH_GETOPTS
13571         shellparam.optind = 1;
13572         shellparam.optoff = -1;
13573 #endif
13574         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13575         while (*xargv) {
13576                 shellparam.nparam++;
13577                 xargv++;
13578         }
13579         optschanged();
13580 }
13581
13582 /*
13583  * Read /etc/profile, ~/.profile, $ENV.
13584  */
13585 static void
13586 read_profile(const char *name)
13587 {
13588         name = expandstr(name);
13589         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13590                 return;
13591         cmdloop(0);
13592         popfile();
13593 }
13594
13595 /*
13596  * This routine is called when an error or an interrupt occurs in an
13597  * interactive shell and control is returned to the main command loop.
13598  * (In dash, this function is auto-generated by build machinery).
13599  */
13600 static void
13601 reset(void)
13602 {
13603         /* from eval.c: */
13604         evalskip = 0;
13605         loopnest = 0;
13606
13607         /* from expand.c: */
13608         ifsfree();
13609
13610         /* from input.c: */
13611         g_parsefile->left_in_buffer = 0;
13612         g_parsefile->left_in_line = 0;      /* clear input buffer */
13613         popallfiles();
13614
13615         /* from redir.c: */
13616         while (redirlist)
13617                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13618
13619         /* from var.c: */
13620         unwindlocalvars(NULL);
13621 }
13622
13623 #if PROFILE
13624 static short profile_buf[16384];
13625 extern int etext();
13626 #endif
13627
13628 /*
13629  * Main routine.  We initialize things, parse the arguments, execute
13630  * profiles if we're a login shell, and then call cmdloop to execute
13631  * commands.  The setjmp call sets up the location to jump to when an
13632  * exception occurs.  When an exception occurs the variable "state"
13633  * is used to figure out how far we had gotten.
13634  */
13635 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13636 int ash_main(int argc UNUSED_PARAM, char **argv)
13637 {
13638         volatile smallint state;
13639         struct jmploc jmploc;
13640         struct stackmark smark;
13641
13642         /* Initialize global data */
13643         INIT_G_misc();
13644         INIT_G_memstack();
13645         INIT_G_var();
13646 #if ENABLE_ASH_ALIAS
13647         INIT_G_alias();
13648 #endif
13649         INIT_G_cmdtable();
13650
13651 #if PROFILE
13652         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13653 #endif
13654
13655 #if ENABLE_FEATURE_EDITING
13656         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13657 #endif
13658         state = 0;
13659         if (setjmp(jmploc.loc)) {
13660                 smallint e;
13661                 smallint s;
13662
13663                 reset();
13664
13665                 e = exception_type;
13666                 s = state;
13667                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13668                         exitshell();
13669                 }
13670                 if (e == EXINT) {
13671                         newline_and_flush(stderr);
13672                 }
13673
13674                 popstackmark(&smark);
13675                 FORCE_INT_ON; /* enable interrupts */
13676                 if (s == 1)
13677                         goto state1;
13678                 if (s == 2)
13679                         goto state2;
13680                 if (s == 3)
13681                         goto state3;
13682                 goto state4;
13683         }
13684         exception_handler = &jmploc;
13685         rootpid = getpid();
13686
13687         init();
13688         setstackmark(&smark);
13689         procargs(argv);
13690 #if DEBUG
13691         TRACE(("Shell args: "));
13692         trace_puts_args(argv);
13693 #endif
13694
13695         if (argv[0] && argv[0][0] == '-')
13696                 isloginsh = 1;
13697         if (isloginsh) {
13698                 const char *hp;
13699
13700                 state = 1;
13701                 read_profile("/etc/profile");
13702  state1:
13703                 state = 2;
13704                 hp = lookupvar("HOME");
13705                 if (hp)
13706                         read_profile("$HOME/.profile");
13707         }
13708  state2:
13709         state = 3;
13710         if (
13711 #ifndef linux
13712          getuid() == geteuid() && getgid() == getegid() &&
13713 #endif
13714          iflag
13715         ) {
13716                 const char *shinit = lookupvar("ENV");
13717                 if (shinit != NULL && *shinit != '\0')
13718                         read_profile(shinit);
13719         }
13720         popstackmark(&smark);
13721  state3:
13722         state = 4;
13723         if (minusc) {
13724                 /* evalstring pushes parsefile stack.
13725                  * Ensure we don't falsely claim that 0 (stdin)
13726                  * is one of stacked source fds.
13727                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13728                 // if (!sflag) g_parsefile->pf_fd = -1;
13729                 // ^^ not necessary since now we special-case fd 0
13730                 // in is_hidden_fd() to not be considered "hidden fd"
13731                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13732         }
13733
13734         if (sflag || minusc == NULL) {
13735 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13736                 if (iflag) {
13737                         const char *hp = lookupvar("HISTFILE");
13738                         if (!hp) {
13739                                 hp = lookupvar("HOME");
13740                                 if (hp) {
13741                                         INT_OFF;
13742                                         hp = concat_path_file(hp, ".ash_history");
13743                                         setvar0("HISTFILE", hp);
13744                                         free((char*)hp);
13745                                         INT_ON;
13746                                         hp = lookupvar("HISTFILE");
13747                                 }
13748                         }
13749                         if (hp)
13750                                 line_input_state->hist_file = hp;
13751 # if ENABLE_FEATURE_SH_HISTFILESIZE
13752                         hp = lookupvar("HISTFILESIZE");
13753                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13754 # endif
13755                 }
13756 #endif
13757  state4: /* XXX ??? - why isn't this before the "if" statement */
13758                 cmdloop(1);
13759         }
13760 #if PROFILE
13761         monitor(0);
13762 #endif
13763 #ifdef GPROF
13764         {
13765                 extern void _mcleanup(void);
13766                 _mcleanup();
13767         }
13768 #endif
13769         TRACE(("End of main reached\n"));
13770         exitshell();
13771         /* NOTREACHED */
13772 }
13773
13774
13775 /*-
13776  * Copyright (c) 1989, 1991, 1993, 1994
13777  *      The Regents of the University of California.  All rights reserved.
13778  *
13779  * This code is derived from software contributed to Berkeley by
13780  * Kenneth Almquist.
13781  *
13782  * Redistribution and use in source and binary forms, with or without
13783  * modification, are permitted provided that the following conditions
13784  * are met:
13785  * 1. Redistributions of source code must retain the above copyright
13786  *    notice, this list of conditions and the following disclaimer.
13787  * 2. Redistributions in binary form must reproduce the above copyright
13788  *    notice, this list of conditions and the following disclaimer in the
13789  *    documentation and/or other materials provided with the distribution.
13790  * 3. Neither the name of the University nor the names of its contributors
13791  *    may be used to endorse or promote products derived from this software
13792  *    without specific prior written permission.
13793  *
13794  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13795  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13796  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13797  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13798  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13799  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13800  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13801  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13802  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13803  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13804  * SUCH DAMAGE.
13805  */