ash: [REDIR] Fix popredir on abnormal exit from built-in
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps, int syntax_type);
2492 /* Values for syntax param */
2493 #define BASESYNTAX 0    /* not in quotes */
2494 #define DQSYNTAX   1    /* in double quotes */
2495 #define SQSYNTAX   2    /* in single quotes */
2496 #define ARISYNTAX  3    /* in arithmetic */
2497 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2498 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2499
2500 /*
2501  * called by editline -- any expansions to the prompt should be added here.
2502  */
2503 static void
2504 setprompt_if(smallint do_set, int whichprompt)
2505 {
2506         const char *prompt;
2507         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2508
2509         if (!do_set)
2510                 return;
2511
2512         needprompt = 0;
2513
2514         switch (whichprompt) {
2515         case 1:
2516                 prompt = ps1val();
2517                 break;
2518         case 2:
2519                 prompt = ps2val();
2520                 break;
2521         default:                        /* 0 */
2522                 prompt = nullstr;
2523         }
2524 #if ENABLE_ASH_EXPAND_PRMT
2525         pushstackmark(&smark, stackblocksize());
2526         putprompt(expandstr(prompt, PSSYNTAX));
2527         popstackmark(&smark);
2528 #else
2529         putprompt(prompt);
2530 #endif
2531 }
2532
2533
2534 /* ============ The cd and pwd commands */
2535
2536 #define CD_PHYSICAL 1
2537 #define CD_PRINT 2
2538
2539 static int
2540 cdopt(void)
2541 {
2542         int flags = 0;
2543         int i, j;
2544
2545         j = 'L';
2546         while ((i = nextopt("LP")) != '\0') {
2547                 if (i != j) {
2548                         flags ^= CD_PHYSICAL;
2549                         j = i;
2550                 }
2551         }
2552
2553         return flags;
2554 }
2555
2556 /*
2557  * Update curdir (the name of the current directory) in response to a
2558  * cd command.
2559  */
2560 static const char *
2561 updatepwd(const char *dir)
2562 {
2563         char *new;
2564         char *p;
2565         char *cdcomppath;
2566         const char *lim;
2567
2568         cdcomppath = sstrdup(dir);
2569         STARTSTACKSTR(new);
2570         if (*dir != '/') {
2571                 if (curdir == nullstr)
2572                         return 0;
2573                 new = stack_putstr(curdir, new);
2574         }
2575         new = makestrspace(strlen(dir) + 2, new);
2576         lim = (char *)stackblock() + 1;
2577         if (*dir != '/') {
2578                 if (new[-1] != '/')
2579                         USTPUTC('/', new);
2580                 if (new > lim && *lim == '/')
2581                         lim++;
2582         } else {
2583                 USTPUTC('/', new);
2584                 cdcomppath++;
2585                 if (dir[1] == '/' && dir[2] != '/') {
2586                         USTPUTC('/', new);
2587                         cdcomppath++;
2588                         lim++;
2589                 }
2590         }
2591         p = strtok(cdcomppath, "/");
2592         while (p) {
2593                 switch (*p) {
2594                 case '.':
2595                         if (p[1] == '.' && p[2] == '\0') {
2596                                 while (new > lim) {
2597                                         STUNPUTC(new);
2598                                         if (new[-1] == '/')
2599                                                 break;
2600                                 }
2601                                 break;
2602                         }
2603                         if (p[1] == '\0')
2604                                 break;
2605                         /* fall through */
2606                 default:
2607                         new = stack_putstr(p, new);
2608                         USTPUTC('/', new);
2609                 }
2610                 p = strtok(NULL, "/");
2611         }
2612         if (new > lim)
2613                 STUNPUTC(new);
2614         *new = 0;
2615         return stackblock();
2616 }
2617
2618 /*
2619  * Find out what the current directory is. If we already know the current
2620  * directory, this routine returns immediately.
2621  */
2622 static char *
2623 getpwd(void)
2624 {
2625         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2626         return dir ? dir : nullstr;
2627 }
2628
2629 static void
2630 setpwd(const char *val, int setold)
2631 {
2632         char *oldcur, *dir;
2633
2634         oldcur = dir = curdir;
2635
2636         if (setold) {
2637                 setvar("OLDPWD", oldcur, VEXPORT);
2638         }
2639         INT_OFF;
2640         if (physdir != nullstr) {
2641                 if (physdir != oldcur)
2642                         free(physdir);
2643                 physdir = nullstr;
2644         }
2645         if (oldcur == val || !val) {
2646                 char *s = getpwd();
2647                 physdir = s;
2648                 if (!val)
2649                         dir = s;
2650         } else
2651                 dir = ckstrdup(val);
2652         if (oldcur != dir && oldcur != nullstr) {
2653                 free(oldcur);
2654         }
2655         curdir = dir;
2656         INT_ON;
2657         setvar("PWD", dir, VEXPORT);
2658 }
2659
2660 static void hashcd(void);
2661
2662 /*
2663  * Actually do the chdir.  We also call hashcd to let other routines
2664  * know that the current directory has changed.
2665  */
2666 static int
2667 docd(const char *dest, int flags)
2668 {
2669         const char *dir = NULL;
2670         int err;
2671
2672         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2673
2674         INT_OFF;
2675         if (!(flags & CD_PHYSICAL)) {
2676                 dir = updatepwd(dest);
2677                 if (dir)
2678                         dest = dir;
2679         }
2680         err = chdir(dest);
2681         if (err)
2682                 goto out;
2683         setpwd(dir, 1);
2684         hashcd();
2685  out:
2686         INT_ON;
2687         return err;
2688 }
2689
2690 static int FAST_FUNC
2691 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2692 {
2693         const char *dest;
2694         const char *path;
2695         const char *p;
2696         char c;
2697         struct stat statb;
2698         int flags;
2699
2700         flags = cdopt();
2701         dest = *argptr;
2702         if (!dest)
2703                 dest = bltinlookup("HOME");
2704         else if (LONE_DASH(dest)) {
2705                 dest = bltinlookup("OLDPWD");
2706                 flags |= CD_PRINT;
2707         }
2708         if (!dest)
2709                 dest = nullstr;
2710         if (*dest == '/')
2711                 goto step6;
2712         if (*dest == '.') {
2713                 c = dest[1];
2714  dotdot:
2715                 switch (c) {
2716                 case '\0':
2717                 case '/':
2718                         goto step6;
2719                 case '.':
2720                         c = dest[2];
2721                         if (c != '.')
2722                                 goto dotdot;
2723                 }
2724         }
2725         if (!*dest)
2726                 dest = ".";
2727         path = bltinlookup("CDPATH");
2728         while (path) {
2729                 c = *path;
2730                 p = path_advance(&path, dest);
2731                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2732                         if (c && c != ':')
2733                                 flags |= CD_PRINT;
2734  docd:
2735                         if (!docd(p, flags))
2736                                 goto out;
2737                         goto err;
2738                 }
2739         }
2740
2741  step6:
2742         p = dest;
2743         goto docd;
2744
2745  err:
2746         ash_msg_and_raise_error("can't cd to %s", dest);
2747         /* NOTREACHED */
2748  out:
2749         if (flags & CD_PRINT)
2750                 out1fmt("%s\n", curdir);
2751         return 0;
2752 }
2753
2754 static int FAST_FUNC
2755 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2756 {
2757         int flags;
2758         const char *dir = curdir;
2759
2760         flags = cdopt();
2761         if (flags) {
2762                 if (physdir == nullstr)
2763                         setpwd(dir, 0);
2764                 dir = physdir;
2765         }
2766         out1fmt("%s\n", dir);
2767         return 0;
2768 }
2769
2770
2771 /* ============ ... */
2772
2773
2774 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2775
2776 /* Syntax classes */
2777 #define CWORD     0             /* character is nothing special */
2778 #define CNL       1             /* newline character */
2779 #define CBACK     2             /* a backslash character */
2780 #define CSQUOTE   3             /* single quote */
2781 #define CDQUOTE   4             /* double quote */
2782 #define CENDQUOTE 5             /* a terminating quote */
2783 #define CBQUOTE   6             /* backwards single quote */
2784 #define CVAR      7             /* a dollar sign */
2785 #define CENDVAR   8             /* a '}' character */
2786 #define CLP       9             /* a left paren in arithmetic */
2787 #define CRP      10             /* a right paren in arithmetic */
2788 #define CENDFILE 11             /* end of file */
2789 #define CCTL     12             /* like CWORD, except it must be escaped */
2790 #define CSPCL    13             /* these terminate a word */
2791 #define CIGN     14             /* character should be ignored */
2792
2793 #define PEOF     256
2794 #if ENABLE_ASH_ALIAS
2795 # define PEOA    257
2796 #endif
2797
2798 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2799
2800 #if ENABLE_FEATURE_SH_MATH
2801 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2802 #else
2803 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2804 #endif
2805 static const uint16_t S_I_T[] ALIGN2 = {
2806 #if ENABLE_ASH_ALIAS
2807         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2808 #endif
2809         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2810         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2811         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2812         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2813         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2814         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2815         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2816         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2817         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2818         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2819         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2820 #if !USE_SIT_FUNCTION
2821         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2822         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2823         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2824 #endif
2825 #undef SIT_ITEM
2826 };
2827 /* Constants below must match table above */
2828 enum {
2829 #if ENABLE_ASH_ALIAS
2830         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2831 #endif
2832         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2833         CNL_CNL_CNL_CNL                    , /*  2 */
2834         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2835         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2836         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2837         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2838         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2839         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2840         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2841         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2842         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2843         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2844         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2845         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2846 };
2847
2848 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2849  * caller must ensure proper cast on it if c is *char_ptr!
2850  */
2851 #if USE_SIT_FUNCTION
2852
2853 static int
2854 SIT(int c, int syntax)
2855 {
2856         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2857         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2858         /*
2859          * This causes '/' to be prepended with CTLESC in dquoted string,
2860          * making "./file"* treated incorrectly because we feed
2861          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2862          * The "homegrown" glob implementation is okay with that,
2863          * but glibc one isn't. With '/' always treated as CWORD,
2864          * both work fine.
2865          */
2866 # if ENABLE_ASH_ALIAS
2867         static const uint8_t syntax_index_table[] ALIGN1 = {
2868                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2869                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2870                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2871                 11, 3                           /* "}~" */
2872         };
2873 # else
2874         static const uint8_t syntax_index_table[] ALIGN1 = {
2875                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2876                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2877                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2878                 10, 2                           /* "}~" */
2879         };
2880 # endif
2881         const char *s;
2882         int indx;
2883
2884         if (c == PEOF)
2885                 return CENDFILE;
2886 # if ENABLE_ASH_ALIAS
2887         if (c == PEOA)
2888                 indx = 0;
2889         else
2890 # endif
2891         {
2892                 /* Cast is purely for paranoia here,
2893                  * just in case someone passed signed char to us */
2894                 if ((unsigned char)c >= CTL_FIRST
2895                  && (unsigned char)c <= CTL_LAST
2896                 ) {
2897                         return CCTL;
2898                 }
2899                 s = strchrnul(spec_symbls, c);
2900                 if (*s == '\0')
2901                         return CWORD;
2902                 indx = syntax_index_table[s - spec_symbls];
2903         }
2904         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2905 }
2906
2907 #else   /* !USE_SIT_FUNCTION */
2908
2909 static const uint8_t syntax_index_table[] ALIGN1 = {
2910         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2911         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2912         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2913         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2921         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2922         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2944         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2945         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2946         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2948         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2950         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2951         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2952         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2953         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2954         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2956         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2957         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2958 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2959         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2971         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2972         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2973         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2974         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2975         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3004         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3005         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3006         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3009         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3011         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3037         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3038         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3039         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3040         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3041         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3042         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3043         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3044         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3045         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3046         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3047         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3048         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3049         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3168         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3169 # if ENABLE_ASH_ALIAS
3170         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3171 # endif
3172 };
3173
3174 #if 1
3175 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3176 #else /* debug version, caught one signed char bug */
3177 # define SIT(c, syntax) \
3178         ({ \
3179                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3180                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3181                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3182                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3183                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3184         })
3185 #endif
3186
3187 #endif  /* !USE_SIT_FUNCTION */
3188
3189
3190 /* ============ Alias handling */
3191
3192 #if ENABLE_ASH_ALIAS
3193
3194 #define ALIASINUSE 1
3195 #define ALIASDEAD  2
3196
3197 struct alias {
3198         struct alias *next;
3199         char *name;
3200         char *val;
3201         int flag;
3202 };
3203
3204
3205 static struct alias **atab; // [ATABSIZE];
3206 #define INIT_G_alias() do { \
3207         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3208 } while (0)
3209
3210
3211 static struct alias **
3212 __lookupalias(const char *name)
3213 {
3214         unsigned int hashval;
3215         struct alias **app;
3216         const char *p;
3217         unsigned int ch;
3218
3219         p = name;
3220
3221         ch = (unsigned char)*p;
3222         hashval = ch << 4;
3223         while (ch) {
3224                 hashval += ch;
3225                 ch = (unsigned char)*++p;
3226         }
3227         app = &atab[hashval % ATABSIZE];
3228
3229         for (; *app; app = &(*app)->next) {
3230                 if (strcmp(name, (*app)->name) == 0) {
3231                         break;
3232                 }
3233         }
3234
3235         return app;
3236 }
3237
3238 static struct alias *
3239 lookupalias(const char *name, int check)
3240 {
3241         struct alias *ap = *__lookupalias(name);
3242
3243         if (check && ap && (ap->flag & ALIASINUSE))
3244                 return NULL;
3245         return ap;
3246 }
3247
3248 static struct alias *
3249 freealias(struct alias *ap)
3250 {
3251         struct alias *next;
3252
3253         if (ap->flag & ALIASINUSE) {
3254                 ap->flag |= ALIASDEAD;
3255                 return ap;
3256         }
3257
3258         next = ap->next;
3259         free(ap->name);
3260         free(ap->val);
3261         free(ap);
3262         return next;
3263 }
3264
3265 static void
3266 setalias(const char *name, const char *val)
3267 {
3268         struct alias *ap, **app;
3269
3270         app = __lookupalias(name);
3271         ap = *app;
3272         INT_OFF;
3273         if (ap) {
3274                 if (!(ap->flag & ALIASINUSE)) {
3275                         free(ap->val);
3276                 }
3277                 ap->val = ckstrdup(val);
3278                 ap->flag &= ~ALIASDEAD;
3279         } else {
3280                 /* not found */
3281                 ap = ckzalloc(sizeof(struct alias));
3282                 ap->name = ckstrdup(name);
3283                 ap->val = ckstrdup(val);
3284                 /*ap->flag = 0; - ckzalloc did it */
3285                 /*ap->next = NULL;*/
3286                 *app = ap;
3287         }
3288         INT_ON;
3289 }
3290
3291 static int
3292 unalias(const char *name)
3293 {
3294         struct alias **app;
3295
3296         app = __lookupalias(name);
3297
3298         if (*app) {
3299                 INT_OFF;
3300                 *app = freealias(*app);
3301                 INT_ON;
3302                 return 0;
3303         }
3304
3305         return 1;
3306 }
3307
3308 static void
3309 rmaliases(void)
3310 {
3311         struct alias *ap, **app;
3312         int i;
3313
3314         INT_OFF;
3315         for (i = 0; i < ATABSIZE; i++) {
3316                 app = &atab[i];
3317                 for (ap = *app; ap; ap = *app) {
3318                         *app = freealias(*app);
3319                         if (ap == *app) {
3320                                 app = &ap->next;
3321                         }
3322                 }
3323         }
3324         INT_ON;
3325 }
3326
3327 static void
3328 printalias(const struct alias *ap)
3329 {
3330         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3331 }
3332
3333 /*
3334  * TODO - sort output
3335  */
3336 static int FAST_FUNC
3337 aliascmd(int argc UNUSED_PARAM, char **argv)
3338 {
3339         char *n, *v;
3340         int ret = 0;
3341         struct alias *ap;
3342
3343         if (!argv[1]) {
3344                 int i;
3345
3346                 for (i = 0; i < ATABSIZE; i++) {
3347                         for (ap = atab[i]; ap; ap = ap->next) {
3348                                 printalias(ap);
3349                         }
3350                 }
3351                 return 0;
3352         }
3353         while ((n = *++argv) != NULL) {
3354                 v = strchr(n+1, '=');
3355                 if (v == NULL) { /* n+1: funny ksh stuff */
3356                         ap = *__lookupalias(n);
3357                         if (ap == NULL) {
3358                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3359                                 ret = 1;
3360                         } else
3361                                 printalias(ap);
3362                 } else {
3363                         *v++ = '\0';
3364                         setalias(n, v);
3365                 }
3366         }
3367
3368         return ret;
3369 }
3370
3371 static int FAST_FUNC
3372 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3373 {
3374         int i;
3375
3376         while (nextopt("a") != '\0') {
3377                 rmaliases();
3378                 return 0;
3379         }
3380         for (i = 0; *argptr; argptr++) {
3381                 if (unalias(*argptr)) {
3382                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3383                         i = 1;
3384                 }
3385         }
3386
3387         return i;
3388 }
3389
3390 #endif /* ASH_ALIAS */
3391
3392
3393 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3394 #define FORK_FG    0
3395 #define FORK_BG    1
3396 #define FORK_NOJOB 2
3397
3398 /* mode flags for showjob(s) */
3399 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3400 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3401 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3402 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3403
3404 /*
3405  * A job structure contains information about a job.  A job is either a
3406  * single process or a set of processes contained in a pipeline.  In the
3407  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3408  * array of pids.
3409  */
3410 struct procstat {
3411         pid_t   ps_pid;         /* process id */
3412         int     ps_status;      /* last process status from wait() */
3413         char    *ps_cmd;        /* text of command being run */
3414 };
3415
3416 struct job {
3417         struct procstat ps0;    /* status of process */
3418         struct procstat *ps;    /* status or processes when more than one */
3419 #if JOBS
3420         int stopstatus;         /* status of a stopped job */
3421 #endif
3422         unsigned nprocs;        /* number of processes */
3423
3424 #define JOBRUNNING      0       /* at least one proc running */
3425 #define JOBSTOPPED      1       /* all procs are stopped */
3426 #define JOBDONE         2       /* all procs are completed */
3427         unsigned
3428                 state: 8,
3429 #if JOBS
3430                 sigint: 1,      /* job was killed by SIGINT */
3431                 jobctl: 1,      /* job running under job control */
3432 #endif
3433                 waited: 1,      /* true if this entry has been waited for */
3434                 used: 1,        /* true if this entry is in used */
3435                 changed: 1;     /* true if status has changed */
3436         struct job *prev_job;   /* previous job */
3437 };
3438
3439 static struct job *makejob(/*union node *,*/ int);
3440 static int forkshell(struct job *, union node *, int);
3441 static int waitforjob(struct job *);
3442
3443 #if !JOBS
3444 enum { doing_jobctl = 0 };
3445 #define setjobctl(on) do {} while (0)
3446 #else
3447 static smallint doing_jobctl; //references:8
3448 static void setjobctl(int);
3449 #endif
3450
3451 /*
3452  * Ignore a signal.
3453  */
3454 static void
3455 ignoresig(int signo)
3456 {
3457         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3458         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3459                 /* No, need to do it */
3460                 signal(signo, SIG_IGN);
3461         }
3462         sigmode[signo - 1] = S_HARD_IGN;
3463 }
3464
3465 /*
3466  * Only one usage site - in setsignal()
3467  */
3468 static void
3469 signal_handler(int signo)
3470 {
3471         if (signo == SIGCHLD) {
3472                 got_sigchld = 1;
3473                 if (!trap[SIGCHLD])
3474                         return;
3475         }
3476
3477         gotsig[signo - 1] = 1;
3478         pending_sig = signo;
3479
3480         if (signo == SIGINT && !trap[SIGINT]) {
3481                 if (!suppress_int) {
3482                         pending_sig = 0;
3483                         raise_interrupt(); /* does not return */
3484                 }
3485                 pending_int = 1;
3486         }
3487 }
3488
3489 /*
3490  * Set the signal handler for the specified signal.  The routine figures
3491  * out what it should be set to.
3492  */
3493 static void
3494 setsignal(int signo)
3495 {
3496         char *t;
3497         char cur_act, new_act;
3498         struct sigaction act;
3499
3500         t = trap[signo];
3501         new_act = S_DFL;
3502         if (t != NULL) { /* trap for this sig is set */
3503                 new_act = S_CATCH;
3504                 if (t[0] == '\0') /* trap is "": ignore this sig */
3505                         new_act = S_IGN;
3506         }
3507
3508         if (rootshell && new_act == S_DFL) {
3509                 switch (signo) {
3510                 case SIGINT:
3511                         if (iflag || minusc || sflag == 0)
3512                                 new_act = S_CATCH;
3513                         break;
3514                 case SIGQUIT:
3515 #if DEBUG
3516                         if (debug)
3517                                 break;
3518 #endif
3519                         /* man bash:
3520                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3521                          * commands run by bash have signal handlers
3522                          * set to the values inherited by the shell
3523                          * from its parent". */
3524                         new_act = S_IGN;
3525                         break;
3526                 case SIGTERM:
3527                         if (iflag)
3528                                 new_act = S_IGN;
3529                         break;
3530 #if JOBS
3531                 case SIGTSTP:
3532                 case SIGTTOU:
3533                         if (mflag)
3534                                 new_act = S_IGN;
3535                         break;
3536 #endif
3537                 }
3538         }
3539 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3540 //whereas we have to restore it to what shell got on entry
3541 //from the parent. See comment above
3542
3543         if (signo == SIGCHLD)
3544                 new_act = S_CATCH;
3545
3546         t = &sigmode[signo - 1];
3547         cur_act = *t;
3548         if (cur_act == 0) {
3549                 /* current setting is not yet known */
3550                 if (sigaction(signo, NULL, &act)) {
3551                         /* pretend it worked; maybe we should give a warning,
3552                          * but other shells don't. We don't alter sigmode,
3553                          * so we retry every time.
3554                          * btw, in Linux it never fails. --vda */
3555                         return;
3556                 }
3557                 if (act.sa_handler == SIG_IGN) {
3558                         cur_act = S_HARD_IGN;
3559                         if (mflag
3560                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3561                         ) {
3562                                 cur_act = S_IGN;   /* don't hard ignore these */
3563                         }
3564                 }
3565         }
3566         if (cur_act == S_HARD_IGN || cur_act == new_act)
3567                 return;
3568
3569         act.sa_handler = SIG_DFL;
3570         switch (new_act) {
3571         case S_CATCH:
3572                 act.sa_handler = signal_handler;
3573                 break;
3574         case S_IGN:
3575                 act.sa_handler = SIG_IGN;
3576                 break;
3577         }
3578
3579         /* flags and mask matter only if !DFL and !IGN, but we do it
3580          * for all cases for more deterministic behavior:
3581          */
3582         act.sa_flags = 0;
3583         sigfillset(&act.sa_mask);
3584
3585         sigaction_set(signo, &act);
3586
3587         *t = new_act;
3588 }
3589
3590 /* mode flags for set_curjob */
3591 #define CUR_DELETE 2
3592 #define CUR_RUNNING 1
3593 #define CUR_STOPPED 0
3594
3595 #if JOBS
3596 /* pgrp of shell on invocation */
3597 static int initialpgrp; //references:2
3598 static int ttyfd = -1; //5
3599 #endif
3600 /* array of jobs */
3601 static struct job *jobtab; //5
3602 /* size of array */
3603 static unsigned njobs; //4
3604 /* current job */
3605 static struct job *curjob; //lots
3606 /* number of presumed living untracked jobs */
3607 static int jobless; //4
3608
3609 #if 0
3610 /* Bash has a feature: it restores termios after a successful wait for
3611  * a foreground job which had at least one stopped or sigkilled member.
3612  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3613  * properly restoring tty state. Should we do this too?
3614  * A reproducer: ^Z an interactive python:
3615  *
3616  * # python
3617  * Python 2.7.12 (...)
3618  * >>> ^Z
3619  *      { python leaves tty in -icanon -echo state. We do survive that... }
3620  *  [1]+  Stopped                    python
3621  *      { ...however, next program (python #2) does not survive it well: }
3622  * # python
3623  * Python 2.7.12 (...)
3624  * >>> Traceback (most recent call last):
3625  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3626  *   File "<stdin>", line 1, in <module>
3627  * NameError: name 'qwerty' is not defined
3628  *
3629  * The implementation below is modeled on bash code and seems to work.
3630  * However, I'm not sure we should do this. For one: what if I'd fg
3631  * the stopped python instead? It'll be confused by "restored" tty state.
3632  */
3633 static struct termios shell_tty_info;
3634 static void
3635 get_tty_state(void)
3636 {
3637         if (rootshell && ttyfd >= 0)
3638                 tcgetattr(ttyfd, &shell_tty_info);
3639 }
3640 static void
3641 set_tty_state(void)
3642 {
3643         /* if (rootshell) - caller ensures this */
3644         if (ttyfd >= 0)
3645                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3646 }
3647 static int
3648 job_signal_status(struct job *jp)
3649 {
3650         int status;
3651         unsigned i;
3652         struct procstat *ps = jp->ps;
3653         for (i = 0; i < jp->nprocs; i++) {
3654                 status = ps[i].ps_status;
3655                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3656                         return status;
3657         }
3658         return 0;
3659 }
3660 static void
3661 restore_tty_if_stopped_or_signaled(struct job *jp)
3662 {
3663 //TODO: check what happens if we come from waitforjob() in expbackq()
3664         if (rootshell) {
3665                 int s = job_signal_status(jp);
3666                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3667                         set_tty_state();
3668         }
3669 }
3670 #else
3671 # define get_tty_state() ((void)0)
3672 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3673 #endif
3674
3675 static void
3676 set_curjob(struct job *jp, unsigned mode)
3677 {
3678         struct job *jp1;
3679         struct job **jpp, **curp;
3680
3681         /* first remove from list */
3682         jpp = curp = &curjob;
3683         while (1) {
3684                 jp1 = *jpp;
3685                 if (jp1 == jp)
3686                         break;
3687                 jpp = &jp1->prev_job;
3688         }
3689         *jpp = jp1->prev_job;
3690
3691         /* Then re-insert in correct position */
3692         jpp = curp;
3693         switch (mode) {
3694         default:
3695 #if DEBUG
3696                 abort();
3697 #endif
3698         case CUR_DELETE:
3699                 /* job being deleted */
3700                 break;
3701         case CUR_RUNNING:
3702                 /* newly created job or backgrounded job,
3703                  * put after all stopped jobs.
3704                  */
3705                 while (1) {
3706                         jp1 = *jpp;
3707 #if JOBS
3708                         if (!jp1 || jp1->state != JOBSTOPPED)
3709 #endif
3710                                 break;
3711                         jpp = &jp1->prev_job;
3712                 }
3713                 /* FALLTHROUGH */
3714 #if JOBS
3715         case CUR_STOPPED:
3716 #endif
3717                 /* newly stopped job - becomes curjob */
3718                 jp->prev_job = *jpp;
3719                 *jpp = jp;
3720                 break;
3721         }
3722 }
3723
3724 #if JOBS || DEBUG
3725 static int
3726 jobno(const struct job *jp)
3727 {
3728         return jp - jobtab + 1;
3729 }
3730 #endif
3731
3732 /*
3733  * Convert a job name to a job structure.
3734  */
3735 #if !JOBS
3736 #define getjob(name, getctl) getjob(name)
3737 #endif
3738 static struct job *
3739 getjob(const char *name, int getctl)
3740 {
3741         struct job *jp;
3742         struct job *found;
3743         const char *err_msg = "%s: no such job";
3744         unsigned num;
3745         int c;
3746         const char *p;
3747         char *(*match)(const char *, const char *);
3748
3749         jp = curjob;
3750         p = name;
3751         if (!p)
3752                 goto currentjob;
3753
3754         if (*p != '%')
3755                 goto err;
3756
3757         c = *++p;
3758         if (!c)
3759                 goto currentjob;
3760
3761         if (!p[1]) {
3762                 if (c == '+' || c == '%') {
3763  currentjob:
3764                         err_msg = "No current job";
3765                         goto check;
3766                 }
3767                 if (c == '-') {
3768                         if (jp)
3769                                 jp = jp->prev_job;
3770                         err_msg = "No previous job";
3771  check:
3772                         if (!jp)
3773                                 goto err;
3774                         goto gotit;
3775                 }
3776         }
3777
3778         if (is_number(p)) {
3779                 num = atoi(p);
3780                 if (num > 0 && num <= njobs) {
3781                         jp = jobtab + num - 1;
3782                         if (jp->used)
3783                                 goto gotit;
3784                         goto err;
3785                 }
3786         }
3787
3788         match = prefix;
3789         if (*p == '?') {
3790                 match = strstr;
3791                 p++;
3792         }
3793
3794         found = NULL;
3795         while (jp) {
3796                 if (match(jp->ps[0].ps_cmd, p)) {
3797                         if (found)
3798                                 goto err;
3799                         found = jp;
3800                         err_msg = "%s: ambiguous";
3801                 }
3802                 jp = jp->prev_job;
3803         }
3804         if (!found)
3805                 goto err;
3806         jp = found;
3807
3808  gotit:
3809 #if JOBS
3810         err_msg = "job %s not created under job control";
3811         if (getctl && jp->jobctl == 0)
3812                 goto err;
3813 #endif
3814         return jp;
3815  err:
3816         ash_msg_and_raise_error(err_msg, name);
3817 }
3818
3819 /*
3820  * Mark a job structure as unused.
3821  */
3822 static void
3823 freejob(struct job *jp)
3824 {
3825         struct procstat *ps;
3826         int i;
3827
3828         INT_OFF;
3829         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3830                 if (ps->ps_cmd != nullstr)
3831                         free(ps->ps_cmd);
3832         }
3833         if (jp->ps != &jp->ps0)
3834                 free(jp->ps);
3835         jp->used = 0;
3836         set_curjob(jp, CUR_DELETE);
3837         INT_ON;
3838 }
3839
3840 #if JOBS
3841 static void
3842 xtcsetpgrp(int fd, pid_t pgrp)
3843 {
3844         if (tcsetpgrp(fd, pgrp))
3845                 ash_msg_and_raise_perror("can't set tty process group");
3846 }
3847
3848 /*
3849  * Turn job control on and off.
3850  *
3851  * Note:  This code assumes that the third arg to ioctl is a character
3852  * pointer, which is true on Berkeley systems but not System V.  Since
3853  * System V doesn't have job control yet, this isn't a problem now.
3854  *
3855  * Called with interrupts off.
3856  */
3857 static void
3858 setjobctl(int on)
3859 {
3860         int fd;
3861         int pgrp;
3862
3863         if (on == doing_jobctl || rootshell == 0)
3864                 return;
3865         if (on) {
3866                 int ofd;
3867                 ofd = fd = open(_PATH_TTY, O_RDWR);
3868                 if (fd < 0) {
3869         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3870          * That sometimes helps to acquire controlling tty.
3871          * Obviously, a workaround for bugs when someone
3872          * failed to provide a controlling tty to bash! :) */
3873                         fd = 2;
3874                         while (!isatty(fd))
3875                                 if (--fd < 0)
3876                                         goto out;
3877                 }
3878                 /* fd is a tty at this point */
3879                 fd = fcntl(fd, F_DUPFD, 10);
3880                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3881                         close(ofd);
3882                 if (fd < 0)
3883                         goto out; /* F_DUPFD failed */
3884                 close_on_exec_on(fd);
3885                 while (1) { /* while we are in the background */
3886                         pgrp = tcgetpgrp(fd);
3887                         if (pgrp < 0) {
3888  out:
3889                                 ash_msg("can't access tty; job control turned off");
3890                                 mflag = on = 0;
3891                                 goto close;
3892                         }
3893                         if (pgrp == getpgrp())
3894                                 break;
3895                         killpg(0, SIGTTIN);
3896                 }
3897                 initialpgrp = pgrp;
3898
3899                 setsignal(SIGTSTP);
3900                 setsignal(SIGTTOU);
3901                 setsignal(SIGTTIN);
3902                 pgrp = rootpid;
3903                 setpgid(0, pgrp);
3904                 xtcsetpgrp(fd, pgrp);
3905         } else {
3906                 /* turning job control off */
3907                 fd = ttyfd;
3908                 pgrp = initialpgrp;
3909                 /* was xtcsetpgrp, but this can make exiting ash
3910                  * loop forever if pty is already deleted */
3911                 tcsetpgrp(fd, pgrp);
3912                 setpgid(0, pgrp);
3913                 setsignal(SIGTSTP);
3914                 setsignal(SIGTTOU);
3915                 setsignal(SIGTTIN);
3916  close:
3917                 if (fd >= 0)
3918                         close(fd);
3919                 fd = -1;
3920         }
3921         ttyfd = fd;
3922         doing_jobctl = on;
3923 }
3924
3925 static int FAST_FUNC
3926 killcmd(int argc, char **argv)
3927 {
3928         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3929                 int i = 1;
3930                 do {
3931                         if (argv[i][0] == '%') {
3932                                 /*
3933                                  * "kill %N" - job kill
3934                                  * Converting to pgrp / pid kill
3935                                  */
3936                                 struct job *jp;
3937                                 char *dst;
3938                                 int j, n;
3939
3940                                 jp = getjob(argv[i], 0);
3941                                 /*
3942                                  * In jobs started under job control, we signal
3943                                  * entire process group by kill -PGRP_ID.
3944                                  * This happens, f.e., in interactive shell.
3945                                  *
3946                                  * Otherwise, we signal each child via
3947                                  * kill PID1 PID2 PID3.
3948                                  * Testcases:
3949                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3950                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3951                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3952                                  */
3953                                 n = jp->nprocs; /* can't be 0 (I hope) */
3954                                 if (jp->jobctl)
3955                                         n = 1;
3956                                 dst = alloca(n * sizeof(int)*4);
3957                                 argv[i] = dst;
3958                                 for (j = 0; j < n; j++) {
3959                                         struct procstat *ps = &jp->ps[j];
3960                                         /* Skip non-running and not-stopped members
3961                                          * (i.e. dead members) of the job
3962                                          */
3963                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3964                                                 continue;
3965                                         /*
3966                                          * kill_main has matching code to expect
3967                                          * leading space. Needed to not confuse
3968                                          * negative pids with "kill -SIGNAL_NO" syntax
3969                                          */
3970                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3971                                 }
3972                                 *dst = '\0';
3973                         }
3974                 } while (argv[++i]);
3975         }
3976         return kill_main(argc, argv);
3977 }
3978
3979 static void
3980 showpipe(struct job *jp /*, FILE *out*/)
3981 {
3982         struct procstat *ps;
3983         struct procstat *psend;
3984
3985         psend = jp->ps + jp->nprocs;
3986         for (ps = jp->ps + 1; ps < psend; ps++)
3987                 printf(" | %s", ps->ps_cmd);
3988         newline_and_flush(stdout);
3989         flush_stdout_stderr();
3990 }
3991
3992
3993 static int
3994 restartjob(struct job *jp, int mode)
3995 {
3996         struct procstat *ps;
3997         int i;
3998         int status;
3999         pid_t pgid;
4000
4001         INT_OFF;
4002         if (jp->state == JOBDONE)
4003                 goto out;
4004         jp->state = JOBRUNNING;
4005         pgid = jp->ps[0].ps_pid;
4006         if (mode == FORK_FG) {
4007                 get_tty_state();
4008                 xtcsetpgrp(ttyfd, pgid);
4009         }
4010         killpg(pgid, SIGCONT);
4011         ps = jp->ps;
4012         i = jp->nprocs;
4013         do {
4014                 if (WIFSTOPPED(ps->ps_status)) {
4015                         ps->ps_status = -1;
4016                 }
4017                 ps++;
4018         } while (--i);
4019  out:
4020         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4021         INT_ON;
4022         return status;
4023 }
4024
4025 static int FAST_FUNC
4026 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4027 {
4028         struct job *jp;
4029         int mode;
4030         int retval;
4031
4032         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4033         nextopt(nullstr);
4034         argv = argptr;
4035         do {
4036                 jp = getjob(*argv, 1);
4037                 if (mode == FORK_BG) {
4038                         set_curjob(jp, CUR_RUNNING);
4039                         printf("[%d] ", jobno(jp));
4040                 }
4041                 out1str(jp->ps[0].ps_cmd);
4042                 showpipe(jp /*, stdout*/);
4043                 retval = restartjob(jp, mode);
4044         } while (*argv && *++argv);
4045         return retval;
4046 }
4047 #endif
4048
4049 static int
4050 sprint_status48(char *s, int status, int sigonly)
4051 {
4052         int col;
4053         int st;
4054
4055         col = 0;
4056         if (!WIFEXITED(status)) {
4057 #if JOBS
4058                 if (WIFSTOPPED(status))
4059                         st = WSTOPSIG(status);
4060                 else
4061 #endif
4062                         st = WTERMSIG(status);
4063                 if (sigonly) {
4064                         if (st == SIGINT || st == SIGPIPE)
4065                                 goto out;
4066 #if JOBS
4067                         if (WIFSTOPPED(status))
4068                                 goto out;
4069 #endif
4070                 }
4071                 st &= 0x7f;
4072 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4073                 col = fmtstr(s, 32, strsignal(st));
4074                 if (WCOREDUMP(status)) {
4075                         strcpy(s + col, " (core dumped)");
4076                         col += sizeof(" (core dumped)")-1;
4077                 }
4078         } else if (!sigonly) {
4079                 st = WEXITSTATUS(status);
4080                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4081         }
4082  out:
4083         return col;
4084 }
4085
4086 static int
4087 wait_block_or_sig(int *status)
4088 {
4089         int pid;
4090
4091         do {
4092                 sigset_t mask;
4093
4094                 /* Poll all children for changes in their state */
4095                 got_sigchld = 0;
4096                 /* if job control is active, accept stopped processes too */
4097                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4098                 if (pid != 0)
4099                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4100
4101                 /* Children exist, but none are ready. Sleep until interesting signal */
4102 #if 1
4103                 sigfillset(&mask);
4104                 sigprocmask(SIG_SETMASK, &mask, &mask);
4105                 while (!got_sigchld && !pending_sig)
4106                         sigsuspend(&mask);
4107                 sigprocmask(SIG_SETMASK, &mask, NULL);
4108 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4109                 while (!got_sigchld && !pending_sig)
4110                         pause();
4111 #endif
4112
4113                 /* If it was SIGCHLD, poll children again */
4114         } while (got_sigchld);
4115
4116         return pid;
4117 }
4118
4119 #define DOWAIT_NONBLOCK 0
4120 #define DOWAIT_BLOCK    1
4121 #define DOWAIT_BLOCK_OR_SIG 2
4122
4123 static int
4124 dowait(int block, struct job *job)
4125 {
4126         int pid;
4127         int status;
4128         struct job *jp;
4129         struct job *thisjob = NULL;
4130
4131         TRACE(("dowait(0x%x) called\n", block));
4132
4133         /* It's wrong to call waitpid() outside of INT_OFF region:
4134          * signal can arrive just after syscall return and handler can
4135          * longjmp away, losing stop/exit notification processing.
4136          * Thus, for "jobs" builtin, and for waiting for a fg job,
4137          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4138          *
4139          * However, for "wait" builtin it is wrong to simply call waitpid()
4140          * in INT_OFF region: "wait" needs to wait for any running job
4141          * to change state, but should exit on any trap too.
4142          * In INT_OFF region, a signal just before syscall entry can set
4143          * pending_sig variables, but we can't check them, and we would
4144          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4145          *
4146          * Because of this, we run inside INT_OFF, but use a special routine
4147          * which combines waitpid() and sigsuspend().
4148          * This is the reason why we need to have a handler for SIGCHLD:
4149          * SIG_DFL handler does not wake sigsuspend().
4150          */
4151         INT_OFF;
4152         if (block == DOWAIT_BLOCK_OR_SIG) {
4153                 pid = wait_block_or_sig(&status);
4154         } else {
4155                 int wait_flags = 0;
4156                 if (block == DOWAIT_NONBLOCK)
4157                         wait_flags = WNOHANG;
4158                 /* if job control is active, accept stopped processes too */
4159                 if (doing_jobctl)
4160                         wait_flags |= WUNTRACED;
4161                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4162                 pid = waitpid(-1, &status, wait_flags);
4163         }
4164         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4165                                 pid, status, errno, strerror(errno)));
4166         if (pid <= 0)
4167                 goto out;
4168
4169         thisjob = NULL;
4170         for (jp = curjob; jp; jp = jp->prev_job) {
4171                 int jobstate;
4172                 struct procstat *ps;
4173                 struct procstat *psend;
4174                 if (jp->state == JOBDONE)
4175                         continue;
4176                 jobstate = JOBDONE;
4177                 ps = jp->ps;
4178                 psend = ps + jp->nprocs;
4179                 do {
4180                         if (ps->ps_pid == pid) {
4181                                 TRACE(("Job %d: changing status of proc %d "
4182                                         "from 0x%x to 0x%x\n",
4183                                         jobno(jp), pid, ps->ps_status, status));
4184                                 ps->ps_status = status;
4185                                 thisjob = jp;
4186                         }
4187                         if (ps->ps_status == -1)
4188                                 jobstate = JOBRUNNING;
4189 #if JOBS
4190                         if (jobstate == JOBRUNNING)
4191                                 continue;
4192                         if (WIFSTOPPED(ps->ps_status)) {
4193                                 jp->stopstatus = ps->ps_status;
4194                                 jobstate = JOBSTOPPED;
4195                         }
4196 #endif
4197                 } while (++ps < psend);
4198                 if (!thisjob)
4199                         continue;
4200
4201                 /* Found the job where one of its processes changed its state.
4202                  * Is there at least one live and running process in this job? */
4203                 if (jobstate != JOBRUNNING) {
4204                         /* No. All live processes in the job are stopped
4205                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4206                          */
4207                         thisjob->changed = 1;
4208                         if (thisjob->state != jobstate) {
4209                                 TRACE(("Job %d: changing state from %d to %d\n",
4210                                         jobno(thisjob), thisjob->state, jobstate));
4211                                 thisjob->state = jobstate;
4212 #if JOBS
4213                                 if (jobstate == JOBSTOPPED)
4214                                         set_curjob(thisjob, CUR_STOPPED);
4215 #endif
4216                         }
4217                 }
4218                 goto out;
4219         }
4220         /* The process wasn't found in job list */
4221 #if JOBS
4222         if (!WIFSTOPPED(status))
4223                 jobless--;
4224 #endif
4225  out:
4226         INT_ON;
4227
4228         if (thisjob && thisjob == job) {
4229                 char s[48 + 1];
4230                 int len;
4231
4232                 len = sprint_status48(s, status, 1);
4233                 if (len) {
4234                         s[len] = '\n';
4235                         s[len + 1] = '\0';
4236                         out2str(s);
4237                 }
4238         }
4239         return pid;
4240 }
4241
4242 #if JOBS
4243 static void
4244 showjob(struct job *jp, int mode)
4245 {
4246         struct procstat *ps;
4247         struct procstat *psend;
4248         int col;
4249         int indent_col;
4250         char s[16 + 16 + 48];
4251         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4252
4253         ps = jp->ps;
4254
4255         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4256                 /* just output process (group) id of pipeline */
4257                 fprintf(out, "%d\n", ps->ps_pid);
4258                 return;
4259         }
4260
4261         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4262         indent_col = col;
4263
4264         if (jp == curjob)
4265                 s[col - 3] = '+';
4266         else if (curjob && jp == curjob->prev_job)
4267                 s[col - 3] = '-';
4268
4269         if (mode & SHOW_PIDS)
4270                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4271
4272         psend = ps + jp->nprocs;
4273
4274         if (jp->state == JOBRUNNING) {
4275                 strcpy(s + col, "Running");
4276                 col += sizeof("Running") - 1;
4277         } else {
4278                 int status = psend[-1].ps_status;
4279                 if (jp->state == JOBSTOPPED)
4280                         status = jp->stopstatus;
4281                 col += sprint_status48(s + col, status, 0);
4282         }
4283         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4284
4285         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4286          * or prints several "PID             | <cmdN>" lines,
4287          * depending on SHOW_PIDS bit.
4288          * We do not print status of individual processes
4289          * between PID and <cmdN>. bash does it, but not very well:
4290          * first line shows overall job status, not process status,
4291          * making it impossible to know 1st process status.
4292          */
4293         goto start;
4294         do {
4295                 /* for each process */
4296                 s[0] = '\0';
4297                 col = 33;
4298                 if (mode & SHOW_PIDS)
4299                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4300  start:
4301                 fprintf(out, "%s%*c%s%s",
4302                                 s,
4303                                 33 - col >= 0 ? 33 - col : 0, ' ',
4304                                 ps == jp->ps ? "" : "| ",
4305                                 ps->ps_cmd
4306                 );
4307         } while (++ps != psend);
4308         newline_and_flush(out);
4309
4310         jp->changed = 0;
4311
4312         if (jp->state == JOBDONE) {
4313                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4314                 freejob(jp);
4315         }
4316 }
4317
4318 /*
4319  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4320  * statuses have changed since the last call to showjobs.
4321  */
4322 static void
4323 showjobs(int mode)
4324 {
4325         struct job *jp;
4326
4327         TRACE(("showjobs(0x%x) called\n", mode));
4328
4329         /* Handle all finished jobs */
4330         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4331                 continue;
4332
4333         for (jp = curjob; jp; jp = jp->prev_job) {
4334                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4335                         showjob(jp, mode);
4336                 }
4337         }
4338 }
4339
4340 static int FAST_FUNC
4341 jobscmd(int argc UNUSED_PARAM, char **argv)
4342 {
4343         int mode, m;
4344
4345         mode = 0;
4346         while ((m = nextopt("lp")) != '\0') {
4347                 if (m == 'l')
4348                         mode |= SHOW_PIDS;
4349                 else
4350                         mode |= SHOW_ONLY_PGID;
4351         }
4352
4353         argv = argptr;
4354         if (*argv) {
4355                 do
4356                         showjob(getjob(*argv, 0), mode);
4357                 while (*++argv);
4358         } else {
4359                 showjobs(mode);
4360         }
4361
4362         return 0;
4363 }
4364 #endif /* JOBS */
4365
4366 /* Called only on finished or stopped jobs (no members are running) */
4367 static int
4368 getstatus(struct job *job)
4369 {
4370         int status;
4371         int retval;
4372         struct procstat *ps;
4373
4374         /* Fetch last member's status */
4375         ps = job->ps + job->nprocs - 1;
4376         status = ps->ps_status;
4377         if (pipefail) {
4378                 /* "set -o pipefail" mode: use last _nonzero_ status */
4379                 while (status == 0 && --ps >= job->ps)
4380                         status = ps->ps_status;
4381         }
4382
4383         retval = WEXITSTATUS(status);
4384         if (!WIFEXITED(status)) {
4385 #if JOBS
4386                 retval = WSTOPSIG(status);
4387                 if (!WIFSTOPPED(status))
4388 #endif
4389                 {
4390                         /* XXX: limits number of signals */
4391                         retval = WTERMSIG(status);
4392 #if JOBS
4393                         if (retval == SIGINT)
4394                                 job->sigint = 1;
4395 #endif
4396                 }
4397                 retval += 128;
4398         }
4399         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4400                 jobno(job), job->nprocs, status, retval));
4401         return retval;
4402 }
4403
4404 static int FAST_FUNC
4405 waitcmd(int argc UNUSED_PARAM, char **argv)
4406 {
4407         struct job *job;
4408         int retval;
4409         struct job *jp;
4410
4411         nextopt(nullstr);
4412         retval = 0;
4413
4414         argv = argptr;
4415         if (!*argv) {
4416                 /* wait for all jobs */
4417                 for (;;) {
4418                         jp = curjob;
4419                         while (1) {
4420                                 if (!jp) /* no running procs */
4421                                         goto ret;
4422                                 if (jp->state == JOBRUNNING)
4423                                         break;
4424                                 jp->waited = 1;
4425                                 jp = jp->prev_job;
4426                         }
4427         /* man bash:
4428          * "When bash is waiting for an asynchronous command via
4429          * the wait builtin, the reception of a signal for which a trap
4430          * has been set will cause the wait builtin to return immediately
4431          * with an exit status greater than 128, immediately after which
4432          * the trap is executed."
4433          */
4434                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4435         /* if child sends us a signal *and immediately exits*,
4436          * dowait() returns pid > 0. Check this case,
4437          * not "if (dowait() < 0)"!
4438          */
4439                         if (pending_sig)
4440                                 goto sigout;
4441                 }
4442         }
4443
4444         retval = 127;
4445         do {
4446                 if (**argv != '%') {
4447                         pid_t pid = number(*argv);
4448                         job = curjob;
4449                         while (1) {
4450                                 if (!job)
4451                                         goto repeat;
4452                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4453                                         break;
4454                                 job = job->prev_job;
4455                         }
4456                 } else {
4457                         job = getjob(*argv, 0);
4458                 }
4459                 /* loop until process terminated or stopped */
4460                 while (job->state == JOBRUNNING) {
4461                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4462                         if (pending_sig)
4463                                 goto sigout;
4464                 }
4465                 job->waited = 1;
4466                 retval = getstatus(job);
4467  repeat: ;
4468         } while (*++argv);
4469
4470  ret:
4471         return retval;
4472  sigout:
4473         retval = 128 + pending_sig;
4474         return retval;
4475 }
4476
4477 static struct job *
4478 growjobtab(void)
4479 {
4480         size_t len;
4481         ptrdiff_t offset;
4482         struct job *jp, *jq;
4483
4484         len = njobs * sizeof(*jp);
4485         jq = jobtab;
4486         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4487
4488         offset = (char *)jp - (char *)jq;
4489         if (offset) {
4490                 /* Relocate pointers */
4491                 size_t l = len;
4492
4493                 jq = (struct job *)((char *)jq + l);
4494                 while (l) {
4495                         l -= sizeof(*jp);
4496                         jq--;
4497 #define joff(p) ((struct job *)((char *)(p) + l))
4498 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4499                         if (joff(jp)->ps == &jq->ps0)
4500                                 jmove(joff(jp)->ps);
4501                         if (joff(jp)->prev_job)
4502                                 jmove(joff(jp)->prev_job);
4503                 }
4504                 if (curjob)
4505                         jmove(curjob);
4506 #undef joff
4507 #undef jmove
4508         }
4509
4510         njobs += 4;
4511         jobtab = jp;
4512         jp = (struct job *)((char *)jp + len);
4513         jq = jp + 3;
4514         do {
4515                 jq->used = 0;
4516         } while (--jq >= jp);
4517         return jp;
4518 }
4519
4520 /*
4521  * Return a new job structure.
4522  * Called with interrupts off.
4523  */
4524 static struct job *
4525 makejob(/*union node *node,*/ int nprocs)
4526 {
4527         int i;
4528         struct job *jp;
4529
4530         for (i = njobs, jp = jobtab; ; jp++) {
4531                 if (--i < 0) {
4532                         jp = growjobtab();
4533                         break;
4534                 }
4535                 if (jp->used == 0)
4536                         break;
4537                 if (jp->state != JOBDONE || !jp->waited)
4538                         continue;
4539 #if JOBS
4540                 if (doing_jobctl)
4541                         continue;
4542 #endif
4543                 freejob(jp);
4544                 break;
4545         }
4546         memset(jp, 0, sizeof(*jp));
4547 #if JOBS
4548         /* jp->jobctl is a bitfield.
4549          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4550         if (doing_jobctl)
4551                 jp->jobctl = 1;
4552 #endif
4553         jp->prev_job = curjob;
4554         curjob = jp;
4555         jp->used = 1;
4556         jp->ps = &jp->ps0;
4557         if (nprocs > 1) {
4558                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4559         }
4560         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4561                                 jobno(jp)));
4562         return jp;
4563 }
4564
4565 #if JOBS
4566 /*
4567  * Return a string identifying a command (to be printed by the
4568  * jobs command).
4569  */
4570 static char *cmdnextc;
4571
4572 static void
4573 cmdputs(const char *s)
4574 {
4575         static const char vstype[VSTYPE + 1][3] = {
4576                 "", "}", "-", "+", "?", "=",
4577                 "%", "%%", "#", "##"
4578                 IF_BASH_SUBSTR(, ":")
4579                 IF_BASH_PATTERN_SUBST(, "/", "//")
4580         };
4581
4582         const char *p, *str;
4583         char cc[2];
4584         char *nextc;
4585         unsigned char c;
4586         unsigned char subtype = 0;
4587         int quoted = 0;
4588
4589         cc[1] = '\0';
4590         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4591         p = s;
4592         while ((c = *p++) != '\0') {
4593                 str = NULL;
4594                 switch (c) {
4595                 case CTLESC:
4596                         c = *p++;
4597                         break;
4598                 case CTLVAR:
4599                         subtype = *p++;
4600                         if ((subtype & VSTYPE) == VSLENGTH)
4601                                 str = "${#";
4602                         else
4603                                 str = "${";
4604                         goto dostr;
4605                 case CTLENDVAR:
4606                         str = "\"}" + !(quoted & 1);
4607                         quoted >>= 1;
4608                         subtype = 0;
4609                         goto dostr;
4610                 case CTLBACKQ:
4611                         str = "$(...)";
4612                         goto dostr;
4613 #if ENABLE_FEATURE_SH_MATH
4614                 case CTLARI:
4615                         str = "$((";
4616                         goto dostr;
4617                 case CTLENDARI:
4618                         str = "))";
4619                         goto dostr;
4620 #endif
4621                 case CTLQUOTEMARK:
4622                         quoted ^= 1;
4623                         c = '"';
4624                         break;
4625                 case '=':
4626                         if (subtype == 0)
4627                                 break;
4628                         if ((subtype & VSTYPE) != VSNORMAL)
4629                                 quoted <<= 1;
4630                         str = vstype[subtype & VSTYPE];
4631                         if (subtype & VSNUL)
4632                                 c = ':';
4633                         else
4634                                 goto checkstr;
4635                         break;
4636                 case '\'':
4637                 case '\\':
4638                 case '"':
4639                 case '$':
4640                         /* These can only happen inside quotes */
4641                         cc[0] = c;
4642                         str = cc;
4643                         c = '\\';
4644                         break;
4645                 default:
4646                         break;
4647                 }
4648                 USTPUTC(c, nextc);
4649  checkstr:
4650                 if (!str)
4651                         continue;
4652  dostr:
4653                 while ((c = *str++) != '\0') {
4654                         USTPUTC(c, nextc);
4655                 }
4656         } /* while *p++ not NUL */
4657
4658         if (quoted & 1) {
4659                 USTPUTC('"', nextc);
4660         }
4661         *nextc = 0;
4662         cmdnextc = nextc;
4663 }
4664
4665 /* cmdtxt() and cmdlist() call each other */
4666 static void cmdtxt(union node *n);
4667
4668 static void
4669 cmdlist(union node *np, int sep)
4670 {
4671         for (; np; np = np->narg.next) {
4672                 if (!sep)
4673                         cmdputs(" ");
4674                 cmdtxt(np);
4675                 if (sep && np->narg.next)
4676                         cmdputs(" ");
4677         }
4678 }
4679
4680 static void
4681 cmdtxt(union node *n)
4682 {
4683         union node *np;
4684         struct nodelist *lp;
4685         const char *p;
4686
4687         if (!n)
4688                 return;
4689         switch (n->type) {
4690         default:
4691 #if DEBUG
4692                 abort();
4693 #endif
4694         case NPIPE:
4695                 lp = n->npipe.cmdlist;
4696                 for (;;) {
4697                         cmdtxt(lp->n);
4698                         lp = lp->next;
4699                         if (!lp)
4700                                 break;
4701                         cmdputs(" | ");
4702                 }
4703                 break;
4704         case NSEMI:
4705                 p = "; ";
4706                 goto binop;
4707         case NAND:
4708                 p = " && ";
4709                 goto binop;
4710         case NOR:
4711                 p = " || ";
4712  binop:
4713                 cmdtxt(n->nbinary.ch1);
4714                 cmdputs(p);
4715                 n = n->nbinary.ch2;
4716                 goto donode;
4717         case NREDIR:
4718         case NBACKGND:
4719                 n = n->nredir.n;
4720                 goto donode;
4721         case NNOT:
4722                 cmdputs("!");
4723                 n = n->nnot.com;
4724  donode:
4725                 cmdtxt(n);
4726                 break;
4727         case NIF:
4728                 cmdputs("if ");
4729                 cmdtxt(n->nif.test);
4730                 cmdputs("; then ");
4731                 if (n->nif.elsepart) {
4732                         cmdtxt(n->nif.ifpart);
4733                         cmdputs("; else ");
4734                         n = n->nif.elsepart;
4735                 } else {
4736                         n = n->nif.ifpart;
4737                 }
4738                 p = "; fi";
4739                 goto dotail;
4740         case NSUBSHELL:
4741                 cmdputs("(");
4742                 n = n->nredir.n;
4743                 p = ")";
4744                 goto dotail;
4745         case NWHILE:
4746                 p = "while ";
4747                 goto until;
4748         case NUNTIL:
4749                 p = "until ";
4750  until:
4751                 cmdputs(p);
4752                 cmdtxt(n->nbinary.ch1);
4753                 n = n->nbinary.ch2;
4754                 p = "; done";
4755  dodo:
4756                 cmdputs("; do ");
4757  dotail:
4758                 cmdtxt(n);
4759                 goto dotail2;
4760         case NFOR:
4761                 cmdputs("for ");
4762                 cmdputs(n->nfor.var);
4763                 cmdputs(" in ");
4764                 cmdlist(n->nfor.args, 1);
4765                 n = n->nfor.body;
4766                 p = "; done";
4767                 goto dodo;
4768         case NDEFUN:
4769                 cmdputs(n->narg.text);
4770                 p = "() { ... }";
4771                 goto dotail2;
4772         case NCMD:
4773                 cmdlist(n->ncmd.args, 1);
4774                 cmdlist(n->ncmd.redirect, 0);
4775                 break;
4776         case NARG:
4777                 p = n->narg.text;
4778  dotail2:
4779                 cmdputs(p);
4780                 break;
4781         case NHERE:
4782         case NXHERE:
4783                 p = "<<...";
4784                 goto dotail2;
4785         case NCASE:
4786                 cmdputs("case ");
4787                 cmdputs(n->ncase.expr->narg.text);
4788                 cmdputs(" in ");
4789                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4790                         cmdtxt(np->nclist.pattern);
4791                         cmdputs(") ");
4792                         cmdtxt(np->nclist.body);
4793                         cmdputs(";; ");
4794                 }
4795                 p = "esac";
4796                 goto dotail2;
4797         case NTO:
4798                 p = ">";
4799                 goto redir;
4800         case NCLOBBER:
4801                 p = ">|";
4802                 goto redir;
4803         case NAPPEND:
4804                 p = ">>";
4805                 goto redir;
4806 #if BASH_REDIR_OUTPUT
4807         case NTO2:
4808 #endif
4809         case NTOFD:
4810                 p = ">&";
4811                 goto redir;
4812         case NFROM:
4813                 p = "<";
4814                 goto redir;
4815         case NFROMFD:
4816                 p = "<&";
4817                 goto redir;
4818         case NFROMTO:
4819                 p = "<>";
4820  redir:
4821                 cmdputs(utoa(n->nfile.fd));
4822                 cmdputs(p);
4823                 if (n->type == NTOFD || n->type == NFROMFD) {
4824                         cmdputs(utoa(n->ndup.dupfd));
4825                         break;
4826                 }
4827                 n = n->nfile.fname;
4828                 goto donode;
4829         }
4830 }
4831
4832 static char *
4833 commandtext(union node *n)
4834 {
4835         char *name;
4836
4837         STARTSTACKSTR(cmdnextc);
4838         cmdtxt(n);
4839         name = stackblock();
4840         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4841         return ckstrdup(name);
4842 }
4843 #endif /* JOBS */
4844
4845 /*
4846  * Fork off a subshell.  If we are doing job control, give the subshell its
4847  * own process group.  Jp is a job structure that the job is to be added to.
4848  * N is the command that will be evaluated by the child.  Both jp and n may
4849  * be NULL.  The mode parameter can be one of the following:
4850  *      FORK_FG - Fork off a foreground process.
4851  *      FORK_BG - Fork off a background process.
4852  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4853  *                   process group even if job control is on.
4854  *
4855  * When job control is turned off, background processes have their standard
4856  * input redirected to /dev/null (except for the second and later processes
4857  * in a pipeline).
4858  *
4859  * Called with interrupts off.
4860  */
4861 /*
4862  * Clear traps on a fork.
4863  */
4864 static void
4865 clear_traps(void)
4866 {
4867         char **tp;
4868
4869         INT_OFF;
4870         for (tp = trap; tp < &trap[NSIG]; tp++) {
4871                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4872                         if (trap_ptr == trap)
4873                                 free(*tp);
4874                         /* else: it "belongs" to trap_ptr vector, don't free */
4875                         *tp = NULL;
4876                         if ((tp - trap) != 0)
4877                                 setsignal(tp - trap);
4878                 }
4879         }
4880         may_have_traps = 0;
4881         INT_ON;
4882 }
4883
4884 /* Lives far away from here, needed for forkchild */
4885 static void closescript(void);
4886
4887 /* Called after fork(), in child */
4888 /* jp and n are NULL when called by openhere() for heredoc support */
4889 static NOINLINE void
4890 forkchild(struct job *jp, union node *n, int mode)
4891 {
4892         int oldlvl;
4893
4894         TRACE(("Child shell %d\n", getpid()));
4895         oldlvl = shlvl;
4896         shlvl++;
4897
4898         /* man bash: "Non-builtin commands run by bash have signal handlers
4899          * set to the values inherited by the shell from its parent".
4900          * Do we do it correctly? */
4901
4902         closescript();
4903
4904         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4905          && n && n->type == NCMD        /* is it single cmd? */
4906         /* && n->ncmd.args->type == NARG - always true? */
4907          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4908          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4909         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4910         ) {
4911                 TRACE(("Trap hack\n"));
4912                 /* Awful hack for `trap` or $(trap).
4913                  *
4914                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4915                  * contains an example where "trap" is executed in a subshell:
4916                  *
4917                  * save_traps=$(trap)
4918                  * ...
4919                  * eval "$save_traps"
4920                  *
4921                  * Standard does not say that "trap" in subshell shall print
4922                  * parent shell's traps. It only says that its output
4923                  * must have suitable form, but then, in the above example
4924                  * (which is not supposed to be normative), it implies that.
4925                  *
4926                  * bash (and probably other shell) does implement it
4927                  * (traps are reset to defaults, but "trap" still shows them),
4928                  * but as a result, "trap" logic is hopelessly messed up:
4929                  *
4930                  * # trap
4931                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4932                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4933                  * # true | trap   <--- trap is in subshell - no output (ditto)
4934                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4935                  * trap -- 'echo Ho' SIGWINCH
4936                  * # echo `(trap)`         <--- in subshell in subshell - output
4937                  * trap -- 'echo Ho' SIGWINCH
4938                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4939                  * trap -- 'echo Ho' SIGWINCH
4940                  *
4941                  * The rules when to forget and when to not forget traps
4942                  * get really complex and nonsensical.
4943                  *
4944                  * Our solution: ONLY bare $(trap) or `trap` is special.
4945                  */
4946                 /* Save trap handler strings for trap builtin to print */
4947                 trap_ptr = xmemdup(trap, sizeof(trap));
4948                 /* Fall through into clearing traps */
4949         }
4950         clear_traps();
4951 #if JOBS
4952         /* do job control only in root shell */
4953         doing_jobctl = 0;
4954         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4955                 pid_t pgrp;
4956
4957                 if (jp->nprocs == 0)
4958                         pgrp = getpid();
4959                 else
4960                         pgrp = jp->ps[0].ps_pid;
4961                 /* this can fail because we are doing it in the parent also */
4962                 setpgid(0, pgrp);
4963                 if (mode == FORK_FG)
4964                         xtcsetpgrp(ttyfd, pgrp);
4965                 setsignal(SIGTSTP);
4966                 setsignal(SIGTTOU);
4967         } else
4968 #endif
4969         if (mode == FORK_BG) {
4970                 /* man bash: "When job control is not in effect,
4971                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4972                 ignoresig(SIGINT);
4973                 ignoresig(SIGQUIT);
4974                 if (jp->nprocs == 0) {
4975                         close(0);
4976                         if (open(bb_dev_null, O_RDONLY) != 0)
4977                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4978                 }
4979         }
4980         if (oldlvl == 0) {
4981                 if (iflag) { /* why if iflag only? */
4982                         setsignal(SIGINT);
4983                         setsignal(SIGTERM);
4984                 }
4985                 /* man bash:
4986                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4987                  * commands run by bash have signal handlers
4988                  * set to the values inherited by the shell
4989                  * from its parent".
4990                  * Take care of the second rule: */
4991                 setsignal(SIGQUIT);
4992         }
4993 #if JOBS
4994         if (n && n->type == NCMD
4995          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4996         ) {
4997                 TRACE(("Job hack\n"));
4998                 /* "jobs": we do not want to clear job list for it,
4999                  * instead we remove only _its_ own_ job from job list.
5000                  * This makes "jobs .... | cat" more useful.
5001                  */
5002                 freejob(curjob);
5003                 return;
5004         }
5005 #endif
5006         for (jp = curjob; jp; jp = jp->prev_job)
5007                 freejob(jp);
5008         jobless = 0;
5009 }
5010
5011 /* Called after fork(), in parent */
5012 #if !JOBS
5013 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5014 #endif
5015 static void
5016 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5017 {
5018         TRACE(("In parent shell: child = %d\n", pid));
5019         if (!jp) {
5020                 /* jp is NULL when called by openhere() for heredoc support */
5021                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5022                         continue;
5023                 jobless++;
5024                 return;
5025         }
5026 #if JOBS
5027         if (mode != FORK_NOJOB && jp->jobctl) {
5028                 int pgrp;
5029
5030                 if (jp->nprocs == 0)
5031                         pgrp = pid;
5032                 else
5033                         pgrp = jp->ps[0].ps_pid;
5034                 /* This can fail because we are doing it in the child also */
5035                 setpgid(pid, pgrp);
5036         }
5037 #endif
5038         if (mode == FORK_BG) {
5039                 backgndpid = pid;               /* set $! */
5040                 set_curjob(jp, CUR_RUNNING);
5041         }
5042         if (jp) {
5043                 struct procstat *ps = &jp->ps[jp->nprocs++];
5044                 ps->ps_pid = pid;
5045                 ps->ps_status = -1;
5046                 ps->ps_cmd = nullstr;
5047 #if JOBS
5048                 if (doing_jobctl && n)
5049                         ps->ps_cmd = commandtext(n);
5050 #endif
5051         }
5052 }
5053
5054 /* jp and n are NULL when called by openhere() for heredoc support */
5055 static int
5056 forkshell(struct job *jp, union node *n, int mode)
5057 {
5058         int pid;
5059
5060         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5061         pid = fork();
5062         if (pid < 0) {
5063                 TRACE(("Fork failed, errno=%d", errno));
5064                 if (jp)
5065                         freejob(jp);
5066                 ash_msg_and_raise_error("can't fork");
5067         }
5068         if (pid == 0) {
5069                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5070                 forkchild(jp, n, mode);
5071         } else {
5072                 forkparent(jp, n, mode, pid);
5073         }
5074         return pid;
5075 }
5076
5077 /*
5078  * Wait for job to finish.
5079  *
5080  * Under job control we have the problem that while a child process
5081  * is running interrupts generated by the user are sent to the child
5082  * but not to the shell.  This means that an infinite loop started by
5083  * an interactive user may be hard to kill.  With job control turned off,
5084  * an interactive user may place an interactive program inside a loop.
5085  * If the interactive program catches interrupts, the user doesn't want
5086  * these interrupts to also abort the loop.  The approach we take here
5087  * is to have the shell ignore interrupt signals while waiting for a
5088  * foreground process to terminate, and then send itself an interrupt
5089  * signal if the child process was terminated by an interrupt signal.
5090  * Unfortunately, some programs want to do a bit of cleanup and then
5091  * exit on interrupt; unless these processes terminate themselves by
5092  * sending a signal to themselves (instead of calling exit) they will
5093  * confuse this approach.
5094  *
5095  * Called with interrupts off.
5096  */
5097 static int
5098 waitforjob(struct job *jp)
5099 {
5100         int st;
5101
5102         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5103
5104         INT_OFF;
5105         while (jp->state == JOBRUNNING) {
5106                 /* In non-interactive shells, we _can_ get
5107                  * a keyboard signal here and be EINTRed,
5108                  * but we just loop back, waiting for command to complete.
5109                  *
5110                  * man bash:
5111                  * "If bash is waiting for a command to complete and receives
5112                  * a signal for which a trap has been set, the trap
5113                  * will not be executed until the command completes."
5114                  *
5115                  * Reality is that even if trap is not set, bash
5116                  * will not act on the signal until command completes.
5117                  * Try this. sleep5intoff.c:
5118                  * #include <signal.h>
5119                  * #include <unistd.h>
5120                  * int main() {
5121                  *         sigset_t set;
5122                  *         sigemptyset(&set);
5123                  *         sigaddset(&set, SIGINT);
5124                  *         sigaddset(&set, SIGQUIT);
5125                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5126                  *         sleep(5);
5127                  *         return 0;
5128                  * }
5129                  * $ bash -c './sleep5intoff; echo hi'
5130                  * ^C^C^C^C <--- pressing ^C once a second
5131                  * $ _
5132                  * $ bash -c './sleep5intoff; echo hi'
5133                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5134                  * $ _
5135                  */
5136                 dowait(DOWAIT_BLOCK, jp);
5137         }
5138         INT_ON;
5139
5140         st = getstatus(jp);
5141 #if JOBS
5142         if (jp->jobctl) {
5143                 xtcsetpgrp(ttyfd, rootpid);
5144                 restore_tty_if_stopped_or_signaled(jp);
5145
5146                 /*
5147                  * This is truly gross.
5148                  * If we're doing job control, then we did a TIOCSPGRP which
5149                  * caused us (the shell) to no longer be in the controlling
5150                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5151                  * intuit from the subprocess exit status whether a SIGINT
5152                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5153                  */
5154                 if (jp->sigint) /* TODO: do the same with all signals */
5155                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5156         }
5157         if (jp->state == JOBDONE)
5158 #endif
5159                 freejob(jp);
5160         return st;
5161 }
5162
5163 /*
5164  * return 1 if there are stopped jobs, otherwise 0
5165  */
5166 static int
5167 stoppedjobs(void)
5168 {
5169         struct job *jp;
5170         int retval;
5171
5172         retval = 0;
5173         if (job_warning)
5174                 goto out;
5175         jp = curjob;
5176         if (jp && jp->state == JOBSTOPPED) {
5177                 out2str("You have stopped jobs.\n");
5178                 job_warning = 2;
5179                 retval++;
5180         }
5181  out:
5182         return retval;
5183 }
5184
5185
5186 /*
5187  * Code for dealing with input/output redirection.
5188  */
5189
5190 #undef EMPTY
5191 #undef CLOSED
5192 #define EMPTY -2                /* marks an unused slot in redirtab */
5193 #define CLOSED -3               /* marks a slot of previously-closed fd */
5194
5195 /*
5196  * Handle here documents.  Normally we fork off a process to write the
5197  * data to a pipe.  If the document is short, we can stuff the data in
5198  * the pipe without forking.
5199  */
5200 /* openhere needs this forward reference */
5201 static void expandhere(union node *arg, int fd);
5202 static int
5203 openhere(union node *redir)
5204 {
5205         int pip[2];
5206         size_t len = 0;
5207
5208         if (pipe(pip) < 0)
5209                 ash_msg_and_raise_error("pipe call failed");
5210         if (redir->type == NHERE) {
5211                 len = strlen(redir->nhere.doc->narg.text);
5212                 if (len <= PIPE_BUF) {
5213                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5214                         goto out;
5215                 }
5216         }
5217         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5218                 /* child */
5219                 close(pip[0]);
5220                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5221                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5222                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5223                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5224                 signal(SIGPIPE, SIG_DFL);
5225                 if (redir->type == NHERE)
5226                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5227                 else /* NXHERE */
5228                         expandhere(redir->nhere.doc, pip[1]);
5229                 _exit(EXIT_SUCCESS);
5230         }
5231  out:
5232         close(pip[1]);
5233         return pip[0];
5234 }
5235
5236 static int
5237 openredirect(union node *redir)
5238 {
5239         struct stat sb;
5240         char *fname;
5241         int f;
5242
5243         switch (redir->nfile.type) {
5244 /* Can't happen, our single caller does this itself */
5245 //      case NTOFD:
5246 //      case NFROMFD:
5247 //              return -1;
5248         case NHERE:
5249         case NXHERE:
5250                 return openhere(redir);
5251         }
5252
5253         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5254          * allocated space. Do it only when we know it is safe.
5255          */
5256         fname = redir->nfile.expfname;
5257
5258         switch (redir->nfile.type) {
5259         default:
5260 #if DEBUG
5261                 abort();
5262 #endif
5263         case NFROM:
5264                 f = open(fname, O_RDONLY);
5265                 if (f < 0)
5266                         goto eopen;
5267                 break;
5268         case NFROMTO:
5269                 f = open(fname, O_RDWR|O_CREAT, 0666);
5270                 if (f < 0)
5271                         goto ecreate;
5272                 break;
5273         case NTO:
5274 #if BASH_REDIR_OUTPUT
5275         case NTO2:
5276 #endif
5277                 /* Take care of noclobber mode. */
5278                 if (Cflag) {
5279                         if (stat(fname, &sb) < 0) {
5280                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5281                                 if (f < 0)
5282                                         goto ecreate;
5283                         } else if (!S_ISREG(sb.st_mode)) {
5284                                 f = open(fname, O_WRONLY, 0666);
5285                                 if (f < 0)
5286                                         goto ecreate;
5287                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5288                                         close(f);
5289                                         errno = EEXIST;
5290                                         goto ecreate;
5291                                 }
5292                         } else {
5293                                 errno = EEXIST;
5294                                 goto ecreate;
5295                         }
5296                         break;
5297                 }
5298                 /* FALLTHROUGH */
5299         case NCLOBBER:
5300                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5301                 if (f < 0)
5302                         goto ecreate;
5303                 break;
5304         case NAPPEND:
5305                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5306                 if (f < 0)
5307                         goto ecreate;
5308                 break;
5309         }
5310
5311         return f;
5312  ecreate:
5313         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5314  eopen:
5315         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5316 }
5317
5318 /*
5319  * Copy a file descriptor to be >= 10. Throws exception on error.
5320  */
5321 static int
5322 savefd(int from)
5323 {
5324         int newfd;
5325         int err;
5326
5327         newfd = fcntl(from, F_DUPFD, 10);
5328         err = newfd < 0 ? errno : 0;
5329         if (err != EBADF) {
5330                 if (err)
5331                         ash_msg_and_raise_perror("%d", from);
5332                 close(from);
5333                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5334         }
5335
5336         return newfd;
5337 }
5338 static int
5339 dup2_or_raise(int from, int to)
5340 {
5341         int newfd;
5342
5343         newfd = (from != to) ? dup2(from, to) : to;
5344         if (newfd < 0) {
5345                 /* Happens when source fd is not open: try "echo >&99" */
5346                 ash_msg_and_raise_perror("%d", from);
5347         }
5348         return newfd;
5349 }
5350
5351 /* Struct def and variable are moved down to the first usage site */
5352 struct two_fd_t {
5353         int orig, copy;
5354 };
5355 struct redirtab {
5356         struct redirtab *next;
5357         int pair_count;
5358         struct two_fd_t two_fd[];
5359 };
5360 #define redirlist (G_var.redirlist)
5361 enum {
5362         COPYFD_RESTORE = (int)~(INT_MAX),
5363 };
5364
5365 static int
5366 need_to_remember(struct redirtab *rp, int fd)
5367 {
5368         int i;
5369
5370         if (!rp) /* remembering was not requested */
5371                 return 0;
5372
5373         for (i = 0; i < rp->pair_count; i++) {
5374                 if (rp->two_fd[i].orig == fd) {
5375                         /* already remembered */
5376                         return 0;
5377                 }
5378         }
5379         return 1;
5380 }
5381
5382 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5383 static int
5384 is_hidden_fd(struct redirtab *rp, int fd)
5385 {
5386         int i;
5387         struct parsefile *pf;
5388
5389         if (fd == -1)
5390                 return 0;
5391         /* Check open scripts' fds */
5392         pf = g_parsefile;
5393         while (pf) {
5394                 /* We skip pf_fd == 0 case because of the following case:
5395                  * $ ash  # running ash interactively
5396                  * $ . ./script.sh
5397                  * and in script.sh: "exec 9>&0".
5398                  * Even though top-level pf_fd _is_ 0,
5399                  * it's still ok to use it: "read" builtin uses it,
5400                  * why should we cripple "exec" builtin?
5401                  */
5402                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5403                         return 1;
5404                 }
5405                 pf = pf->prev;
5406         }
5407
5408         if (!rp)
5409                 return 0;
5410         /* Check saved fds of redirects */
5411         fd |= COPYFD_RESTORE;
5412         for (i = 0; i < rp->pair_count; i++) {
5413                 if (rp->two_fd[i].copy == fd) {
5414                         return 1;
5415                 }
5416         }
5417         return 0;
5418 }
5419
5420 /*
5421  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5422  * old file descriptors are stashed away so that the redirection can be
5423  * undone by calling popredir.
5424  */
5425 /* flags passed to redirect */
5426 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5427 #define REDIR_SAVEFD2 03        /* set preverrout */
5428 static void
5429 redirect(union node *redir, int flags)
5430 {
5431         struct redirtab *sv;
5432         int sv_pos;
5433         int i;
5434         int fd;
5435         int newfd;
5436         int copied_fd2 = -1;
5437
5438         if (!redir)
5439                 return;
5440         sv = NULL;
5441         INT_OFF;
5442         if (flags & REDIR_PUSH)
5443                 sv = redirlist;
5444         sv_pos = 0;
5445         do {
5446                 int right_fd = -1;
5447                 fd = redir->nfile.fd;
5448                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5449                         right_fd = redir->ndup.dupfd;
5450                         //bb_error_msg("doing %d > %d", fd, right_fd);
5451                         /* redirect from/to same file descriptor? */
5452                         if (right_fd == fd)
5453                                 continue;
5454                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5455                         if (is_hidden_fd(sv, right_fd)) {
5456                                 errno = EBADF; /* as if it is closed */
5457                                 ash_msg_and_raise_perror("%d", right_fd);
5458                         }
5459                         newfd = -1;
5460                 } else {
5461                         newfd = openredirect(redir); /* always >= 0 */
5462                         if (fd == newfd) {
5463                                 /* Descriptor wasn't open before redirect.
5464                                  * Mark it for close in the future */
5465                                 if (need_to_remember(sv, fd)) {
5466                                         goto remember_to_close;
5467                                 }
5468                                 continue;
5469                         }
5470                 }
5471 #if BASH_REDIR_OUTPUT
5472  redirect_more:
5473 #endif
5474                 if (need_to_remember(sv, fd)) {
5475                         /* Copy old descriptor */
5476                         /* Careful to not accidentally "save"
5477                          * to the same fd as right side fd in N>&M */
5478                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5479 #if defined(F_DUPFD_CLOEXEC)
5480                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5481 #else
5482                         i = fcntl(fd, F_DUPFD, minfd);
5483 #endif
5484                         if (i == -1) {
5485                                 i = errno;
5486                                 if (i != EBADF) {
5487                                         /* Strange error (e.g. "too many files" EMFILE?) */
5488                                         if (newfd >= 0)
5489                                                 close(newfd);
5490                                         errno = i;
5491                                         ash_msg_and_raise_perror("%d", fd);
5492                                         /* NOTREACHED */
5493                                 }
5494                                 /* EBADF: it is not open - good, remember to close it */
5495  remember_to_close:
5496                                 i = CLOSED;
5497                         } else { /* fd is open, save its copy */
5498 #if !defined(F_DUPFD_CLOEXEC)
5499                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5500 #endif
5501                                 /* "exec fd>&-" should not close fds
5502                                  * which point to script file(s).
5503                                  * Force them to be restored afterwards */
5504                                 if (is_hidden_fd(sv, fd))
5505                                         i |= COPYFD_RESTORE;
5506                         }
5507                         if (fd == 2)
5508                                 copied_fd2 = i;
5509                         sv->two_fd[sv_pos].orig = fd;
5510                         sv->two_fd[sv_pos].copy = i;
5511                         sv_pos++;
5512                 }
5513                 if (newfd < 0) {
5514                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5515                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5516                                 /* Don't want to trigger debugging */
5517                                 if (fd != -1)
5518                                         close(fd);
5519                         } else {
5520                                 dup2_or_raise(redir->ndup.dupfd, fd);
5521                         }
5522                 } else if (fd != newfd) { /* move newfd to fd */
5523                         dup2_or_raise(newfd, fd);
5524 #if BASH_REDIR_OUTPUT
5525                         if (!(redir->nfile.type == NTO2 && fd == 2))
5526 #endif
5527                                 close(newfd);
5528                 }
5529 #if BASH_REDIR_OUTPUT
5530                 if (redir->nfile.type == NTO2 && fd == 1) {
5531                         /* We already redirected it to fd 1, now copy it to 2 */
5532                         newfd = 1;
5533                         fd = 2;
5534                         goto redirect_more;
5535                 }
5536 #endif
5537         } while ((redir = redir->nfile.next) != NULL);
5538
5539         INT_ON;
5540         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5541                 preverrout_fd = copied_fd2;
5542 }
5543
5544 static int
5545 redirectsafe(union node *redir, int flags)
5546 {
5547         int err;
5548         volatile int saveint;
5549         struct jmploc *volatile savehandler = exception_handler;
5550         struct jmploc jmploc;
5551
5552         SAVE_INT(saveint);
5553         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5554         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5555         if (!err) {
5556                 exception_handler = &jmploc;
5557                 redirect(redir, flags);
5558         }
5559         exception_handler = savehandler;
5560         if (err && exception_type != EXERROR)
5561                 longjmp(exception_handler->loc, 1);
5562         RESTORE_INT(saveint);
5563         return err;
5564 }
5565
5566 static struct redirtab*
5567 pushredir(union node *redir)
5568 {
5569         struct redirtab *sv;
5570         int i;
5571
5572         if (!redir)
5573                 return redirlist;
5574
5575         i = 0;
5576         do {
5577                 i++;
5578 #if BASH_REDIR_OUTPUT
5579                 if (redir->nfile.type == NTO2)
5580                         i++;
5581 #endif
5582                 redir = redir->nfile.next;
5583         } while (redir);
5584
5585         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5586         sv->pair_count = i;
5587         while (--i >= 0)
5588                 sv->two_fd[i].orig = sv->two_fd[i].copy = EMPTY;
5589         sv->next = redirlist;
5590         redirlist = sv;
5591         return sv->next;
5592 }
5593
5594 /*
5595  * Undo the effects of the last redirection.
5596  */
5597 static void
5598 popredir(int drop, int restore)
5599 {
5600         struct redirtab *rp;
5601         int i;
5602
5603         if (redirlist == NULL)
5604                 return;
5605         INT_OFF;
5606         rp = redirlist;
5607         for (i = 0; i < rp->pair_count; i++) {
5608                 int fd = rp->two_fd[i].orig;
5609                 int copy = rp->two_fd[i].copy;
5610                 if (copy == CLOSED) {
5611                         if (!drop)
5612                                 close(fd);
5613                         continue;
5614                 }
5615                 if (copy != EMPTY) {
5616                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5617                                 copy &= ~COPYFD_RESTORE;
5618                                 /*close(fd);*/
5619                                 dup2_or_raise(copy, fd);
5620                         }
5621                         close(copy & ~COPYFD_RESTORE);
5622                 }
5623         }
5624         redirlist = rp->next;
5625         free(rp);
5626         INT_ON;
5627 }
5628
5629 static void
5630 unwindredir(struct redirtab *stop)
5631 {
5632         while (redirlist != stop)
5633                 popredir(/*drop:*/ 0, /*restore:*/ 0);
5634 }
5635
5636
5637 /* ============ Routines to expand arguments to commands
5638  *
5639  * We have to deal with backquotes, shell variables, and file metacharacters.
5640  */
5641
5642 #if ENABLE_FEATURE_SH_MATH
5643 static arith_t
5644 ash_arith(const char *s)
5645 {
5646         arith_state_t math_state;
5647         arith_t result;
5648
5649         math_state.lookupvar = lookupvar;
5650         math_state.setvar    = setvar0;
5651         //math_state.endofname = endofname;
5652
5653         INT_OFF;
5654         result = arith(&math_state, s);
5655         if (math_state.errmsg)
5656                 ash_msg_and_raise_error(math_state.errmsg);
5657         INT_ON;
5658
5659         return result;
5660 }
5661 #endif
5662
5663 /*
5664  * expandarg flags
5665  */
5666 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5667 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5668 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5669 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5670 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5671  * POSIX says for this case:
5672  *  Pathname expansion shall not be performed on the word by a
5673  *  non-interactive shell; an interactive shell may perform it, but shall
5674  *  do so only when the expansion would result in one word.
5675  * Currently, our code complies to the above rule by never globbing
5676  * redirection filenames.
5677  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5678  * (this means that on a typical Linux distro, bash almost always
5679  * performs globbing, and thus diverges from what we do).
5680  */
5681 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5682 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5683 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5684 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5685 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5686 /*
5687  * rmescape() flags
5688  */
5689 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5690 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5691 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5692 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5693 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5694
5695 /* Add CTLESC when necessary. */
5696 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5697 /* Do not skip NUL characters. */
5698 #define QUOTES_KEEPNUL EXP_TILDE
5699
5700 /*
5701  * Structure specifying which parts of the string should be searched
5702  * for IFS characters.
5703  */
5704 struct ifsregion {
5705         struct ifsregion *next; /* next region in list */
5706         int begoff;             /* offset of start of region */
5707         int endoff;             /* offset of end of region */
5708         int nulonly;            /* search for nul bytes only */
5709 };
5710
5711 struct arglist {
5712         struct strlist *list;
5713         struct strlist **lastp;
5714 };
5715
5716 /* output of current string */
5717 static char *expdest;
5718 /* list of back quote expressions */
5719 static struct nodelist *argbackq;
5720 /* first struct in list of ifs regions */
5721 static struct ifsregion ifsfirst;
5722 /* last struct in list */
5723 static struct ifsregion *ifslastp;
5724 /* holds expanded arg list */
5725 static struct arglist exparg;
5726
5727 /*
5728  * Our own itoa().
5729  * cvtnum() is used even if math support is off (to prepare $? values and such).
5730  */
5731 static int
5732 cvtnum(arith_t num)
5733 {
5734         int len;
5735
5736         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5737         len = sizeof(arith_t) * 3;
5738         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5739         if (sizeof(arith_t) < 4) len += 2;
5740
5741         expdest = makestrspace(len, expdest);
5742         len = fmtstr(expdest, len, ARITH_FMT, num);
5743         STADJUST(len, expdest);
5744         return len;
5745 }
5746
5747 /*
5748  * Break the argument string into pieces based upon IFS and add the
5749  * strings to the argument list.  The regions of the string to be
5750  * searched for IFS characters have been stored by recordregion.
5751  */
5752 static void
5753 ifsbreakup(char *string, struct arglist *arglist)
5754 {
5755         struct ifsregion *ifsp;
5756         struct strlist *sp;
5757         char *start;
5758         char *p;
5759         char *q;
5760         const char *ifs, *realifs;
5761         int ifsspc;
5762         int nulonly;
5763
5764         start = string;
5765         if (ifslastp != NULL) {
5766                 ifsspc = 0;
5767                 nulonly = 0;
5768                 realifs = ifsset() ? ifsval() : defifs;
5769                 ifsp = &ifsfirst;
5770                 do {
5771                         p = string + ifsp->begoff;
5772                         nulonly = ifsp->nulonly;
5773                         ifs = nulonly ? nullstr : realifs;
5774                         ifsspc = 0;
5775                         while (p < string + ifsp->endoff) {
5776                                 q = p;
5777                                 if ((unsigned char)*p == CTLESC)
5778                                         p++;
5779                                 if (!strchr(ifs, *p)) {
5780                                         p++;
5781                                         continue;
5782                                 }
5783                                 if (!nulonly)
5784                                         ifsspc = (strchr(defifs, *p) != NULL);
5785                                 /* Ignore IFS whitespace at start */
5786                                 if (q == start && ifsspc) {
5787                                         p++;
5788                                         start = p;
5789                                         continue;
5790                                 }
5791                                 *q = '\0';
5792                                 sp = stzalloc(sizeof(*sp));
5793                                 sp->text = start;
5794                                 *arglist->lastp = sp;
5795                                 arglist->lastp = &sp->next;
5796                                 p++;
5797                                 if (!nulonly) {
5798                                         for (;;) {
5799                                                 if (p >= string + ifsp->endoff) {
5800                                                         break;
5801                                                 }
5802                                                 q = p;
5803                                                 if ((unsigned char)*p == CTLESC)
5804                                                         p++;
5805                                                 if (strchr(ifs, *p) == NULL) {
5806                                                         p = q;
5807                                                         break;
5808                                                 }
5809                                                 if (strchr(defifs, *p) == NULL) {
5810                                                         if (ifsspc) {
5811                                                                 p++;
5812                                                                 ifsspc = 0;
5813                                                         } else {
5814                                                                 p = q;
5815                                                                 break;
5816                                                         }
5817                                                 } else
5818                                                         p++;
5819                                         }
5820                                 }
5821                                 start = p;
5822                         } /* while */
5823                         ifsp = ifsp->next;
5824                 } while (ifsp != NULL);
5825                 if (nulonly)
5826                         goto add;
5827         }
5828
5829         if (!*start)
5830                 return;
5831
5832  add:
5833         sp = stzalloc(sizeof(*sp));
5834         sp->text = start;
5835         *arglist->lastp = sp;
5836         arglist->lastp = &sp->next;
5837 }
5838
5839 static void
5840 ifsfree(void)
5841 {
5842         struct ifsregion *p = ifsfirst.next;
5843
5844         if (!p)
5845                 goto out;
5846
5847         INT_OFF;
5848         do {
5849                 struct ifsregion *ifsp;
5850                 ifsp = p->next;
5851                 free(p);
5852                 p = ifsp;
5853         } while (p);
5854         ifsfirst.next = NULL;
5855         INT_ON;
5856  out:
5857         ifslastp = NULL;
5858 }
5859
5860 static size_t
5861 esclen(const char *start, const char *p)
5862 {
5863         size_t esc = 0;
5864
5865         while (p > start && (unsigned char)*--p == CTLESC) {
5866                 esc++;
5867         }
5868         return esc;
5869 }
5870
5871 /*
5872  * Remove any CTLESC characters from a string.
5873  */
5874 static char *
5875 rmescapes(char *str, int flag)
5876 {
5877         static const char qchars[] ALIGN1 = {
5878                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5879
5880         char *p, *q, *r;
5881         unsigned inquotes;
5882         unsigned protect_against_glob;
5883         unsigned globbing;
5884         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5885
5886         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5887         if (!p)
5888                 return str;
5889
5890         q = p;
5891         r = str;
5892         if (flag & RMESCAPE_ALLOC) {
5893                 size_t len = p - str;
5894                 size_t fulllen = len + strlen(p) + 1;
5895
5896                 if (flag & RMESCAPE_GROW) {
5897                         int strloc = str - (char *)stackblock();
5898                         r = makestrspace(fulllen, expdest);
5899                         /* p and str may be invalidated by makestrspace */
5900                         str = (char *)stackblock() + strloc;
5901                         p = str + len;
5902                 } else if (flag & RMESCAPE_HEAP) {
5903                         r = ckmalloc(fulllen);
5904                 } else {
5905                         r = stalloc(fulllen);
5906                 }
5907                 q = r;
5908                 if (len > 0) {
5909                         q = (char *)mempcpy(q, str, len);
5910                 }
5911         }
5912
5913         inquotes = 0;
5914         globbing = flag & RMESCAPE_GLOB;
5915         protect_against_glob = globbing;
5916         while (*p) {
5917                 if ((unsigned char)*p == CTLQUOTEMARK) {
5918 // Note: both inquotes and protect_against_glob only affect whether
5919 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5920                         inquotes = ~inquotes;
5921                         p++;
5922                         protect_against_glob = globbing;
5923                         continue;
5924                 }
5925                 if ((unsigned char)*p == CTLESC) {
5926                         p++;
5927 #if DEBUG
5928                         if (*p == '\0')
5929                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5930 #endif
5931                         if (protect_against_glob) {
5932                                 /*
5933                                  * We used to trust glob() and fnmatch() to eat
5934                                  * superfluous escapes (\z where z has no
5935                                  * special meaning anyway). But this causes
5936                                  * bugs such as string of one greek letter rho
5937                                  * (unicode-encoded as two bytes "cf,81")
5938                                  * getting encoded as "cf,CTLESC,81"
5939                                  * and here, converted to "cf,\,81" -
5940                                  * which does not go well with some flavors
5941                                  * of fnmatch() in unicode locales
5942                                  * (for example, glibc <= 2.22).
5943                                  *
5944                                  * Lets add "\" only on the chars which need it.
5945                                  * Testcases for less obvious chars are shown.
5946                                  */
5947                                 if (*p == '*'
5948                                  || *p == '?'
5949                                  || *p == '['
5950                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5951                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5952                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5953                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5954                                 /* Some libc support [^negate], that's why "^" also needs love */
5955                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5956                                 ) {
5957                                         *q++ = '\\';
5958                                 }
5959                         }
5960                 } else if (*p == '\\' && !inquotes) {
5961                         /* naked back slash */
5962                         protect_against_glob = 0;
5963                         goto copy;
5964                 }
5965 #if BASH_PATTERN_SUBST
5966                 else if (*p == '/' && slash) {
5967                         /* stop handling globbing and mark location of slash */
5968                         globbing = slash = 0;
5969                         *p = CTLESC;
5970                 }
5971 #endif
5972                 protect_against_glob = globbing;
5973  copy:
5974                 *q++ = *p++;
5975         }
5976         *q = '\0';
5977         if (flag & RMESCAPE_GROW) {
5978                 expdest = r;
5979                 STADJUST(q - r + 1, expdest);
5980         }
5981         return r;
5982 }
5983 #define pmatch(a, b) !fnmatch((a), (b), 0)
5984
5985 /*
5986  * Prepare a pattern for a expmeta (internal glob(3)) call.
5987  *
5988  * Returns an stalloced string.
5989  */
5990 static char *
5991 preglob(const char *pattern, int flag)
5992 {
5993         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5994 }
5995
5996 /*
5997  * Put a string on the stack.
5998  */
5999 static void
6000 memtodest(const char *p, size_t len, int syntax, int quotes)
6001 {
6002         char *q;
6003
6004         if (!len)
6005                 return;
6006
6007         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6008
6009         do {
6010                 unsigned char c = *p++;
6011                 if (c) {
6012                         if (quotes & QUOTES_ESC) {
6013                                 int n = SIT(c, syntax);
6014                                 if (n == CCTL
6015                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6016                                      && n == CBACK
6017                                     )
6018                                 ) {
6019                                         USTPUTC(CTLESC, q);
6020                                 }
6021                         }
6022                 } else if (!(quotes & QUOTES_KEEPNUL))
6023                         continue;
6024                 USTPUTC(c, q);
6025         } while (--len);
6026
6027         expdest = q;
6028 }
6029
6030 static size_t
6031 strtodest(const char *p, int syntax, int quotes)
6032 {
6033         size_t len = strlen(p);
6034         memtodest(p, len, syntax, quotes);
6035         return len;
6036 }
6037
6038 /*
6039  * Record the fact that we have to scan this region of the
6040  * string for IFS characters.
6041  */
6042 static void
6043 recordregion(int start, int end, int nulonly)
6044 {
6045         struct ifsregion *ifsp;
6046
6047         if (ifslastp == NULL) {
6048                 ifsp = &ifsfirst;
6049         } else {
6050                 INT_OFF;
6051                 ifsp = ckzalloc(sizeof(*ifsp));
6052                 /*ifsp->next = NULL; - ckzalloc did it */
6053                 ifslastp->next = ifsp;
6054                 INT_ON;
6055         }
6056         ifslastp = ifsp;
6057         ifslastp->begoff = start;
6058         ifslastp->endoff = end;
6059         ifslastp->nulonly = nulonly;
6060 }
6061
6062 static void
6063 removerecordregions(int endoff)
6064 {
6065         if (ifslastp == NULL)
6066                 return;
6067
6068         if (ifsfirst.endoff > endoff) {
6069                 while (ifsfirst.next) {
6070                         struct ifsregion *ifsp;
6071                         INT_OFF;
6072                         ifsp = ifsfirst.next->next;
6073                         free(ifsfirst.next);
6074                         ifsfirst.next = ifsp;
6075                         INT_ON;
6076                 }
6077                 if (ifsfirst.begoff > endoff) {
6078                         ifslastp = NULL;
6079                 } else {
6080                         ifslastp = &ifsfirst;
6081                         ifsfirst.endoff = endoff;
6082                 }
6083                 return;
6084         }
6085
6086         ifslastp = &ifsfirst;
6087         while (ifslastp->next && ifslastp->next->begoff < endoff)
6088                 ifslastp = ifslastp->next;
6089         while (ifslastp->next) {
6090                 struct ifsregion *ifsp;
6091                 INT_OFF;
6092                 ifsp = ifslastp->next->next;
6093                 free(ifslastp->next);
6094                 ifslastp->next = ifsp;
6095                 INT_ON;
6096         }
6097         if (ifslastp->endoff > endoff)
6098                 ifslastp->endoff = endoff;
6099 }
6100
6101 static char *
6102 exptilde(char *startp, char *p, int flags)
6103 {
6104         unsigned char c;
6105         char *name;
6106         struct passwd *pw;
6107         const char *home;
6108         int quotes = flags & QUOTES_ESC;
6109
6110         name = p + 1;
6111
6112         while ((c = *++p) != '\0') {
6113                 switch (c) {
6114                 case CTLESC:
6115                         return startp;
6116                 case CTLQUOTEMARK:
6117                         return startp;
6118                 case ':':
6119                         if (flags & EXP_VARTILDE)
6120                                 goto done;
6121                         break;
6122                 case '/':
6123                 case CTLENDVAR:
6124                         goto done;
6125                 }
6126         }
6127  done:
6128         *p = '\0';
6129         if (*name == '\0') {
6130                 home = lookupvar("HOME");
6131         } else {
6132                 pw = getpwnam(name);
6133                 if (pw == NULL)
6134                         goto lose;
6135                 home = pw->pw_dir;
6136         }
6137         if (!home || !*home)
6138                 goto lose;
6139         *p = c;
6140         strtodest(home, SQSYNTAX, quotes);
6141         return p;
6142  lose:
6143         *p = c;
6144         return startp;
6145 }
6146
6147 /*
6148  * Execute a command inside back quotes.  If it's a builtin command, we
6149  * want to save its output in a block obtained from malloc.  Otherwise
6150  * we fork off a subprocess and get the output of the command via a pipe.
6151  * Should be called with interrupts off.
6152  */
6153 struct backcmd {                /* result of evalbackcmd */
6154         int fd;                 /* file descriptor to read from */
6155         int nleft;              /* number of chars in buffer */
6156         char *buf;              /* buffer */
6157         struct job *jp;         /* job structure for command */
6158 };
6159
6160 /* These forward decls are needed to use "eval" code for backticks handling: */
6161 /* flags in argument to evaltree */
6162 #define EV_EXIT    01           /* exit after evaluating tree */
6163 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6164 static int evaltree(union node *, int);
6165
6166 /* An evaltree() which is known to never return.
6167  * Used to use an alias:
6168  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6169  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6170  */
6171 static ALWAYS_INLINE NORETURN void
6172 evaltreenr(union node *n, int flags)
6173 {
6174         evaltree(n, flags);
6175         bb_unreachable(abort());
6176         /* NOTREACHED */
6177 }
6178
6179 static void FAST_FUNC
6180 evalbackcmd(union node *n, struct backcmd *result)
6181 {
6182         int pip[2];
6183         struct job *jp;
6184
6185         result->fd = -1;
6186         result->buf = NULL;
6187         result->nleft = 0;
6188         result->jp = NULL;
6189         if (n == NULL) {
6190                 goto out;
6191         }
6192
6193         if (pipe(pip) < 0)
6194                 ash_msg_and_raise_error("pipe call failed");
6195         jp = makejob(/*n,*/ 1);
6196         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6197                 /* child */
6198                 FORCE_INT_ON;
6199                 close(pip[0]);
6200                 if (pip[1] != 1) {
6201                         /*close(1);*/
6202                         dup2_or_raise(pip[1], 1);
6203                         close(pip[1]);
6204                 }
6205 /* TODO: eflag clearing makes the following not abort:
6206  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6207  * which is what bash does (unless it is in POSIX mode).
6208  * dash deleted "eflag = 0" line in the commit
6209  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6210  *  [EVAL] Don't clear eflag in evalbackcmd
6211  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6212  */
6213                 eflag = 0;
6214                 ifsfree();
6215                 evaltreenr(n, EV_EXIT);
6216                 /* NOTREACHED */
6217         }
6218         /* parent */
6219         close(pip[1]);
6220         result->fd = pip[0];
6221         result->jp = jp;
6222
6223  out:
6224         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6225                 result->fd, result->buf, result->nleft, result->jp));
6226 }
6227
6228 /*
6229  * Expand stuff in backwards quotes.
6230  */
6231 static void
6232 expbackq(union node *cmd, int flag)
6233 {
6234         struct backcmd in;
6235         int i;
6236         char buf[128];
6237         char *p;
6238         char *dest;
6239         int startloc;
6240         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6241         struct stackmark smark;
6242
6243         INT_OFF;
6244         startloc = expdest - (char *)stackblock();
6245         pushstackmark(&smark, startloc);
6246         evalbackcmd(cmd, &in);
6247         popstackmark(&smark);
6248
6249         p = in.buf;
6250         i = in.nleft;
6251         if (i == 0)
6252                 goto read;
6253         for (;;) {
6254                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6255  read:
6256                 if (in.fd < 0)
6257                         break;
6258                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6259                 TRACE(("expbackq: read returns %d\n", i));
6260                 if (i <= 0)
6261                         break;
6262                 p = buf;
6263         }
6264
6265         free(in.buf);
6266         if (in.fd >= 0) {
6267                 close(in.fd);
6268                 back_exitstatus = waitforjob(in.jp);
6269         }
6270         INT_ON;
6271
6272         /* Eat all trailing newlines */
6273         dest = expdest;
6274         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6275                 STUNPUTC(dest);
6276         expdest = dest;
6277
6278         if (!(flag & EXP_QUOTED))
6279                 recordregion(startloc, dest - (char *)stackblock(), 0);
6280         TRACE(("evalbackq: size:%d:'%.*s'\n",
6281                 (int)((dest - (char *)stackblock()) - startloc),
6282                 (int)((dest - (char *)stackblock()) - startloc),
6283                 stackblock() + startloc));
6284 }
6285
6286 #if ENABLE_FEATURE_SH_MATH
6287 /*
6288  * Expand arithmetic expression.  Backup to start of expression,
6289  * evaluate, place result in (backed up) result, adjust string position.
6290  */
6291 static void
6292 expari(int flag)
6293 {
6294         char *p, *start;
6295         int begoff;
6296         int len;
6297
6298         /* ifsfree(); */
6299
6300         /*
6301          * This routine is slightly over-complicated for
6302          * efficiency.  Next we scan backwards looking for the
6303          * start of arithmetic.
6304          */
6305         start = stackblock();
6306         p = expdest - 1;
6307         *p = '\0';
6308         p--;
6309         while (1) {
6310                 int esc;
6311
6312                 while ((unsigned char)*p != CTLARI) {
6313                         p--;
6314 #if DEBUG
6315                         if (p < start) {
6316                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6317                         }
6318 #endif
6319                 }
6320
6321                 esc = esclen(start, p);
6322                 if (!(esc % 2)) {
6323                         break;
6324                 }
6325
6326                 p -= esc + 1;
6327         }
6328
6329         begoff = p - start;
6330
6331         removerecordregions(begoff);
6332
6333         expdest = p;
6334
6335         if (flag & QUOTES_ESC)
6336                 rmescapes(p + 1, 0);
6337
6338         len = cvtnum(ash_arith(p + 1));
6339
6340         if (!(flag & EXP_QUOTED))
6341                 recordregion(begoff, begoff + len, 0);
6342 }
6343 #endif
6344
6345 /* argstr needs it */
6346 static char *evalvar(char *p, int flags);
6347
6348 /*
6349  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6350  * characters to allow for further processing.  Otherwise treat
6351  * $@ like $* since no splitting will be performed.
6352  */
6353 static void
6354 argstr(char *p, int flags)
6355 {
6356         static const char spclchars[] ALIGN1 = {
6357                 '=',
6358                 ':',
6359                 CTLQUOTEMARK,
6360                 CTLENDVAR,
6361                 CTLESC,
6362                 CTLVAR,
6363                 CTLBACKQ,
6364 #if ENABLE_FEATURE_SH_MATH
6365                 CTLENDARI,
6366 #endif
6367                 '\0'
6368         };
6369         const char *reject = spclchars;
6370         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6371         int inquotes;
6372         size_t length;
6373         int startloc;
6374
6375         if (!(flags & EXP_VARTILDE)) {
6376                 reject += 2;
6377         } else if (flags & EXP_VARTILDE2) {
6378                 reject++;
6379         }
6380         inquotes = 0;
6381         length = 0;
6382         if (flags & EXP_TILDE) {
6383                 char *q;
6384
6385                 flags &= ~EXP_TILDE;
6386  tilde:
6387                 q = p;
6388                 if (*q == '~')
6389                         p = exptilde(p, q, flags);
6390         }
6391  start:
6392         startloc = expdest - (char *)stackblock();
6393         for (;;) {
6394                 unsigned char c;
6395
6396                 length += strcspn(p + length, reject);
6397                 c = p[length];
6398                 if (c) {
6399                         if (!(c & 0x80)
6400                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6401                         ) {
6402                                 /* c == '=' || c == ':' || c == CTLENDARI */
6403                                 length++;
6404                         }
6405                 }
6406                 if (length > 0) {
6407                         int newloc;
6408                         expdest = stack_nputstr(p, length, expdest);
6409                         newloc = expdest - (char *)stackblock();
6410                         if (breakall && !inquotes && newloc > startloc) {
6411                                 recordregion(startloc, newloc, 0);
6412                         }
6413                         startloc = newloc;
6414                 }
6415                 p += length + 1;
6416                 length = 0;
6417
6418                 switch (c) {
6419                 case '\0':
6420                         goto breakloop;
6421                 case '=':
6422                         if (flags & EXP_VARTILDE2) {
6423                                 p--;
6424                                 continue;
6425                         }
6426                         flags |= EXP_VARTILDE2;
6427                         reject++;
6428                         /* fall through */
6429                 case ':':
6430                         /*
6431                          * sort of a hack - expand tildes in variable
6432                          * assignments (after the first '=' and after ':'s).
6433                          */
6434                         if (*--p == '~') {
6435                                 goto tilde;
6436                         }
6437                         continue;
6438                 }
6439
6440                 switch (c) {
6441                 case CTLENDVAR: /* ??? */
6442                         goto breakloop;
6443                 case CTLQUOTEMARK:
6444                         inquotes ^= EXP_QUOTED;
6445                         /* "$@" syntax adherence hack */
6446                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6447                                 p = evalvar(p + 1, flags | inquotes) + 1;
6448                                 goto start;
6449                         }
6450  addquote:
6451                         if (flags & QUOTES_ESC) {
6452                                 p--;
6453                                 length++;
6454                                 startloc++;
6455                         }
6456                         break;
6457                 case CTLESC:
6458                         startloc++;
6459                         length++;
6460
6461                         /*
6462                          * Quoted parameter expansion pattern: remove quote
6463                          * unless inside inner quotes or we have a literal
6464                          * backslash.
6465                          */
6466                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6467                             EXP_QPAT && *p != '\\')
6468                                 break;
6469
6470                         goto addquote;
6471                 case CTLVAR:
6472                         TRACE(("argstr: evalvar('%s')\n", p));
6473                         p = evalvar(p, flags | inquotes);
6474                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6475                         goto start;
6476                 case CTLBACKQ:
6477                         expbackq(argbackq->n, flags | inquotes);
6478                         argbackq = argbackq->next;
6479                         goto start;
6480 #if ENABLE_FEATURE_SH_MATH
6481                 case CTLENDARI:
6482                         p--;
6483                         expari(flags | inquotes);
6484                         goto start;
6485 #endif
6486                 }
6487         }
6488  breakloop: ;
6489 }
6490
6491 static char *
6492 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6493                 char *pattern, int quotes, int zero)
6494 {
6495         char *loc, *loc2;
6496         char c;
6497
6498         loc = startp;
6499         loc2 = rmesc;
6500         do {
6501                 int match;
6502                 const char *s = loc2;
6503
6504                 c = *loc2;
6505                 if (zero) {
6506                         *loc2 = '\0';
6507                         s = rmesc;
6508                 }
6509                 match = pmatch(pattern, s);
6510
6511                 *loc2 = c;
6512                 if (match)
6513                         return loc;
6514                 if (quotes && (unsigned char)*loc == CTLESC)
6515                         loc++;
6516                 loc++;
6517                 loc2++;
6518         } while (c);
6519         return NULL;
6520 }
6521
6522 static char *
6523 scanright(char *startp, char *rmesc, char *rmescend,
6524                 char *pattern, int quotes, int match_at_start)
6525 {
6526 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6527         int try2optimize = match_at_start;
6528 #endif
6529         int esc = 0;
6530         char *loc;
6531         char *loc2;
6532
6533         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6534          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6535          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6536          * Logic:
6537          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6538          * and on each iteration they go back two/one char until they reach the beginning.
6539          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6540          */
6541         /* TODO: document in what other circumstances we are called. */
6542
6543         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6544                 int match;
6545                 char c = *loc2;
6546                 const char *s = loc2;
6547                 if (match_at_start) {
6548                         *loc2 = '\0';
6549                         s = rmesc;
6550                 }
6551                 match = pmatch(pattern, s);
6552                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6553                 *loc2 = c;
6554                 if (match)
6555                         return loc;
6556 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6557                 if (try2optimize) {
6558                         /* Maybe we can optimize this:
6559                          * if pattern ends with unescaped *, we can avoid checking
6560                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6561                          * it won't match truncated "raw_value_of_" strings too.
6562                          */
6563                         unsigned plen = strlen(pattern);
6564                         /* Does it end with "*"? */
6565                         if (plen != 0 && pattern[--plen] == '*') {
6566                                 /* "xxxx*" is not escaped */
6567                                 /* "xxx\*" is escaped */
6568                                 /* "xx\\*" is not escaped */
6569                                 /* "x\\\*" is escaped */
6570                                 int slashes = 0;
6571                                 while (plen != 0 && pattern[--plen] == '\\')
6572                                         slashes++;
6573                                 if (!(slashes & 1))
6574                                         break; /* ends with unescaped "*" */
6575                         }
6576                         try2optimize = 0;
6577                 }
6578 #endif
6579                 loc--;
6580                 if (quotes) {
6581                         if (--esc < 0) {
6582                                 esc = esclen(startp, loc);
6583                         }
6584                         if (esc % 2) {
6585                                 esc--;
6586                                 loc--;
6587                         }
6588                 }
6589         }
6590         return NULL;
6591 }
6592
6593 static void varunset(const char *, const char *, const char *, int) NORETURN;
6594 static void
6595 varunset(const char *end, const char *var, const char *umsg, int varflags)
6596 {
6597         const char *msg;
6598         const char *tail;
6599
6600         tail = nullstr;
6601         msg = "parameter not set";
6602         if (umsg) {
6603                 if ((unsigned char)*end == CTLENDVAR) {
6604                         if (varflags & VSNUL)
6605                                 tail = " or null";
6606                 } else {
6607                         msg = umsg;
6608                 }
6609         }
6610         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6611 }
6612
6613 static const char *
6614 subevalvar(char *p, char *varname, int strloc, int subtype,
6615                 int startloc, int varflags, int flag)
6616 {
6617         struct nodelist *saveargbackq = argbackq;
6618         int quotes = flag & QUOTES_ESC;
6619         char *startp;
6620         char *loc;
6621         char *rmesc, *rmescend;
6622         char *str;
6623         int amount, resetloc;
6624         IF_BASH_PATTERN_SUBST(int workloc;)
6625         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6626         int zero;
6627         char *(*scan)(char*, char*, char*, char*, int, int);
6628
6629         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6630         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6631
6632         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6633                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6634         );
6635         STPUTC('\0', expdest);
6636         argbackq = saveargbackq;
6637         startp = (char *)stackblock() + startloc;
6638
6639         switch (subtype) {
6640         case VSASSIGN:
6641                 setvar0(varname, startp);
6642                 amount = startp - expdest;
6643                 STADJUST(amount, expdest);
6644                 return startp;
6645
6646         case VSQUESTION:
6647                 varunset(p, varname, startp, varflags);
6648                 /* NOTREACHED */
6649
6650 #if BASH_SUBSTR
6651         case VSSUBSTR: {
6652                 int pos, len, orig_len;
6653                 char *colon;
6654
6655                 loc = str = stackblock() + strloc;
6656
6657 # if !ENABLE_FEATURE_SH_MATH
6658 #  define ash_arith number
6659 # endif
6660                 /* Read POS in ${var:POS:LEN} */
6661                 colon = strchr(loc, ':');
6662                 if (colon) *colon = '\0';
6663                 pos = ash_arith(loc);
6664                 if (colon) *colon = ':';
6665
6666                 /* Read LEN in ${var:POS:LEN} */
6667                 len = str - startp - 1;
6668                 /* *loc != '\0', guaranteed by parser */
6669                 if (quotes) {
6670                         char *ptr;
6671
6672                         /* Adjust the length by the number of escapes */
6673                         for (ptr = startp; ptr < (str - 1); ptr++) {
6674                                 if ((unsigned char)*ptr == CTLESC) {
6675                                         len--;
6676                                         ptr++;
6677                                 }
6678                         }
6679                 }
6680                 orig_len = len;
6681                 if (*loc++ == ':') {
6682                         /* ${var::LEN} */
6683                         len = ash_arith(loc);
6684                 } else {
6685                         /* Skip POS in ${var:POS:LEN} */
6686                         len = orig_len;
6687                         while (*loc && *loc != ':') {
6688                                 loc++;
6689                         }
6690                         if (*loc++ == ':') {
6691                                 len = ash_arith(loc);
6692                         }
6693                 }
6694 #  undef ash_arith
6695
6696                 if (pos < 0) {
6697                         /* ${VAR:$((-n)):l} starts n chars from the end */
6698                         pos = orig_len + pos;
6699                 }
6700                 if ((unsigned)pos >= orig_len) {
6701                         /* apart from obvious ${VAR:999999:l},
6702                          * covers ${VAR:$((-9999999)):l} - result is ""
6703                          * (bash compat)
6704                          */
6705                         pos = 0;
6706                         len = 0;
6707                 }
6708                 if (len < 0) {
6709                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6710                         len = (orig_len - pos) + len;
6711                 }
6712                 if ((unsigned)len > (orig_len - pos))
6713                         len = orig_len - pos;
6714
6715                 for (str = startp; pos; str++, pos--) {
6716                         if (quotes && (unsigned char)*str == CTLESC)
6717                                 str++;
6718                 }
6719                 for (loc = startp; len; len--) {
6720                         if (quotes && (unsigned char)*str == CTLESC)
6721                                 *loc++ = *str++;
6722                         *loc++ = *str++;
6723                 }
6724                 *loc = '\0';
6725                 amount = loc - expdest;
6726                 STADJUST(amount, expdest);
6727                 return loc;
6728         }
6729 #endif /* BASH_SUBSTR */
6730         }
6731
6732         resetloc = expdest - (char *)stackblock();
6733
6734 #if BASH_PATTERN_SUBST
6735         /* We'll comeback here if we grow the stack while handling
6736          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6737          * stack will need rebasing, and we'll need to remove our work
6738          * areas each time
6739          */
6740  restart:
6741 #endif
6742
6743         amount = expdest - ((char *)stackblock() + resetloc);
6744         STADJUST(-amount, expdest);
6745         startp = (char *)stackblock() + startloc;
6746
6747         rmesc = startp;
6748         rmescend = (char *)stackblock() + strloc;
6749         if (quotes) {
6750                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6751                 if (rmesc != startp) {
6752                         rmescend = expdest;
6753                         startp = (char *)stackblock() + startloc;
6754                 }
6755         }
6756         rmescend--;
6757         str = (char *)stackblock() + strloc;
6758         /*
6759          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6760          * The result is a_\_z_c (not a\_\_z_c)!
6761          *
6762          * The search pattern and replace string treat backslashes differently!
6763          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6764          * and string.  It's only used on the first call.
6765          */
6766         preglob(str, IF_BASH_PATTERN_SUBST(
6767                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6768                         RMESCAPE_SLASH : ) 0);
6769
6770 #if BASH_PATTERN_SUBST
6771         workloc = expdest - (char *)stackblock();
6772         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6773                 int len;
6774                 char *idx, *end;
6775
6776                 if (!repl) {
6777                         repl = strchr(str, CTLESC);
6778                         if (repl)
6779                                 *repl++ = '\0';
6780                         else
6781                                 repl = nullstr;
6782                 }
6783                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6784
6785                 /* If there's no pattern to match, return the expansion unmolested */
6786                 if (str[0] == '\0')
6787                         return NULL;
6788
6789                 len = 0;
6790                 idx = startp;
6791                 end = str - 1;
6792                 while (idx < end) {
6793  try_to_match:
6794                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6795                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6796                         if (!loc) {
6797                                 /* No match, advance */
6798                                 char *restart_detect = stackblock();
6799  skip_matching:
6800                                 STPUTC(*idx, expdest);
6801                                 if (quotes && (unsigned char)*idx == CTLESC) {
6802                                         idx++;
6803                                         len++;
6804                                         STPUTC(*idx, expdest);
6805                                 }
6806                                 if (stackblock() != restart_detect)
6807                                         goto restart;
6808                                 idx++;
6809                                 len++;
6810                                 rmesc++;
6811                                 /* continue; - prone to quadratic behavior, smarter code: */
6812                                 if (idx >= end)
6813                                         break;
6814                                 if (str[0] == '*') {
6815                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6816                                          * it would never match "ong_string" etc, no point in trying.
6817                                          */
6818                                         goto skip_matching;
6819                                 }
6820                                 goto try_to_match;
6821                         }
6822
6823                         if (subtype == VSREPLACEALL) {
6824                                 while (idx < loc) {
6825                                         if (quotes && (unsigned char)*idx == CTLESC)
6826                                                 idx++;
6827                                         idx++;
6828                                         rmesc++;
6829                                 }
6830                         } else {
6831                                 idx = loc;
6832                         }
6833
6834                         //bb_error_msg("repl:'%s'", repl);
6835                         for (loc = (char*)repl; *loc; loc++) {
6836                                 char *restart_detect = stackblock();
6837                                 if (quotes && *loc == '\\') {
6838                                         STPUTC(CTLESC, expdest);
6839                                         len++;
6840                                 }
6841                                 STPUTC(*loc, expdest);
6842                                 if (stackblock() != restart_detect)
6843                                         goto restart;
6844                                 len++;
6845                         }
6846
6847                         if (subtype == VSREPLACE) {
6848                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6849                                 while (*idx) {
6850                                         char *restart_detect = stackblock();
6851                                         STPUTC(*idx, expdest);
6852                                         if (stackblock() != restart_detect)
6853                                                 goto restart;
6854                                         len++;
6855                                         idx++;
6856                                 }
6857                                 break;
6858                         }
6859                 }
6860
6861                 /* We've put the replaced text into a buffer at workloc, now
6862                  * move it to the right place and adjust the stack.
6863                  */
6864                 STPUTC('\0', expdest);
6865                 startp = (char *)stackblock() + startloc;
6866                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6867                 //bb_error_msg("startp:'%s'", startp);
6868                 amount = expdest - (startp + len);
6869                 STADJUST(-amount, expdest);
6870                 return startp;
6871         }
6872 #endif /* BASH_PATTERN_SUBST */
6873
6874         subtype -= VSTRIMRIGHT;
6875 #if DEBUG
6876         if (subtype < 0 || subtype > 7)
6877                 abort();
6878 #endif
6879         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6880         zero = subtype >> 1;
6881         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6882         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6883
6884         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6885         if (loc) {
6886                 if (zero) {
6887                         memmove(startp, loc, str - loc);
6888                         loc = startp + (str - loc) - 1;
6889                 }
6890                 *loc = '\0';
6891                 amount = loc - expdest;
6892                 STADJUST(amount, expdest);
6893         }
6894         return loc;
6895 }
6896
6897 /*
6898  * Add the value of a specialized variable to the stack string.
6899  * name parameter (examples):
6900  * ash -c 'echo $1'      name:'1='
6901  * ash -c 'echo $qwe'    name:'qwe='
6902  * ash -c 'echo $$'      name:'$='
6903  * ash -c 'echo ${$}'    name:'$='
6904  * ash -c 'echo ${$##q}' name:'$=q'
6905  * ash -c 'echo ${#$}'   name:'$='
6906  * note: examples with bad shell syntax:
6907  * ash -c 'echo ${#$1}'  name:'$=1'
6908  * ash -c 'echo ${#1#}'  name:'1=#'
6909  */
6910 static NOINLINE ssize_t
6911 varvalue(char *name, int varflags, int flags, int *quotedp)
6912 {
6913         const char *p;
6914         int num;
6915         int i;
6916         ssize_t len = 0;
6917         int sep;
6918         int quoted = *quotedp;
6919         int subtype = varflags & VSTYPE;
6920         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6921         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6922         int syntax;
6923
6924         sep = (flags & EXP_FULL) << CHAR_BIT;
6925         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6926
6927         switch (*name) {
6928         case '$':
6929                 num = rootpid;
6930                 goto numvar;
6931         case '?':
6932                 num = exitstatus;
6933                 goto numvar;
6934         case '#':
6935                 num = shellparam.nparam;
6936                 goto numvar;
6937         case '!':
6938                 num = backgndpid;
6939                 if (num == 0)
6940                         return -1;
6941  numvar:
6942                 len = cvtnum(num);
6943                 goto check_1char_name;
6944         case '-':
6945                 expdest = makestrspace(NOPTS, expdest);
6946                 for (i = NOPTS - 1; i >= 0; i--) {
6947                         if (optlist[i]) {
6948                                 USTPUTC(optletters(i), expdest);
6949                                 len++;
6950                         }
6951                 }
6952  check_1char_name:
6953 #if 0
6954                 /* handles cases similar to ${#$1} */
6955                 if (name[2] != '\0')
6956                         raise_error_syntax("bad substitution");
6957 #endif
6958                 break;
6959         case '@':
6960                 if (quoted && sep)
6961                         goto param;
6962                 /* fall through */
6963         case '*': {
6964                 char **ap;
6965                 char sepc;
6966
6967                 if (quoted)
6968                         sep = 0;
6969                 sep |= ifsset() ? ifsval()[0] : ' ';
6970  param:
6971                 sepc = sep;
6972                 *quotedp = !sepc;
6973                 ap = shellparam.p;
6974                 if (!ap)
6975                         return -1;
6976                 while ((p = *ap++) != NULL) {
6977                         len += strtodest(p, syntax, quotes);
6978
6979                         if (*ap && sep) {
6980                                 len++;
6981                                 memtodest(&sepc, 1, syntax, quotes);
6982                         }
6983                 }
6984                 break;
6985         } /* case '*' */
6986         case '0':
6987         case '1':
6988         case '2':
6989         case '3':
6990         case '4':
6991         case '5':
6992         case '6':
6993         case '7':
6994         case '8':
6995         case '9':
6996                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6997                 if (num < 0 || num > shellparam.nparam)
6998                         return -1;
6999                 p = num ? shellparam.p[num - 1] : arg0;
7000                 goto value;
7001         default:
7002                 /* NB: name has form "VAR=..." */
7003                 p = lookupvar(name);
7004  value:
7005                 if (!p)
7006                         return -1;
7007
7008                 len = strtodest(p, syntax, quotes);
7009 #if ENABLE_UNICODE_SUPPORT
7010                 if (subtype == VSLENGTH && len > 0) {
7011                         reinit_unicode_for_ash();
7012                         if (unicode_status == UNICODE_ON) {
7013                                 STADJUST(-len, expdest);
7014                                 discard = 0;
7015                                 len = unicode_strlen(p);
7016                         }
7017                 }
7018 #endif
7019                 break;
7020         }
7021
7022         if (discard)
7023                 STADJUST(-len, expdest);
7024         return len;
7025 }
7026
7027 /*
7028  * Expand a variable, and return a pointer to the next character in the
7029  * input string.
7030  */
7031 static char *
7032 evalvar(char *p, int flag)
7033 {
7034         char varflags;
7035         char subtype;
7036         int quoted;
7037         char easy;
7038         char *var;
7039         int patloc;
7040         int startloc;
7041         ssize_t varlen;
7042
7043         varflags = (unsigned char) *p++;
7044         subtype = varflags & VSTYPE;
7045
7046         if (!subtype)
7047                 raise_error_syntax("bad substitution");
7048
7049         quoted = flag & EXP_QUOTED;
7050         var = p;
7051         easy = (!quoted || (*var == '@' && shellparam.nparam));
7052         startloc = expdest - (char *)stackblock();
7053         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7054
7055  again:
7056         varlen = varvalue(var, varflags, flag, &quoted);
7057         if (varflags & VSNUL)
7058                 varlen--;
7059
7060         if (subtype == VSPLUS) {
7061                 varlen = -1 - varlen;
7062                 goto vsplus;
7063         }
7064
7065         if (subtype == VSMINUS) {
7066  vsplus:
7067                 if (varlen < 0) {
7068                         argstr(
7069                                 p,
7070                                 flag | EXP_TILDE | EXP_WORD
7071                         );
7072                         goto end;
7073                 }
7074                 goto record;
7075         }
7076
7077         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7078                 if (varlen >= 0)
7079                         goto record;
7080
7081                 subevalvar(p, var, 0, subtype, startloc, varflags,
7082                            flag & ~QUOTES_ESC);
7083                 varflags &= ~VSNUL;
7084                 /*
7085                  * Remove any recorded regions beyond
7086                  * start of variable
7087                  */
7088                 removerecordregions(startloc);
7089                 goto again;
7090         }
7091
7092         if (varlen < 0 && uflag)
7093                 varunset(p, var, 0, 0);
7094
7095         if (subtype == VSLENGTH) {
7096                 cvtnum(varlen > 0 ? varlen : 0);
7097                 goto record;
7098         }
7099
7100         if (subtype == VSNORMAL) {
7101  record:
7102                 if (!easy)
7103                         goto end;
7104                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7105                 goto end;
7106         }
7107
7108 #if DEBUG
7109         switch (subtype) {
7110         case VSTRIMLEFT:
7111         case VSTRIMLEFTMAX:
7112         case VSTRIMRIGHT:
7113         case VSTRIMRIGHTMAX:
7114 #if BASH_SUBSTR
7115         case VSSUBSTR:
7116 #endif
7117 #if BASH_PATTERN_SUBST
7118         case VSREPLACE:
7119         case VSREPLACEALL:
7120 #endif
7121                 break;
7122         default:
7123                 abort();
7124         }
7125 #endif
7126
7127         if (varlen >= 0) {
7128                 /*
7129                  * Terminate the string and start recording the pattern
7130                  * right after it
7131                  */
7132                 STPUTC('\0', expdest);
7133                 patloc = expdest - (char *)stackblock();
7134                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7135                                 startloc, varflags, flag)) {
7136                         int amount = expdest - (
7137                                 (char *)stackblock() + patloc - 1
7138                         );
7139                         STADJUST(-amount, expdest);
7140                 }
7141                 /* Remove any recorded regions beyond start of variable */
7142                 removerecordregions(startloc);
7143                 goto record;
7144         }
7145
7146  end:
7147         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7148                 int nesting = 1;
7149                 for (;;) {
7150                         unsigned char c = *p++;
7151                         if (c == CTLESC)
7152                                 p++;
7153                         else if (c == CTLBACKQ) {
7154                                 if (varlen >= 0)
7155                                         argbackq = argbackq->next;
7156                         } else if (c == CTLVAR) {
7157                                 if ((*p++ & VSTYPE) != VSNORMAL)
7158                                         nesting++;
7159                         } else if (c == CTLENDVAR) {
7160                                 if (--nesting == 0)
7161                                         break;
7162                         }
7163                 }
7164         }
7165         return p;
7166 }
7167
7168 /*
7169  * Add a file name to the list.
7170  */
7171 static void
7172 addfname(const char *name)
7173 {
7174         struct strlist *sp;
7175
7176         sp = stzalloc(sizeof(*sp));
7177         sp->text = sstrdup(name);
7178         *exparg.lastp = sp;
7179         exparg.lastp = &sp->next;
7180 }
7181
7182 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7183 static int
7184 hasmeta(const char *p)
7185 {
7186         static const char chars[] ALIGN1 = {
7187                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7188         };
7189
7190         for (;;) {
7191                 p = strpbrk(p, chars);
7192                 if (!p)
7193                         break;
7194                 switch ((unsigned char) *p) {
7195                 case CTLQUOTEMARK:
7196                         for (;;) {
7197                                 p++;
7198                                 if (*p == CTLQUOTEMARK)
7199                                         break;
7200                                 if (*p == CTLESC)
7201                                         p++;
7202                                 if (*p == '\0') /* huh? */
7203                                         return 0;
7204                         }
7205                         break;
7206                 case '\\':
7207                 case CTLESC:
7208                         p++;
7209                         if (*p == '\0')
7210                                 return 0;
7211                         break;
7212                 case '[':
7213                         if (!strchr(p + 1, ']')) {
7214                                 /* It's not a properly closed [] pattern,
7215                                  * but other metas may follow. Continue checking.
7216                                  * my[file* _is_ globbed by bash
7217                                  * and matches filenames like "my[file1".
7218                                  */
7219                                 break;
7220                         }
7221                         /* fallthrough */
7222                 default:
7223                 /* case '*': */
7224                 /* case '?': */
7225                         return 1;
7226                 }
7227                 p++;
7228         }
7229
7230         return 0;
7231 }
7232
7233 /* If we want to use glob() from libc... */
7234 #if !ENABLE_ASH_INTERNAL_GLOB
7235
7236 /* Add the result of glob() to the list */
7237 static void
7238 addglob(const glob_t *pglob)
7239 {
7240         char **p = pglob->gl_pathv;
7241
7242         do {
7243                 addfname(*p);
7244         } while (*++p);
7245 }
7246 static void
7247 expandmeta(struct strlist *str /*, int flag*/)
7248 {
7249         /* TODO - EXP_REDIR */
7250
7251         while (str) {
7252                 char *p;
7253                 glob_t pglob;
7254                 int i;
7255
7256                 if (fflag)
7257                         goto nometa;
7258
7259                 if (!hasmeta(str->text))
7260                         goto nometa;
7261
7262                 INT_OFF;
7263                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7264 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7265 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7266 //
7267 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7268 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7269 // Which means you need to unescape the string, right? Not so fast:
7270 // if there _is_ a file named "file\?" (with backslash), it is returned
7271 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7272 // You DON'T KNOW by looking at the result whether you need to unescape it.
7273 //
7274 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7275 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7276 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7277 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7278 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7279 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7280                 i = glob(p, 0, NULL, &pglob);
7281                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7282                 if (p != str->text)
7283                         free(p);
7284                 switch (i) {
7285                 case 0:
7286 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7287                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7288                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7289                                 goto nometa2;
7290 #endif
7291                         addglob(&pglob);
7292                         globfree(&pglob);
7293                         INT_ON;
7294                         break;
7295                 case GLOB_NOMATCH:
7296  //nometa2:
7297                         globfree(&pglob);
7298                         INT_ON;
7299  nometa:
7300                         *exparg.lastp = str;
7301                         rmescapes(str->text, 0);
7302                         exparg.lastp = &str->next;
7303                         break;
7304                 default:        /* GLOB_NOSPACE */
7305                         globfree(&pglob);
7306                         INT_ON;
7307                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7308                 }
7309                 str = str->next;
7310         }
7311 }
7312
7313 #else
7314 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7315
7316 /*
7317  * Do metacharacter (i.e. *, ?, [...]) expansion.
7318  */
7319 static void
7320 expmeta(char *expdir, char *enddir, char *name)
7321 {
7322         char *p;
7323         const char *cp;
7324         char *start;
7325         char *endname;
7326         int metaflag;
7327         struct stat statb;
7328         DIR *dirp;
7329         struct dirent *dp;
7330         int atend;
7331         int matchdot;
7332         int esc;
7333
7334         metaflag = 0;
7335         start = name;
7336         for (p = name; esc = 0, *p; p += esc + 1) {
7337                 if (*p == '*' || *p == '?')
7338                         metaflag = 1;
7339                 else if (*p == '[') {
7340                         char *q = p + 1;
7341                         if (*q == '!')
7342                                 q++;
7343                         for (;;) {
7344                                 if (*q == '\\')
7345                                         q++;
7346                                 if (*q == '/' || *q == '\0')
7347                                         break;
7348                                 if (*++q == ']') {
7349                                         metaflag = 1;
7350                                         break;
7351                                 }
7352                         }
7353                 } else {
7354                         if (*p == '\\')
7355                                 esc++;
7356                         if (p[esc] == '/') {
7357                                 if (metaflag)
7358                                         break;
7359                                 start = p + esc + 1;
7360                         }
7361                 }
7362         }
7363         if (metaflag == 0) {    /* we've reached the end of the file name */
7364                 if (enddir != expdir)
7365                         metaflag++;
7366                 p = name;
7367                 do {
7368                         if (*p == '\\')
7369                                 p++;
7370                         *enddir++ = *p;
7371                 } while (*p++);
7372                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7373                         addfname(expdir);
7374                 return;
7375         }
7376         endname = p;
7377         if (name < start) {
7378                 p = name;
7379                 do {
7380                         if (*p == '\\')
7381                                 p++;
7382                         *enddir++ = *p++;
7383                 } while (p < start);
7384         }
7385         if (enddir == expdir) {
7386                 cp = ".";
7387         } else if (enddir == expdir + 1 && *expdir == '/') {
7388                 cp = "/";
7389         } else {
7390                 cp = expdir;
7391                 enddir[-1] = '\0';
7392         }
7393         dirp = opendir(cp);
7394         if (dirp == NULL)
7395                 return;
7396         if (enddir != expdir)
7397                 enddir[-1] = '/';
7398         if (*endname == 0) {
7399                 atend = 1;
7400         } else {
7401                 atend = 0;
7402                 *endname = '\0';
7403                 endname += esc + 1;
7404         }
7405         matchdot = 0;
7406         p = start;
7407         if (*p == '\\')
7408                 p++;
7409         if (*p == '.')
7410                 matchdot++;
7411         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7412                 if (dp->d_name[0] == '.' && !matchdot)
7413                         continue;
7414                 if (pmatch(start, dp->d_name)) {
7415                         if (atend) {
7416                                 strcpy(enddir, dp->d_name);
7417                                 addfname(expdir);
7418                         } else {
7419                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7420                                         continue;
7421                                 p[-1] = '/';
7422                                 expmeta(expdir, p, endname);
7423                         }
7424                 }
7425         }
7426         closedir(dirp);
7427         if (!atend)
7428                 endname[-esc - 1] = esc ? '\\' : '/';
7429 }
7430
7431 static struct strlist *
7432 msort(struct strlist *list, int len)
7433 {
7434         struct strlist *p, *q = NULL;
7435         struct strlist **lpp;
7436         int half;
7437         int n;
7438
7439         if (len <= 1)
7440                 return list;
7441         half = len >> 1;
7442         p = list;
7443         for (n = half; --n >= 0;) {
7444                 q = p;
7445                 p = p->next;
7446         }
7447         q->next = NULL;                 /* terminate first half of list */
7448         q = msort(list, half);          /* sort first half of list */
7449         p = msort(p, len - half);               /* sort second half */
7450         lpp = &list;
7451         for (;;) {
7452 #if ENABLE_LOCALE_SUPPORT
7453                 if (strcoll(p->text, q->text) < 0)
7454 #else
7455                 if (strcmp(p->text, q->text) < 0)
7456 #endif
7457                                                 {
7458                         *lpp = p;
7459                         lpp = &p->next;
7460                         p = *lpp;
7461                         if (p == NULL) {
7462                                 *lpp = q;
7463                                 break;
7464                         }
7465                 } else {
7466                         *lpp = q;
7467                         lpp = &q->next;
7468                         q = *lpp;
7469                         if (q == NULL) {
7470                                 *lpp = p;
7471                                 break;
7472                         }
7473                 }
7474         }
7475         return list;
7476 }
7477
7478 /*
7479  * Sort the results of file name expansion.  It calculates the number of
7480  * strings to sort and then calls msort (short for merge sort) to do the
7481  * work.
7482  */
7483 static struct strlist *
7484 expsort(struct strlist *str)
7485 {
7486         int len;
7487         struct strlist *sp;
7488
7489         len = 0;
7490         for (sp = str; sp; sp = sp->next)
7491                 len++;
7492         return msort(str, len);
7493 }
7494
7495 static void
7496 expandmeta(struct strlist *str /*, int flag*/)
7497 {
7498         /* TODO - EXP_REDIR */
7499
7500         while (str) {
7501                 char *expdir;
7502                 struct strlist **savelastp;
7503                 struct strlist *sp;
7504                 char *p;
7505
7506                 if (fflag)
7507                         goto nometa;
7508                 if (!hasmeta(str->text))
7509                         goto nometa;
7510                 savelastp = exparg.lastp;
7511
7512                 INT_OFF;
7513                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7514                 {
7515                         int i = strlen(str->text);
7516 //BUGGY estimation of how long expanded name can be
7517                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7518                 }
7519                 expmeta(expdir, expdir, p);
7520                 free(expdir);
7521                 if (p != str->text)
7522                         free(p);
7523                 INT_ON;
7524                 if (exparg.lastp == savelastp) {
7525                         /*
7526                          * no matches
7527                          */
7528  nometa:
7529                         *exparg.lastp = str;
7530                         rmescapes(str->text, 0);
7531                         exparg.lastp = &str->next;
7532                 } else {
7533                         *exparg.lastp = NULL;
7534                         *savelastp = sp = expsort(*savelastp);
7535                         while (sp->next != NULL)
7536                                 sp = sp->next;
7537                         exparg.lastp = &sp->next;
7538                 }
7539                 str = str->next;
7540         }
7541 }
7542 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7543
7544 /*
7545  * Perform variable substitution and command substitution on an argument,
7546  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7547  * perform splitting and file name expansion.  When arglist is NULL, perform
7548  * here document expansion.
7549  */
7550 static void
7551 expandarg(union node *arg, struct arglist *arglist, int flag)
7552 {
7553         struct strlist *sp;
7554         char *p;
7555
7556         argbackq = arg->narg.backquote;
7557         STARTSTACKSTR(expdest);
7558         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7559         argstr(arg->narg.text, flag);
7560         p = _STPUTC('\0', expdest);
7561         expdest = p - 1;
7562         if (arglist == NULL) {
7563                 /* here document expanded */
7564                 goto out;
7565         }
7566         p = grabstackstr(p);
7567         TRACE(("expandarg: p:'%s'\n", p));
7568         exparg.lastp = &exparg.list;
7569         /*
7570          * TODO - EXP_REDIR
7571          */
7572         if (flag & EXP_FULL) {
7573                 ifsbreakup(p, &exparg);
7574                 *exparg.lastp = NULL;
7575                 exparg.lastp = &exparg.list;
7576                 expandmeta(exparg.list /*, flag*/);
7577         } else {
7578                 sp = stzalloc(sizeof(*sp));
7579                 sp->text = p;
7580                 *exparg.lastp = sp;
7581                 exparg.lastp = &sp->next;
7582         }
7583         *exparg.lastp = NULL;
7584         if (exparg.list) {
7585                 *arglist->lastp = exparg.list;
7586                 arglist->lastp = exparg.lastp;
7587         }
7588
7589  out:
7590         ifsfree();
7591 }
7592
7593 /*
7594  * Expand shell variables and backquotes inside a here document.
7595  */
7596 static void
7597 expandhere(union node *arg, int fd)
7598 {
7599         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7600         full_write(fd, stackblock(), expdest - (char *)stackblock());
7601 }
7602
7603 /*
7604  * Returns true if the pattern matches the string.
7605  */
7606 static int
7607 patmatch(char *pattern, const char *string)
7608 {
7609         char *p = preglob(pattern, 0);
7610         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7611         return pmatch(p, string);
7612 }
7613
7614 /*
7615  * See if a pattern matches in a case statement.
7616  */
7617 static int
7618 casematch(union node *pattern, char *val)
7619 {
7620         struct stackmark smark;
7621         int result;
7622
7623         setstackmark(&smark);
7624         argbackq = pattern->narg.backquote;
7625         STARTSTACKSTR(expdest);
7626         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7627         STACKSTRNUL(expdest);
7628         ifsfree();
7629         result = patmatch(stackblock(), val);
7630         popstackmark(&smark);
7631         return result;
7632 }
7633
7634
7635 /* ============ find_command */
7636
7637 struct builtincmd {
7638         const char *name;
7639         int (*builtin)(int, char **) FAST_FUNC;
7640         /* unsigned flags; */
7641 };
7642 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7643 /* "regular" builtins always take precedence over commands,
7644  * regardless of PATH=....%builtin... position */
7645 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7646 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7647
7648 struct cmdentry {
7649         smallint cmdtype;       /* CMDxxx */
7650         union param {
7651                 int index;
7652                 /* index >= 0 for commands without path (slashes) */
7653                 /* (TODO: what exactly does the value mean? PATH position?) */
7654                 /* index == -1 for commands with slashes */
7655                 /* index == (-2 - applet_no) for NOFORK applets */
7656                 const struct builtincmd *cmd;
7657                 struct funcnode *func;
7658         } u;
7659 };
7660 /* values of cmdtype */
7661 #define CMDUNKNOWN      -1      /* no entry in table for command */
7662 #define CMDNORMAL       0       /* command is an executable program */
7663 #define CMDFUNCTION     1       /* command is a shell function */
7664 #define CMDBUILTIN      2       /* command is a shell builtin */
7665
7666 /* action to find_command() */
7667 #define DO_ERR          0x01    /* prints errors */
7668 #define DO_ABS          0x02    /* checks absolute paths */
7669 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7670 #define DO_ALTPATH      0x08    /* using alternate path */
7671 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7672
7673 static void find_command(char *, struct cmdentry *, int, const char *);
7674
7675
7676 /* ============ Hashing commands */
7677
7678 /*
7679  * When commands are first encountered, they are entered in a hash table.
7680  * This ensures that a full path search will not have to be done for them
7681  * on each invocation.
7682  *
7683  * We should investigate converting to a linear search, even though that
7684  * would make the command name "hash" a misnomer.
7685  */
7686
7687 struct tblentry {
7688         struct tblentry *next;  /* next entry in hash chain */
7689         union param param;      /* definition of builtin function */
7690         smallint cmdtype;       /* CMDxxx */
7691         char rehash;            /* if set, cd done since entry created */
7692         char cmdname[1];        /* name of command */
7693 };
7694
7695 static struct tblentry **cmdtable;
7696 #define INIT_G_cmdtable() do { \
7697         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7698 } while (0)
7699
7700 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7701
7702
7703 static void
7704 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7705 {
7706 #if ENABLE_FEATURE_SH_STANDALONE
7707         if (applet_no >= 0) {
7708                 if (APPLET_IS_NOEXEC(applet_no)) {
7709                         clearenv();
7710                         while (*envp)
7711                                 putenv(*envp++);
7712                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7713                         run_applet_no_and_exit(applet_no, cmd, argv);
7714                 }
7715                 /* re-exec ourselves with the new arguments */
7716                 execve(bb_busybox_exec_path, argv, envp);
7717                 /* If they called chroot or otherwise made the binary no longer
7718                  * executable, fall through */
7719         }
7720 #endif
7721
7722  repeat:
7723 #ifdef SYSV
7724         do {
7725                 execve(cmd, argv, envp);
7726         } while (errno == EINTR);
7727 #else
7728         execve(cmd, argv, envp);
7729 #endif
7730         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7731                 /* Run "cmd" as a shell script:
7732                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7733                  * "If the execve() function fails with ENOEXEC, the shell
7734                  * shall execute a command equivalent to having a shell invoked
7735                  * with the command name as its first operand,
7736                  * with any remaining arguments passed to the new shell"
7737                  *
7738                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7739                  * just call ourselves.
7740                  *
7741                  * Note that bash reads ~80 chars of the file, and if it sees
7742                  * a zero byte before it sees newline, it doesn't try to
7743                  * interpret it, but fails with "cannot execute binary file"
7744                  * message and exit code 126. For one, this prevents attempts
7745                  * to interpret foreign ELF binaries as shell scripts.
7746                  */
7747                 argv[0] = (char*) cmd;
7748                 cmd = bb_busybox_exec_path;
7749                 /* NB: this is only possible because all callers of shellexec()
7750                  * ensure that the argv[-1] slot exists!
7751                  */
7752                 argv--;
7753                 argv[0] = (char*) "ash";
7754                 goto repeat;
7755         }
7756 }
7757
7758 /*
7759  * Exec a program.  Never returns.  If you change this routine, you may
7760  * have to change the find_command routine as well.
7761  * argv[-1] must exist and be writable! See tryexec() for why.
7762  */
7763 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7764 static void shellexec(char *prog, char **argv, const char *path, int idx)
7765 {
7766         char *cmdname;
7767         int e;
7768         char **envp;
7769         int exerrno;
7770         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7771
7772         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7773         if (strchr(prog, '/') != NULL
7774 #if ENABLE_FEATURE_SH_STANDALONE
7775          || (applet_no = find_applet_by_name(prog)) >= 0
7776 #endif
7777         ) {
7778                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7779                 if (applet_no >= 0) {
7780                         /* We tried execing ourself, but it didn't work.
7781                          * Maybe /proc/self/exe doesn't exist?
7782                          * Try $PATH search.
7783                          */
7784                         goto try_PATH;
7785                 }
7786                 e = errno;
7787         } else {
7788  try_PATH:
7789                 e = ENOENT;
7790                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7791                         if (--idx < 0 && pathopt == NULL) {
7792                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7793                                 if (errno != ENOENT && errno != ENOTDIR)
7794                                         e = errno;
7795                         }
7796                         stunalloc(cmdname);
7797                 }
7798         }
7799
7800         /* Map to POSIX errors */
7801         switch (e) {
7802         case EACCES:
7803                 exerrno = 126;
7804                 break;
7805         case ENOENT:
7806                 exerrno = 127;
7807                 break;
7808         default:
7809                 exerrno = 2;
7810                 break;
7811         }
7812         exitstatus = exerrno;
7813         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7814                 prog, e, suppress_int));
7815         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7816         /* NOTREACHED */
7817 }
7818
7819 static void
7820 printentry(struct tblentry *cmdp)
7821 {
7822         int idx;
7823         const char *path;
7824         char *name;
7825
7826         idx = cmdp->param.index;
7827         path = pathval();
7828         do {
7829                 name = path_advance(&path, cmdp->cmdname);
7830                 stunalloc(name);
7831         } while (--idx >= 0);
7832         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7833 }
7834
7835 /*
7836  * Clear out command entries.  The argument specifies the first entry in
7837  * PATH which has changed.
7838  */
7839 static void
7840 clearcmdentry(int firstchange)
7841 {
7842         struct tblentry **tblp;
7843         struct tblentry **pp;
7844         struct tblentry *cmdp;
7845
7846         INT_OFF;
7847         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7848                 pp = tblp;
7849                 while ((cmdp = *pp) != NULL) {
7850                         if ((cmdp->cmdtype == CMDNORMAL &&
7851                              cmdp->param.index >= firstchange)
7852                          || (cmdp->cmdtype == CMDBUILTIN &&
7853                              builtinloc >= firstchange)
7854                         ) {
7855                                 *pp = cmdp->next;
7856                                 free(cmdp);
7857                         } else {
7858                                 pp = &cmdp->next;
7859                         }
7860                 }
7861         }
7862         INT_ON;
7863 }
7864
7865 /*
7866  * Locate a command in the command hash table.  If "add" is nonzero,
7867  * add the command to the table if it is not already present.  The
7868  * variable "lastcmdentry" is set to point to the address of the link
7869  * pointing to the entry, so that delete_cmd_entry can delete the
7870  * entry.
7871  *
7872  * Interrupts must be off if called with add != 0.
7873  */
7874 static struct tblentry **lastcmdentry;
7875
7876 static struct tblentry *
7877 cmdlookup(const char *name, int add)
7878 {
7879         unsigned int hashval;
7880         const char *p;
7881         struct tblentry *cmdp;
7882         struct tblentry **pp;
7883
7884         p = name;
7885         hashval = (unsigned char)*p << 4;
7886         while (*p)
7887                 hashval += (unsigned char)*p++;
7888         hashval &= 0x7FFF;
7889         pp = &cmdtable[hashval % CMDTABLESIZE];
7890         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7891                 if (strcmp(cmdp->cmdname, name) == 0)
7892                         break;
7893                 pp = &cmdp->next;
7894         }
7895         if (add && cmdp == NULL) {
7896                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7897                                 + strlen(name)
7898                                 /* + 1 - already done because
7899                                  * tblentry::cmdname is char[1] */);
7900                 /*cmdp->next = NULL; - ckzalloc did it */
7901                 cmdp->cmdtype = CMDUNKNOWN;
7902                 strcpy(cmdp->cmdname, name);
7903         }
7904         lastcmdentry = pp;
7905         return cmdp;
7906 }
7907
7908 /*
7909  * Delete the command entry returned on the last lookup.
7910  */
7911 static void
7912 delete_cmd_entry(void)
7913 {
7914         struct tblentry *cmdp;
7915
7916         INT_OFF;
7917         cmdp = *lastcmdentry;
7918         *lastcmdentry = cmdp->next;
7919         if (cmdp->cmdtype == CMDFUNCTION)
7920                 freefunc(cmdp->param.func);
7921         free(cmdp);
7922         INT_ON;
7923 }
7924
7925 /*
7926  * Add a new command entry, replacing any existing command entry for
7927  * the same name - except special builtins.
7928  */
7929 static void
7930 addcmdentry(char *name, struct cmdentry *entry)
7931 {
7932         struct tblentry *cmdp;
7933
7934         cmdp = cmdlookup(name, 1);
7935         if (cmdp->cmdtype == CMDFUNCTION) {
7936                 freefunc(cmdp->param.func);
7937         }
7938         cmdp->cmdtype = entry->cmdtype;
7939         cmdp->param = entry->u;
7940         cmdp->rehash = 0;
7941 }
7942
7943 static int FAST_FUNC
7944 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7945 {
7946         struct tblentry **pp;
7947         struct tblentry *cmdp;
7948         int c;
7949         struct cmdentry entry;
7950         char *name;
7951
7952         if (nextopt("r") != '\0') {
7953                 clearcmdentry(0);
7954                 return 0;
7955         }
7956
7957         if (*argptr == NULL) {
7958                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7959                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7960                                 if (cmdp->cmdtype == CMDNORMAL)
7961                                         printentry(cmdp);
7962                         }
7963                 }
7964                 return 0;
7965         }
7966
7967         c = 0;
7968         while ((name = *argptr) != NULL) {
7969                 cmdp = cmdlookup(name, 0);
7970                 if (cmdp != NULL
7971                  && (cmdp->cmdtype == CMDNORMAL
7972                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7973                 ) {
7974                         delete_cmd_entry();
7975                 }
7976                 find_command(name, &entry, DO_ERR, pathval());
7977                 if (entry.cmdtype == CMDUNKNOWN)
7978                         c = 1;
7979                 argptr++;
7980         }
7981         return c;
7982 }
7983
7984 /*
7985  * Called when a cd is done.  Marks all commands so the next time they
7986  * are executed they will be rehashed.
7987  */
7988 static void
7989 hashcd(void)
7990 {
7991         struct tblentry **pp;
7992         struct tblentry *cmdp;
7993
7994         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7995                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7996                         if (cmdp->cmdtype == CMDNORMAL
7997                          || (cmdp->cmdtype == CMDBUILTIN
7998                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7999                              && builtinloc > 0)
8000                         ) {
8001                                 cmdp->rehash = 1;
8002                         }
8003                 }
8004         }
8005 }
8006
8007 /*
8008  * Fix command hash table when PATH changed.
8009  * Called before PATH is changed.  The argument is the new value of PATH;
8010  * pathval() still returns the old value at this point.
8011  * Called with interrupts off.
8012  */
8013 static void FAST_FUNC
8014 changepath(const char *new)
8015 {
8016         const char *old;
8017         int firstchange;
8018         int idx;
8019         int idx_bltin;
8020
8021         old = pathval();
8022         firstchange = 9999;     /* assume no change */
8023         idx = 0;
8024         idx_bltin = -1;
8025         for (;;) {
8026                 if (*old != *new) {
8027                         firstchange = idx;
8028                         if ((*old == '\0' && *new == ':')
8029                          || (*old == ':' && *new == '\0')
8030                         ) {
8031                                 firstchange++;
8032                         }
8033                         old = new;      /* ignore subsequent differences */
8034                 }
8035                 if (*new == '\0')
8036                         break;
8037                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8038                         idx_bltin = idx;
8039                 if (*new == ':')
8040                         idx++;
8041                 new++;
8042                 old++;
8043         }
8044         if (builtinloc < 0 && idx_bltin >= 0)
8045                 builtinloc = idx_bltin;             /* zap builtins */
8046         if (builtinloc >= 0 && idx_bltin < 0)
8047                 firstchange = 0;
8048         clearcmdentry(firstchange);
8049         builtinloc = idx_bltin;
8050 }
8051 enum {
8052         TEOF,
8053         TNL,
8054         TREDIR,
8055         TWORD,
8056         TSEMI,
8057         TBACKGND,
8058         TAND,
8059         TOR,
8060         TPIPE,
8061         TLP,
8062         TRP,
8063         TENDCASE,
8064         TENDBQUOTE,
8065         TNOT,
8066         TCASE,
8067         TDO,
8068         TDONE,
8069         TELIF,
8070         TELSE,
8071         TESAC,
8072         TFI,
8073         TFOR,
8074 #if BASH_FUNCTION
8075         TFUNCTION,
8076 #endif
8077         TIF,
8078         TIN,
8079         TTHEN,
8080         TUNTIL,
8081         TWHILE,
8082         TBEGIN,
8083         TEND
8084 };
8085 typedef smallint token_id_t;
8086
8087 /* Nth bit indicates if token marks the end of a list */
8088 enum {
8089         tokendlist = 0
8090         /*  0 */ | (1u << TEOF)
8091         /*  1 */ | (0u << TNL)
8092         /*  2 */ | (0u << TREDIR)
8093         /*  3 */ | (0u << TWORD)
8094         /*  4 */ | (0u << TSEMI)
8095         /*  5 */ | (0u << TBACKGND)
8096         /*  6 */ | (0u << TAND)
8097         /*  7 */ | (0u << TOR)
8098         /*  8 */ | (0u << TPIPE)
8099         /*  9 */ | (0u << TLP)
8100         /* 10 */ | (1u << TRP)
8101         /* 11 */ | (1u << TENDCASE)
8102         /* 12 */ | (1u << TENDBQUOTE)
8103         /* 13 */ | (0u << TNOT)
8104         /* 14 */ | (0u << TCASE)
8105         /* 15 */ | (1u << TDO)
8106         /* 16 */ | (1u << TDONE)
8107         /* 17 */ | (1u << TELIF)
8108         /* 18 */ | (1u << TELSE)
8109         /* 19 */ | (1u << TESAC)
8110         /* 20 */ | (1u << TFI)
8111         /* 21 */ | (0u << TFOR)
8112 #if BASH_FUNCTION
8113         /* 22 */ | (0u << TFUNCTION)
8114 #endif
8115         /* 23 */ | (0u << TIF)
8116         /* 24 */ | (0u << TIN)
8117         /* 25 */ | (1u << TTHEN)
8118         /* 26 */ | (0u << TUNTIL)
8119         /* 27 */ | (0u << TWHILE)
8120         /* 28 */ | (0u << TBEGIN)
8121         /* 29 */ | (1u << TEND)
8122         , /* thus far 29 bits used */
8123 };
8124
8125 static const char *const tokname_array[] = {
8126         "end of file",
8127         "newline",
8128         "redirection",
8129         "word",
8130         ";",
8131         "&",
8132         "&&",
8133         "||",
8134         "|",
8135         "(",
8136         ")",
8137         ";;",
8138         "`",
8139 #define KWDOFFSET 13
8140         /* the following are keywords */
8141         "!",
8142         "case",
8143         "do",
8144         "done",
8145         "elif",
8146         "else",
8147         "esac",
8148         "fi",
8149         "for",
8150 #if BASH_FUNCTION
8151         "function",
8152 #endif
8153         "if",
8154         "in",
8155         "then",
8156         "until",
8157         "while",
8158         "{",
8159         "}",
8160 };
8161
8162 /* Wrapper around strcmp for qsort/bsearch/... */
8163 static int
8164 pstrcmp(const void *a, const void *b)
8165 {
8166         return strcmp((char*)a, *(char**)b);
8167 }
8168
8169 static const char *const *
8170 findkwd(const char *s)
8171 {
8172         return bsearch(s, tokname_array + KWDOFFSET,
8173                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8174                         sizeof(tokname_array[0]), pstrcmp);
8175 }
8176
8177 /*
8178  * Locate and print what a word is...
8179  */
8180 static int
8181 describe_command(char *command, const char *path, int describe_command_verbose)
8182 {
8183         struct cmdentry entry;
8184 #if ENABLE_ASH_ALIAS
8185         const struct alias *ap;
8186 #endif
8187
8188         path = path ? path : pathval();
8189
8190         if (describe_command_verbose) {
8191                 out1str(command);
8192         }
8193
8194         /* First look at the keywords */
8195         if (findkwd(command)) {
8196                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8197                 goto out;
8198         }
8199
8200 #if ENABLE_ASH_ALIAS
8201         /* Then look at the aliases */
8202         ap = lookupalias(command, 0);
8203         if (ap != NULL) {
8204                 if (!describe_command_verbose) {
8205                         out1str("alias ");
8206                         printalias(ap);
8207                         return 0;
8208                 }
8209                 out1fmt(" is an alias for %s", ap->val);
8210                 goto out;
8211         }
8212 #endif
8213         /* Brute force */
8214         find_command(command, &entry, DO_ABS, path);
8215
8216         switch (entry.cmdtype) {
8217         case CMDNORMAL: {
8218                 int j = entry.u.index;
8219                 char *p;
8220                 if (j < 0) {
8221                         p = command;
8222                 } else {
8223                         do {
8224                                 p = path_advance(&path, command);
8225                                 stunalloc(p);
8226                         } while (--j >= 0);
8227                 }
8228                 if (describe_command_verbose) {
8229                         out1fmt(" is %s", p);
8230                 } else {
8231                         out1str(p);
8232                 }
8233                 break;
8234         }
8235
8236         case CMDFUNCTION:
8237                 if (describe_command_verbose) {
8238                         out1str(" is a shell function");
8239                 } else {
8240                         out1str(command);
8241                 }
8242                 break;
8243
8244         case CMDBUILTIN:
8245                 if (describe_command_verbose) {
8246                         out1fmt(" is a %sshell builtin",
8247                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8248                                         "special " : nullstr
8249                         );
8250                 } else {
8251                         out1str(command);
8252                 }
8253                 break;
8254
8255         default:
8256                 if (describe_command_verbose) {
8257                         out1str(": not found\n");
8258                 }
8259                 return 127;
8260         }
8261  out:
8262         out1str("\n");
8263         return 0;
8264 }
8265
8266 static int FAST_FUNC
8267 typecmd(int argc UNUSED_PARAM, char **argv)
8268 {
8269         int i = 1;
8270         int err = 0;
8271         int verbose = 1;
8272
8273         /* type -p ... ? (we don't bother checking for 'p') */
8274         if (argv[1] && argv[1][0] == '-') {
8275                 i++;
8276                 verbose = 0;
8277         }
8278         while (argv[i]) {
8279                 err |= describe_command(argv[i++], NULL, verbose);
8280         }
8281         return err;
8282 }
8283
8284 #if ENABLE_ASH_CMDCMD
8285 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8286 static char **
8287 parse_command_args(char **argv, const char **path)
8288 {
8289         char *cp, c;
8290
8291         for (;;) {
8292                 cp = *++argv;
8293                 if (!cp)
8294                         return NULL;
8295                 if (*cp++ != '-')
8296                         break;
8297                 c = *cp++;
8298                 if (!c)
8299                         break;
8300                 if (c == '-' && !*cp) {
8301                         if (!*++argv)
8302                                 return NULL;
8303                         break;
8304                 }
8305                 do {
8306                         switch (c) {
8307                         case 'p':
8308                                 *path = bb_default_path;
8309                                 break;
8310                         default:
8311                                 /* run 'typecmd' for other options */
8312                                 return NULL;
8313                         }
8314                         c = *cp++;
8315                 } while (c);
8316         }
8317         return argv;
8318 }
8319
8320 static int FAST_FUNC
8321 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8322 {
8323         char *cmd;
8324         int c;
8325         enum {
8326                 VERIFY_BRIEF = 1,
8327                 VERIFY_VERBOSE = 2,
8328         } verify = 0;
8329         const char *path = NULL;
8330
8331         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8332          * never reaches this function.
8333          */
8334
8335         while ((c = nextopt("pvV")) != '\0')
8336                 if (c == 'V')
8337                         verify |= VERIFY_VERBOSE;
8338                 else if (c == 'v')
8339                         /*verify |= VERIFY_BRIEF*/;
8340 #if DEBUG
8341                 else if (c != 'p')
8342                         abort();
8343 #endif
8344                 else
8345                         path = bb_default_path;
8346
8347         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8348         cmd = *argptr;
8349         if (/*verify && */ cmd)
8350                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8351
8352         return 0;
8353 }
8354 #endif
8355
8356
8357 /*static int funcblocksize;     // size of structures in function */
8358 /*static int funcstringsize;    // size of strings in node */
8359 static void *funcblock;         /* block to allocate function from */
8360 static char *funcstring_end;    /* end of block to allocate strings from */
8361
8362 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8363         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8364         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8365         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8366         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8367         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8368         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8369         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8370         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8371         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8372         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8373         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8374         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8375         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8376         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8377         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8378         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8379         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8380 #if BASH_REDIR_OUTPUT
8381         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8382 #endif
8383         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8384         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8385         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8386         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8387         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8388         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8389         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8390         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8391         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8392 };
8393
8394 static int calcsize(int funcblocksize, union node *n);
8395
8396 static int
8397 sizenodelist(int funcblocksize, struct nodelist *lp)
8398 {
8399         while (lp) {
8400                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8401                 funcblocksize = calcsize(funcblocksize, lp->n);
8402                 lp = lp->next;
8403         }
8404         return funcblocksize;
8405 }
8406
8407 static int
8408 calcsize(int funcblocksize, union node *n)
8409 {
8410         if (n == NULL)
8411                 return funcblocksize;
8412         funcblocksize += nodesize[n->type];
8413         switch (n->type) {
8414         case NCMD:
8415                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8416                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8417                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8418                 break;
8419         case NPIPE:
8420                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8421                 break;
8422         case NREDIR:
8423         case NBACKGND:
8424         case NSUBSHELL:
8425                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8426                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8427                 break;
8428         case NAND:
8429         case NOR:
8430         case NSEMI:
8431         case NWHILE:
8432         case NUNTIL:
8433                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8434                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8435                 break;
8436         case NIF:
8437                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8438                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8439                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8440                 break;
8441         case NFOR:
8442                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8443                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8444                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8445                 break;
8446         case NCASE:
8447                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8448                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8449                 break;
8450         case NCLIST:
8451                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8452                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8453                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8454                 break;
8455         case NDEFUN:
8456         case NARG:
8457                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8458                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8459                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8460                 break;
8461         case NTO:
8462 #if BASH_REDIR_OUTPUT
8463         case NTO2:
8464 #endif
8465         case NCLOBBER:
8466         case NFROM:
8467         case NFROMTO:
8468         case NAPPEND:
8469                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8470                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8471                 break;
8472         case NTOFD:
8473         case NFROMFD:
8474                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8475                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8476         break;
8477         case NHERE:
8478         case NXHERE:
8479                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8480                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8481                 break;
8482         case NNOT:
8483                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8484                 break;
8485         };
8486         return funcblocksize;
8487 }
8488
8489 static char *
8490 nodeckstrdup(char *s)
8491 {
8492         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8493         return strcpy(funcstring_end, s);
8494 }
8495
8496 static union node *copynode(union node *);
8497
8498 static struct nodelist *
8499 copynodelist(struct nodelist *lp)
8500 {
8501         struct nodelist *start;
8502         struct nodelist **lpp;
8503
8504         lpp = &start;
8505         while (lp) {
8506                 *lpp = funcblock;
8507                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8508                 (*lpp)->n = copynode(lp->n);
8509                 lp = lp->next;
8510                 lpp = &(*lpp)->next;
8511         }
8512         *lpp = NULL;
8513         return start;
8514 }
8515
8516 static union node *
8517 copynode(union node *n)
8518 {
8519         union node *new;
8520
8521         if (n == NULL)
8522                 return NULL;
8523         new = funcblock;
8524         funcblock = (char *) funcblock + nodesize[n->type];
8525
8526         switch (n->type) {
8527         case NCMD:
8528                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8529                 new->ncmd.args = copynode(n->ncmd.args);
8530                 new->ncmd.assign = copynode(n->ncmd.assign);
8531                 break;
8532         case NPIPE:
8533                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8534                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8535                 break;
8536         case NREDIR:
8537         case NBACKGND:
8538         case NSUBSHELL:
8539                 new->nredir.redirect = copynode(n->nredir.redirect);
8540                 new->nredir.n = copynode(n->nredir.n);
8541                 break;
8542         case NAND:
8543         case NOR:
8544         case NSEMI:
8545         case NWHILE:
8546         case NUNTIL:
8547                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8548                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8549                 break;
8550         case NIF:
8551                 new->nif.elsepart = copynode(n->nif.elsepart);
8552                 new->nif.ifpart = copynode(n->nif.ifpart);
8553                 new->nif.test = copynode(n->nif.test);
8554                 break;
8555         case NFOR:
8556                 new->nfor.var = nodeckstrdup(n->nfor.var);
8557                 new->nfor.body = copynode(n->nfor.body);
8558                 new->nfor.args = copynode(n->nfor.args);
8559                 break;
8560         case NCASE:
8561                 new->ncase.cases = copynode(n->ncase.cases);
8562                 new->ncase.expr = copynode(n->ncase.expr);
8563                 break;
8564         case NCLIST:
8565                 new->nclist.body = copynode(n->nclist.body);
8566                 new->nclist.pattern = copynode(n->nclist.pattern);
8567                 new->nclist.next = copynode(n->nclist.next);
8568                 break;
8569         case NDEFUN:
8570         case NARG:
8571                 new->narg.backquote = copynodelist(n->narg.backquote);
8572                 new->narg.text = nodeckstrdup(n->narg.text);
8573                 new->narg.next = copynode(n->narg.next);
8574                 break;
8575         case NTO:
8576 #if BASH_REDIR_OUTPUT
8577         case NTO2:
8578 #endif
8579         case NCLOBBER:
8580         case NFROM:
8581         case NFROMTO:
8582         case NAPPEND:
8583                 new->nfile.fname = copynode(n->nfile.fname);
8584                 new->nfile.fd = n->nfile.fd;
8585                 new->nfile.next = copynode(n->nfile.next);
8586                 break;
8587         case NTOFD:
8588         case NFROMFD:
8589                 new->ndup.vname = copynode(n->ndup.vname);
8590                 new->ndup.dupfd = n->ndup.dupfd;
8591                 new->ndup.fd = n->ndup.fd;
8592                 new->ndup.next = copynode(n->ndup.next);
8593                 break;
8594         case NHERE:
8595         case NXHERE:
8596                 new->nhere.doc = copynode(n->nhere.doc);
8597                 new->nhere.fd = n->nhere.fd;
8598                 new->nhere.next = copynode(n->nhere.next);
8599                 break;
8600         case NNOT:
8601                 new->nnot.com = copynode(n->nnot.com);
8602                 break;
8603         };
8604         new->type = n->type;
8605         return new;
8606 }
8607
8608 /*
8609  * Make a copy of a parse tree.
8610  */
8611 static struct funcnode *
8612 copyfunc(union node *n)
8613 {
8614         struct funcnode *f;
8615         size_t blocksize;
8616
8617         /*funcstringsize = 0;*/
8618         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8619         f = ckzalloc(blocksize /* + funcstringsize */);
8620         funcblock = (char *) f + offsetof(struct funcnode, n);
8621         funcstring_end = (char *) f + blocksize;
8622         copynode(n);
8623         /* f->count = 0; - ckzalloc did it */
8624         return f;
8625 }
8626
8627 /*
8628  * Define a shell function.
8629  */
8630 static void
8631 defun(union node *func)
8632 {
8633         struct cmdentry entry;
8634
8635         INT_OFF;
8636         entry.cmdtype = CMDFUNCTION;
8637         entry.u.func = copyfunc(func);
8638         addcmdentry(func->narg.text, &entry);
8639         INT_ON;
8640 }
8641
8642 /* Reasons for skipping commands (see comment on breakcmd routine) */
8643 #define SKIPBREAK      (1 << 0)
8644 #define SKIPCONT       (1 << 1)
8645 #define SKIPFUNC       (1 << 2)
8646 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8647 static int skipcount;           /* number of levels to skip */
8648 static int funcnest;            /* depth of function calls */
8649 static int loopnest;            /* current loop nesting level */
8650
8651 /* Forward decl way out to parsing code - dotrap needs it */
8652 static int evalstring(char *s, int flags);
8653
8654 /* Called to execute a trap.
8655  * Single callsite - at the end of evaltree().
8656  * If we return non-zero, evaltree raises EXEXIT exception.
8657  *
8658  * Perhaps we should avoid entering new trap handlers
8659  * while we are executing a trap handler. [is it a TODO?]
8660  */
8661 static void
8662 dotrap(void)
8663 {
8664         uint8_t *g;
8665         int sig;
8666         uint8_t last_status;
8667
8668         if (!pending_sig)
8669                 return;
8670
8671         last_status = exitstatus;
8672         pending_sig = 0;
8673         barrier();
8674
8675         TRACE(("dotrap entered\n"));
8676         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8677                 char *p;
8678
8679                 if (!*g)
8680                         continue;
8681
8682                 if (evalskip) {
8683                         pending_sig = sig;
8684                         break;
8685                 }
8686
8687                 p = trap[sig];
8688                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8689                  * don't upset it by resetting gotsig[SIGINT-1] */
8690                 if (sig == SIGINT && !p)
8691                         continue;
8692
8693                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8694                 *g = 0;
8695                 if (!p)
8696                         continue;
8697                 evalstring(p, 0);
8698         }
8699         exitstatus = last_status;
8700         TRACE(("dotrap returns\n"));
8701 }
8702
8703 /* forward declarations - evaluation is fairly recursive business... */
8704 static int evalloop(union node *, int);
8705 static int evalfor(union node *, int);
8706 static int evalcase(union node *, int);
8707 static int evalsubshell(union node *, int);
8708 static void expredir(union node *);
8709 static int evalpipe(union node *, int);
8710 static int evalcommand(union node *, int);
8711 static int evalbltin(const struct builtincmd *, int, char **, int);
8712 static void prehash(union node *);
8713
8714 /*
8715  * Evaluate a parse tree.  The value is left in the global variable
8716  * exitstatus.
8717  */
8718 static int
8719 evaltree(union node *n, int flags)
8720 {
8721         int checkexit = 0;
8722         int (*evalfn)(union node *, int);
8723         int status = 0;
8724
8725         if (n == NULL) {
8726                 TRACE(("evaltree(NULL) called\n"));
8727                 goto out;
8728         }
8729         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8730
8731         dotrap();
8732
8733         switch (n->type) {
8734         default:
8735 #if DEBUG
8736                 out1fmt("Node type = %d\n", n->type);
8737                 fflush_all();
8738                 break;
8739 #endif
8740         case NNOT:
8741                 status = !evaltree(n->nnot.com, EV_TESTED);
8742                 goto setstatus;
8743         case NREDIR:
8744                 expredir(n->nredir.redirect);
8745                 pushredir(n->nredir.redirect);
8746                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8747                 if (!status) {
8748                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8749                 }
8750                 if (n->nredir.redirect)
8751                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8752                 goto setstatus;
8753         case NCMD:
8754                 evalfn = evalcommand;
8755  checkexit:
8756                 if (eflag && !(flags & EV_TESTED))
8757                         checkexit = ~0;
8758                 goto calleval;
8759         case NFOR:
8760                 evalfn = evalfor;
8761                 goto calleval;
8762         case NWHILE:
8763         case NUNTIL:
8764                 evalfn = evalloop;
8765                 goto calleval;
8766         case NSUBSHELL:
8767         case NBACKGND:
8768                 evalfn = evalsubshell;
8769                 goto checkexit;
8770         case NPIPE:
8771                 evalfn = evalpipe;
8772                 goto checkexit;
8773         case NCASE:
8774                 evalfn = evalcase;
8775                 goto calleval;
8776         case NAND:
8777         case NOR:
8778         case NSEMI: {
8779
8780 #if NAND + 1 != NOR
8781 #error NAND + 1 != NOR
8782 #endif
8783 #if NOR + 1 != NSEMI
8784 #error NOR + 1 != NSEMI
8785 #endif
8786                 unsigned is_or = n->type - NAND;
8787                 status = evaltree(
8788                         n->nbinary.ch1,
8789                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8790                 );
8791                 if ((!status) == is_or || evalskip)
8792                         break;
8793                 n = n->nbinary.ch2;
8794  evaln:
8795                 evalfn = evaltree;
8796  calleval:
8797                 status = evalfn(n, flags);
8798                 goto setstatus;
8799         }
8800         case NIF:
8801                 status = evaltree(n->nif.test, EV_TESTED);
8802                 if (evalskip)
8803                         break;
8804                 if (!status) {
8805                         n = n->nif.ifpart;
8806                         goto evaln;
8807                 }
8808                 if (n->nif.elsepart) {
8809                         n = n->nif.elsepart;
8810                         goto evaln;
8811                 }
8812                 status = 0;
8813                 goto setstatus;
8814         case NDEFUN:
8815                 defun(n);
8816                 /* Not necessary. To test it:
8817                  * "false; f() { qwerty; }; echo $?" should print 0.
8818                  */
8819                 /* status = 0; */
8820  setstatus:
8821                 exitstatus = status;
8822                 break;
8823         }
8824  out:
8825         /* Order of checks below is important:
8826          * signal handlers trigger before exit caused by "set -e".
8827          */
8828         dotrap();
8829
8830         if (checkexit & status)
8831                 raise_exception(EXEXIT);
8832         if (flags & EV_EXIT)
8833                 raise_exception(EXEXIT);
8834
8835         TRACE(("leaving evaltree (no interrupts)\n"));
8836         return exitstatus;
8837 }
8838
8839 static int
8840 skiploop(void)
8841 {
8842         int skip = evalskip;
8843
8844         switch (skip) {
8845         case 0:
8846                 break;
8847         case SKIPBREAK:
8848         case SKIPCONT:
8849                 if (--skipcount <= 0) {
8850                         evalskip = 0;
8851                         break;
8852                 }
8853                 skip = SKIPBREAK;
8854                 break;
8855         }
8856         return skip;
8857 }
8858
8859 static int
8860 evalloop(union node *n, int flags)
8861 {
8862         int skip;
8863         int status;
8864
8865         loopnest++;
8866         status = 0;
8867         flags &= EV_TESTED;
8868         do {
8869                 int i;
8870
8871                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8872                 skip = skiploop();
8873                 if (skip == SKIPFUNC)
8874                         status = i;
8875                 if (skip)
8876                         continue;
8877                 if (n->type != NWHILE)
8878                         i = !i;
8879                 if (i != 0)
8880                         break;
8881                 status = evaltree(n->nbinary.ch2, flags);
8882                 skip = skiploop();
8883         } while (!(skip & ~SKIPCONT));
8884         loopnest--;
8885
8886         return status;
8887 }
8888
8889 static int
8890 evalfor(union node *n, int flags)
8891 {
8892         struct arglist arglist;
8893         union node *argp;
8894         struct strlist *sp;
8895         struct stackmark smark;
8896         int status = 0;
8897
8898         setstackmark(&smark);
8899         arglist.list = NULL;
8900         arglist.lastp = &arglist.list;
8901         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8902                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8903         }
8904         *arglist.lastp = NULL;
8905
8906         loopnest++;
8907         flags &= EV_TESTED;
8908         for (sp = arglist.list; sp; sp = sp->next) {
8909                 setvar0(n->nfor.var, sp->text);
8910                 status = evaltree(n->nfor.body, flags);
8911                 if (skiploop() & ~SKIPCONT)
8912                         break;
8913         }
8914         loopnest--;
8915         popstackmark(&smark);
8916
8917         return status;
8918 }
8919
8920 static int
8921 evalcase(union node *n, int flags)
8922 {
8923         union node *cp;
8924         union node *patp;
8925         struct arglist arglist;
8926         struct stackmark smark;
8927         int status = 0;
8928
8929         setstackmark(&smark);
8930         arglist.list = NULL;
8931         arglist.lastp = &arglist.list;
8932         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8933         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8934                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8935                         if (casematch(patp, arglist.list->text)) {
8936                                 /* Ensure body is non-empty as otherwise
8937                                  * EV_EXIT may prevent us from setting the
8938                                  * exit status.
8939                                  */
8940                                 if (evalskip == 0 && cp->nclist.body) {
8941                                         status = evaltree(cp->nclist.body, flags);
8942                                 }
8943                                 goto out;
8944                         }
8945                 }
8946         }
8947  out:
8948         popstackmark(&smark);
8949
8950         return status;
8951 }
8952
8953 /*
8954  * Kick off a subshell to evaluate a tree.
8955  */
8956 static int
8957 evalsubshell(union node *n, int flags)
8958 {
8959         struct job *jp;
8960         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8961         int status;
8962
8963         expredir(n->nredir.redirect);
8964         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8965                 goto nofork;
8966         INT_OFF;
8967         if (backgnd == FORK_FG)
8968                 get_tty_state();
8969         jp = makejob(/*n,*/ 1);
8970         if (forkshell(jp, n, backgnd) == 0) {
8971                 /* child */
8972                 INT_ON;
8973                 flags |= EV_EXIT;
8974                 if (backgnd)
8975                         flags &= ~EV_TESTED;
8976  nofork:
8977                 redirect(n->nredir.redirect, 0);
8978                 evaltreenr(n->nredir.n, flags);
8979                 /* never returns */
8980         }
8981         /* parent */
8982         status = 0;
8983         if (backgnd == FORK_FG)
8984                 status = waitforjob(jp);
8985         INT_ON;
8986         return status;
8987 }
8988
8989 /*
8990  * Compute the names of the files in a redirection list.
8991  */
8992 static void fixredir(union node *, const char *, int);
8993 static void
8994 expredir(union node *n)
8995 {
8996         union node *redir;
8997
8998         for (redir = n; redir; redir = redir->nfile.next) {
8999                 struct arglist fn;
9000
9001                 fn.list = NULL;
9002                 fn.lastp = &fn.list;
9003                 switch (redir->type) {
9004                 case NFROMTO:
9005                 case NFROM:
9006                 case NTO:
9007 #if BASH_REDIR_OUTPUT
9008                 case NTO2:
9009 #endif
9010                 case NCLOBBER:
9011                 case NAPPEND:
9012                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9013                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9014 #if BASH_REDIR_OUTPUT
9015  store_expfname:
9016 #endif
9017 #if 0
9018 // By the design of stack allocator, the loop of this kind:
9019 //      while true; do while true; do break; done </dev/null; done
9020 // will look like a memory leak: ash plans to free expfname's
9021 // of "/dev/null" as soon as it finishes running the loop
9022 // (in this case, never).
9023 // This "fix" is wrong:
9024                         if (redir->nfile.expfname)
9025                                 stunalloc(redir->nfile.expfname);
9026 // It results in corrupted state of stacked allocations.
9027 #endif
9028                         redir->nfile.expfname = fn.list->text;
9029                         break;
9030                 case NFROMFD:
9031                 case NTOFD: /* >& */
9032                         if (redir->ndup.vname) {
9033                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9034                                 if (fn.list == NULL)
9035                                         ash_msg_and_raise_error("redir error");
9036 #if BASH_REDIR_OUTPUT
9037 //FIXME: we used expandarg with different args!
9038                                 if (!isdigit_str9(fn.list->text)) {
9039                                         /* >&file, not >&fd */
9040                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9041                                                 ash_msg_and_raise_error("redir error");
9042                                         redir->type = NTO2;
9043                                         goto store_expfname;
9044                                 }
9045 #endif
9046                                 fixredir(redir, fn.list->text, 1);
9047                         }
9048                         break;
9049                 }
9050         }
9051 }
9052
9053 /*
9054  * Evaluate a pipeline.  All the processes in the pipeline are children
9055  * of the process creating the pipeline.  (This differs from some versions
9056  * of the shell, which make the last process in a pipeline the parent
9057  * of all the rest.)
9058  */
9059 static int
9060 evalpipe(union node *n, int flags)
9061 {
9062         struct job *jp;
9063         struct nodelist *lp;
9064         int pipelen;
9065         int prevfd;
9066         int pip[2];
9067         int status = 0;
9068
9069         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9070         pipelen = 0;
9071         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9072                 pipelen++;
9073         flags |= EV_EXIT;
9074         INT_OFF;
9075         if (n->npipe.pipe_backgnd == 0)
9076                 get_tty_state();
9077         jp = makejob(/*n,*/ pipelen);
9078         prevfd = -1;
9079         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9080                 prehash(lp->n);
9081                 pip[1] = -1;
9082                 if (lp->next) {
9083                         if (pipe(pip) < 0) {
9084                                 close(prevfd);
9085                                 ash_msg_and_raise_error("pipe call failed");
9086                         }
9087                 }
9088                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9089                         /* child */
9090                         INT_ON;
9091                         if (pip[1] >= 0) {
9092                                 close(pip[0]);
9093                         }
9094                         if (prevfd > 0) {
9095                                 dup2(prevfd, 0);
9096                                 close(prevfd);
9097                         }
9098                         if (pip[1] > 1) {
9099                                 dup2(pip[1], 1);
9100                                 close(pip[1]);
9101                         }
9102                         evaltreenr(lp->n, flags);
9103                         /* never returns */
9104                 }
9105                 /* parent */
9106                 if (prevfd >= 0)
9107                         close(prevfd);
9108                 prevfd = pip[0];
9109                 /* Don't want to trigger debugging */
9110                 if (pip[1] != -1)
9111                         close(pip[1]);
9112         }
9113         if (n->npipe.pipe_backgnd == 0) {
9114                 status = waitforjob(jp);
9115                 TRACE(("evalpipe:  job done exit status %d\n", status));
9116         }
9117         INT_ON;
9118
9119         return status;
9120 }
9121
9122 /*
9123  * Controls whether the shell is interactive or not.
9124  */
9125 static void
9126 setinteractive(int on)
9127 {
9128         static smallint is_interactive;
9129
9130         if (++on == is_interactive)
9131                 return;
9132         is_interactive = on;
9133         setsignal(SIGINT);
9134         setsignal(SIGQUIT);
9135         setsignal(SIGTERM);
9136 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9137         if (is_interactive > 1) {
9138                 /* Looks like they want an interactive shell */
9139                 static smallint did_banner;
9140
9141                 if (!did_banner) {
9142                         /* note: ash and hush share this string */
9143                         out1fmt("\n\n%s %s\n"
9144                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9145                                 "\n",
9146                                 bb_banner,
9147                                 "built-in shell (ash)"
9148                         );
9149                         did_banner = 1;
9150                 }
9151         }
9152 #endif
9153 }
9154
9155 static void
9156 optschanged(void)
9157 {
9158 #if DEBUG
9159         opentrace();
9160 #endif
9161         setinteractive(iflag);
9162         setjobctl(mflag);
9163 #if ENABLE_FEATURE_EDITING_VI
9164         if (viflag)
9165                 line_input_state->flags |= VI_MODE;
9166         else
9167                 line_input_state->flags &= ~VI_MODE;
9168 #else
9169         viflag = 0; /* forcibly keep the option off */
9170 #endif
9171 }
9172
9173 struct localvar_list {
9174         struct localvar_list *next;
9175         struct localvar *lv;
9176 };
9177
9178 static struct localvar_list *localvar_stack;
9179
9180 /*
9181  * Called after a function returns.
9182  * Interrupts must be off.
9183  */
9184 static void
9185 poplocalvars(int keep)
9186 {
9187         struct localvar_list *ll;
9188         struct localvar *lvp, *next;
9189         struct var *vp;
9190
9191         INT_OFF;
9192         ll = localvar_stack;
9193         localvar_stack = ll->next;
9194
9195         next = ll->lv;
9196         free(ll);
9197
9198         while ((lvp = next) != NULL) {
9199                 next = lvp->next;
9200                 vp = lvp->vp;
9201                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9202                 if (keep) {
9203                         int bits = VSTRFIXED;
9204
9205                         if (lvp->flags != VUNSET) {
9206                                 if (vp->var_text == lvp->text)
9207                                         bits |= VTEXTFIXED;
9208                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9209                                         free((char*)lvp->text);
9210                         }
9211
9212                         vp->flags &= ~bits;
9213                         vp->flags |= (lvp->flags & bits);
9214
9215                         if ((vp->flags &
9216                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9217                                 unsetvar(vp->var_text);
9218                 } else if (vp == NULL) {        /* $- saved */
9219                         memcpy(optlist, lvp->text, sizeof(optlist));
9220                         free((char*)lvp->text);
9221                         optschanged();
9222                 } else if (lvp->flags == VUNSET) {
9223                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9224                         unsetvar(vp->var_text);
9225                 } else {
9226                         if (vp->var_func)
9227                                 vp->var_func(var_end(lvp->text));
9228                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9229                                 free((char*)vp->var_text);
9230                         vp->flags = lvp->flags;
9231                         vp->var_text = lvp->text;
9232                 }
9233                 free(lvp);
9234         }
9235         INT_ON;
9236 }
9237
9238 /*
9239  * Create a new localvar environment.
9240  */
9241 static struct localvar_list *
9242 pushlocalvars(void)
9243 {
9244         struct localvar_list *ll;
9245
9246         INT_OFF;
9247         ll = ckzalloc(sizeof(*ll));
9248         /*ll->lv = NULL; - zalloc did it */
9249         ll->next = localvar_stack;
9250         localvar_stack = ll;
9251         INT_ON;
9252
9253         return ll->next;
9254 }
9255
9256 static void
9257 unwindlocalvars(struct localvar_list *stop)
9258 {
9259         while (localvar_stack != stop)
9260                 poplocalvars(0);
9261 }
9262
9263 static int
9264 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9265 {
9266         volatile struct shparam saveparam;
9267         struct jmploc *volatile savehandler;
9268         struct jmploc jmploc;
9269         int e;
9270
9271         saveparam = shellparam;
9272         savehandler = exception_handler;
9273         e = setjmp(jmploc.loc);
9274         if (e) {
9275                 goto funcdone;
9276         }
9277         INT_OFF;
9278         exception_handler = &jmploc;
9279         shellparam.malloced = 0;
9280         func->count++;
9281         funcnest++;
9282         INT_ON;
9283         shellparam.nparam = argc - 1;
9284         shellparam.p = argv + 1;
9285 #if ENABLE_ASH_GETOPTS
9286         shellparam.optind = 1;
9287         shellparam.optoff = -1;
9288 #endif
9289         pushlocalvars();
9290         evaltree(func->n.narg.next, flags & EV_TESTED);
9291         poplocalvars(0);
9292  funcdone:
9293         INT_OFF;
9294         funcnest--;
9295         freefunc(func);
9296         freeparam(&shellparam);
9297         shellparam = saveparam;
9298         exception_handler = savehandler;
9299         INT_ON;
9300         evalskip &= ~SKIPFUNC;
9301         return e;
9302 }
9303
9304 /*
9305  * Make a variable a local variable.  When a variable is made local, it's
9306  * value and flags are saved in a localvar structure.  The saved values
9307  * will be restored when the shell function returns.  We handle the name
9308  * "-" as a special case: it makes changes to "set +-options" local
9309  * (options will be restored on return from the function).
9310  */
9311 static void
9312 mklocal(char *name)
9313 {
9314         struct localvar *lvp;
9315         struct var **vpp;
9316         struct var *vp;
9317         char *eq = strchr(name, '=');
9318
9319         INT_OFF;
9320         /* Cater for duplicate "local". Examples:
9321          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9322          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9323          */
9324         lvp = localvar_stack->lv;
9325         while (lvp) {
9326                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9327                         if (eq)
9328                                 setvareq(name, 0);
9329                         /* else:
9330                          * it's a duplicate "local VAR" declaration, do nothing
9331                          */
9332                         goto ret;
9333                 }
9334                 lvp = lvp->next;
9335         }
9336
9337         lvp = ckzalloc(sizeof(*lvp));
9338         if (LONE_DASH(name)) {
9339                 char *p;
9340                 p = ckmalloc(sizeof(optlist));
9341                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9342                 vp = NULL;
9343         } else {
9344                 vpp = hashvar(name);
9345                 vp = *findvar(vpp, name);
9346                 if (vp == NULL) {
9347                         /* variable did not exist yet */
9348                         if (eq)
9349                                 vp = setvareq(name, VSTRFIXED);
9350                         else
9351                                 vp = setvar(name, NULL, VSTRFIXED);
9352                         lvp->flags = VUNSET;
9353                 } else {
9354                         lvp->text = vp->var_text;
9355                         lvp->flags = vp->flags;
9356                         /* make sure neither "struct var" nor string gets freed
9357                          * during (un)setting:
9358                          */
9359                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9360                         if (eq)
9361                                 setvareq(name, 0);
9362                         else
9363                                 /* "local VAR" unsets VAR: */
9364                                 setvar0(name, NULL);
9365                 }
9366         }
9367         lvp->vp = vp;
9368         lvp->next = localvar_stack->lv;
9369         localvar_stack->lv = lvp;
9370  ret:
9371         INT_ON;
9372 }
9373
9374 /*
9375  * The "local" command.
9376  */
9377 static int FAST_FUNC
9378 localcmd(int argc UNUSED_PARAM, char **argv)
9379 {
9380         char *name;
9381
9382         if (!localvar_stack)
9383                 ash_msg_and_raise_error("not in a function");
9384
9385         argv = argptr;
9386         while ((name = *argv++) != NULL) {
9387                 mklocal(name);
9388         }
9389         return 0;
9390 }
9391
9392 static int FAST_FUNC
9393 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9394 {
9395         return 1;
9396 }
9397
9398 static int FAST_FUNC
9399 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9400 {
9401         return 0;
9402 }
9403
9404 static int FAST_FUNC
9405 execcmd(int argc UNUSED_PARAM, char **argv)
9406 {
9407         optionarg = NULL;
9408         while (nextopt("a:") != '\0')
9409                 /* nextopt() sets optionarg to "-a ARGV0" */;
9410
9411         argv = argptr;
9412         if (argv[0]) {
9413                 char *prog;
9414
9415                 iflag = 0;              /* exit on error */
9416                 mflag = 0;
9417                 optschanged();
9418                 /* We should set up signals for "exec CMD"
9419                  * the same way as for "CMD" without "exec".
9420                  * But optschanged->setinteractive->setsignal
9421                  * still thought we are a root shell. Therefore, for example,
9422                  * SIGQUIT is still set to IGN. Fix it:
9423                  */
9424                 shlvl++;
9425                 setsignal(SIGQUIT);
9426                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9427                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9428                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9429
9430                 prog = argv[0];
9431                 if (optionarg)
9432                         argv[0] = optionarg;
9433                 shellexec(prog, argv, pathval(), 0);
9434                 /* NOTREACHED */
9435         }
9436         return 0;
9437 }
9438
9439 /*
9440  * The return command.
9441  */
9442 static int FAST_FUNC
9443 returncmd(int argc UNUSED_PARAM, char **argv)
9444 {
9445         /*
9446          * If called outside a function, do what ksh does;
9447          * skip the rest of the file.
9448          */
9449         evalskip = SKIPFUNC;
9450         return argv[1] ? number(argv[1]) : exitstatus;
9451 }
9452
9453 /* Forward declarations for builtintab[] */
9454 static int breakcmd(int, char **) FAST_FUNC;
9455 static int dotcmd(int, char **) FAST_FUNC;
9456 static int evalcmd(int, char **, int) FAST_FUNC;
9457 static int exitcmd(int, char **) FAST_FUNC;
9458 static int exportcmd(int, char **) FAST_FUNC;
9459 #if ENABLE_ASH_GETOPTS
9460 static int getoptscmd(int, char **) FAST_FUNC;
9461 #endif
9462 #if ENABLE_ASH_HELP
9463 static int helpcmd(int, char **) FAST_FUNC;
9464 #endif
9465 #if MAX_HISTORY
9466 static int historycmd(int, char **) FAST_FUNC;
9467 #endif
9468 #if ENABLE_FEATURE_SH_MATH
9469 static int letcmd(int, char **) FAST_FUNC;
9470 #endif
9471 static int readcmd(int, char **) FAST_FUNC;
9472 static int setcmd(int, char **) FAST_FUNC;
9473 static int shiftcmd(int, char **) FAST_FUNC;
9474 static int timescmd(int, char **) FAST_FUNC;
9475 static int trapcmd(int, char **) FAST_FUNC;
9476 static int umaskcmd(int, char **) FAST_FUNC;
9477 static int unsetcmd(int, char **) FAST_FUNC;
9478 static int ulimitcmd(int, char **) FAST_FUNC;
9479
9480 #define BUILTIN_NOSPEC          "0"
9481 #define BUILTIN_SPECIAL         "1"
9482 #define BUILTIN_REGULAR         "2"
9483 #define BUILTIN_SPEC_REG        "3"
9484 #define BUILTIN_ASSIGN          "4"
9485 #define BUILTIN_SPEC_ASSG       "5"
9486 #define BUILTIN_REG_ASSG        "6"
9487 #define BUILTIN_SPEC_REG_ASSG   "7"
9488
9489 /* Stubs for calling non-FAST_FUNC's */
9490 #if ENABLE_ASH_ECHO
9491 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9492 #endif
9493 #if ENABLE_ASH_PRINTF
9494 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9495 #endif
9496 #if ENABLE_ASH_TEST || BASH_TEST2
9497 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9498 #endif
9499
9500 /* Keep these in proper order since it is searched via bsearch() */
9501 static const struct builtincmd builtintab[] = {
9502         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9503         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9504 #if ENABLE_ASH_TEST
9505         { BUILTIN_REGULAR       "["       , testcmd    },
9506 #endif
9507 #if BASH_TEST2
9508         { BUILTIN_REGULAR       "[["      , testcmd    },
9509 #endif
9510 #if ENABLE_ASH_ALIAS
9511         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9512 #endif
9513 #if JOBS
9514         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9515 #endif
9516         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9517         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9518         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9519 #if ENABLE_ASH_CMDCMD
9520         { BUILTIN_REGULAR       "command" , commandcmd },
9521 #endif
9522         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9523 #if ENABLE_ASH_ECHO
9524         { BUILTIN_REGULAR       "echo"    , echocmd    },
9525 #endif
9526         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9527         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9528         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9529         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9530         { BUILTIN_REGULAR       "false"   , falsecmd   },
9531 #if JOBS
9532         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9533 #endif
9534 #if ENABLE_ASH_GETOPTS
9535         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9536 #endif
9537         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9538 #if ENABLE_ASH_HELP
9539         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9540 #endif
9541 #if MAX_HISTORY
9542         { BUILTIN_NOSPEC        "history" , historycmd },
9543 #endif
9544 #if JOBS
9545         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9546         { BUILTIN_REGULAR       "kill"    , killcmd    },
9547 #endif
9548 #if ENABLE_FEATURE_SH_MATH
9549         { BUILTIN_NOSPEC        "let"     , letcmd     },
9550 #endif
9551         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9552 #if ENABLE_ASH_PRINTF
9553         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9554 #endif
9555         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9556         { BUILTIN_REGULAR       "read"    , readcmd    },
9557         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9558         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9559         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9560         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9561 #if BASH_SOURCE
9562         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9563 #endif
9564 #if ENABLE_ASH_TEST
9565         { BUILTIN_REGULAR       "test"    , testcmd    },
9566 #endif
9567         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9568         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9569         { BUILTIN_REGULAR       "true"    , truecmd    },
9570         { BUILTIN_NOSPEC        "type"    , typecmd    },
9571         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9572         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9573 #if ENABLE_ASH_ALIAS
9574         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9575 #endif
9576         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9577         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9578 };
9579
9580 /* Should match the above table! */
9581 #define COMMANDCMD (builtintab + \
9582         /* . : */       2 + \
9583         /* [ */         1 * ENABLE_ASH_TEST + \
9584         /* [[ */        1 * BASH_TEST2 + \
9585         /* alias */     1 * ENABLE_ASH_ALIAS + \
9586         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9587         /* break cd cddir  */   3)
9588 #define EVALCMD (COMMANDCMD + \
9589         /* command */   1 * ENABLE_ASH_CMDCMD + \
9590         /* continue */  1 + \
9591         /* echo */      1 * ENABLE_ASH_ECHO + \
9592         0)
9593 #define EXECCMD (EVALCMD + \
9594         /* eval */      1)
9595
9596 /*
9597  * Search the table of builtin commands.
9598  */
9599 static int
9600 pstrcmp1(const void *a, const void *b)
9601 {
9602         return strcmp((char*)a, *(char**)b + 1);
9603 }
9604 static struct builtincmd *
9605 find_builtin(const char *name)
9606 {
9607         struct builtincmd *bp;
9608
9609         bp = bsearch(
9610                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9611                 pstrcmp1
9612         );
9613         return bp;
9614 }
9615
9616 /*
9617  * Execute a simple command.
9618  */
9619 static int
9620 isassignment(const char *p)
9621 {
9622         const char *q = endofname(p);
9623         if (p == q)
9624                 return 0;
9625         return *q == '=';
9626 }
9627 static int FAST_FUNC
9628 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9629 {
9630         /* Preserve exitstatus of a previous possible redirection
9631          * as POSIX mandates */
9632         return back_exitstatus;
9633 }
9634 static int
9635 evalcommand(union node *cmd, int flags)
9636 {
9637         static const struct builtincmd null_bltin = {
9638                 "\0\0", bltincmd /* why three NULs? */
9639         };
9640         struct localvar_list *localvar_stop;
9641         struct redirtab *redir_stop;
9642         struct stackmark smark;
9643         union node *argp;
9644         struct arglist arglist;
9645         struct arglist varlist;
9646         char **argv;
9647         int argc;
9648         const struct strlist *sp;
9649         struct cmdentry cmdentry;
9650         struct job *jp;
9651         char *lastarg;
9652         const char *path;
9653         int spclbltin;
9654         int status;
9655         char **nargv;
9656         struct builtincmd *bcmd;
9657         smallint cmd_is_exec;
9658         smallint pseudovarflag = 0;
9659
9660         /* First expand the arguments. */
9661         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9662         setstackmark(&smark);
9663         localvar_stop = pushlocalvars();
9664         back_exitstatus = 0;
9665
9666         cmdentry.cmdtype = CMDBUILTIN;
9667         cmdentry.u.cmd = &null_bltin;
9668         varlist.lastp = &varlist.list;
9669         *varlist.lastp = NULL;
9670         arglist.lastp = &arglist.list;
9671         *arglist.lastp = NULL;
9672
9673         argc = 0;
9674         if (cmd->ncmd.args) {
9675                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9676                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9677         }
9678
9679         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9680                 struct strlist **spp;
9681
9682                 spp = arglist.lastp;
9683                 if (pseudovarflag && isassignment(argp->narg.text))
9684                         expandarg(argp, &arglist, EXP_VARTILDE);
9685                 else
9686                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9687
9688                 for (sp = *spp; sp; sp = sp->next)
9689                         argc++;
9690         }
9691
9692         /* Reserve one extra spot at the front for shellexec. */
9693         nargv = stalloc(sizeof(char *) * (argc + 2));
9694         argv = ++nargv;
9695         for (sp = arglist.list; sp; sp = sp->next) {
9696                 TRACE(("evalcommand arg: %s\n", sp->text));
9697                 *nargv++ = sp->text;
9698         }
9699         *nargv = NULL;
9700
9701         lastarg = NULL;
9702         if (iflag && funcnest == 0 && argc > 0)
9703                 lastarg = nargv[-1];
9704
9705         preverrout_fd = 2;
9706         expredir(cmd->ncmd.redirect);
9707         redir_stop = pushredir(cmd->ncmd.redirect);
9708         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9709
9710         path = vpath.var_text;
9711         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9712                 struct strlist **spp;
9713                 char *p;
9714
9715                 spp = varlist.lastp;
9716                 expandarg(argp, &varlist, EXP_VARTILDE);
9717
9718                 mklocal((*spp)->text);
9719
9720                 /*
9721                  * Modify the command lookup path, if a PATH= assignment
9722                  * is present
9723                  */
9724                 p = (*spp)->text;
9725                 if (varcmp(p, path) == 0)
9726                         path = p;
9727         }
9728
9729         /* Print the command if xflag is set. */
9730         if (xflag) {
9731                 const char *pfx = "";
9732
9733                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9734
9735                 sp = varlist.list;
9736                 while (sp) {
9737                         char *varval = sp->text;
9738                         char *eq = strchrnul(varval, '=');
9739                         if (*eq)
9740                                 eq++;
9741                         fdprintf(preverrout_fd, "%s%.*s%s",
9742                                 pfx,
9743                                 (int)(eq - varval), varval,
9744                                 maybe_single_quote(eq)
9745                         );
9746                         sp = sp->next;
9747                         pfx = " ";
9748                 }
9749
9750                 sp = arglist.list;
9751                 while (sp) {
9752                         fdprintf(preverrout_fd, "%s%s",
9753                                 pfx,
9754                                 /* always quote if matches reserved word: */
9755                                 findkwd(sp->text)
9756                                 ? single_quote(sp->text)
9757                                 : maybe_single_quote(sp->text)
9758                         );
9759                         sp = sp->next;
9760                         pfx = " ";
9761                 }
9762                 safe_write(preverrout_fd, "\n", 1);
9763         }
9764
9765         cmd_is_exec = 0;
9766         spclbltin = -1;
9767
9768         /* Now locate the command. */
9769         if (argc) {
9770                 int cmd_flag = DO_ERR;
9771 #if ENABLE_ASH_CMDCMD
9772                 const char *oldpath = path + 5;
9773 #endif
9774                 path += 5;
9775                 for (;;) {
9776                         find_command(argv[0], &cmdentry, cmd_flag, path);
9777                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9778                                 flush_stdout_stderr();
9779                                 status = 127;
9780                                 goto bail;
9781                         }
9782
9783                         /* implement bltin and command here */
9784                         if (cmdentry.cmdtype != CMDBUILTIN)
9785                                 break;
9786                         if (spclbltin < 0)
9787                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9788                         if (cmdentry.u.cmd == EXECCMD)
9789                                 cmd_is_exec = 1;
9790 #if ENABLE_ASH_CMDCMD
9791                         if (cmdentry.u.cmd == COMMANDCMD) {
9792                                 path = oldpath;
9793                                 nargv = parse_command_args(argv, &path);
9794                                 if (!nargv)
9795                                         break;
9796                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9797                                  * nargv => "PROG". path is updated if -p.
9798                                  */
9799                                 argc -= nargv - argv;
9800                                 argv = nargv;
9801                                 cmd_flag |= DO_NOFUNC;
9802                         } else
9803 #endif
9804                                 break;
9805                 }
9806         }
9807
9808         if (status) {
9809  bail:
9810                 exitstatus = status;
9811
9812                 /* We have a redirection error. */
9813                 if (spclbltin > 0)
9814                         raise_exception(EXERROR);
9815
9816                 goto out;
9817         }
9818
9819         /* Execute the command. */
9820         switch (cmdentry.cmdtype) {
9821         default: {
9822
9823 #if ENABLE_FEATURE_SH_NOFORK
9824 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9825  *     around run_nofork_applet() call.
9826  * (2) Should this check also be done in forkshell()?
9827  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9828  */
9829                 /* find_command() encodes applet_no as (-2 - applet_no) */
9830                 int applet_no = (- cmdentry.u.index - 2);
9831                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9832                         listsetvar(varlist.list, VEXPORT|VSTACK);
9833                         /* run <applet>_main() */
9834                         status = run_nofork_applet(applet_no, argv);
9835                         break;
9836                 }
9837 #endif
9838                 /* Can we avoid forking off? For example, very last command
9839                  * in a script or a subshell does not need forking,
9840                  * we can just exec it.
9841                  */
9842                 if (!(flags & EV_EXIT) || may_have_traps) {
9843                         /* No, forking off a child is necessary */
9844                         INT_OFF;
9845                         get_tty_state();
9846                         jp = makejob(/*cmd,*/ 1);
9847                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9848                                 /* parent */
9849                                 status = waitforjob(jp);
9850                                 INT_ON;
9851                                 TRACE(("forked child exited with %d\n", status));
9852                                 break;
9853                         }
9854                         /* child */
9855                         FORCE_INT_ON;
9856                         /* fall through to exec'ing external program */
9857                 }
9858                 listsetvar(varlist.list, VEXPORT|VSTACK);
9859                 shellexec(argv[0], argv, path, cmdentry.u.index);
9860                 /* NOTREACHED */
9861         } /* default */
9862         case CMDBUILTIN:
9863                 if (spclbltin > 0 || argc == 0) {
9864                         poplocalvars(1);
9865                         if (cmd_is_exec && argc > 1)
9866                                 listsetvar(varlist.list, VEXPORT);
9867                 }
9868
9869                 /* Tight loop with builtins only:
9870                  * "while kill -0 $child; do true; done"
9871                  * will never exit even if $child died, unless we do this
9872                  * to reap the zombie and make kill detect that it's gone: */
9873                 dowait(DOWAIT_NONBLOCK, NULL);
9874
9875                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9876                         if (exception_type == EXERROR && spclbltin <= 0) {
9877                                 FORCE_INT_ON;
9878                                 goto readstatus;
9879                         }
9880  raise:
9881                         longjmp(exception_handler->loc, 1);
9882                 }
9883                 goto readstatus;
9884
9885         case CMDFUNCTION:
9886                 poplocalvars(1);
9887                 /* See above for the rationale */
9888                 dowait(DOWAIT_NONBLOCK, NULL);
9889                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9890                         goto raise;
9891  readstatus:
9892                 status = exitstatus;
9893                 break;
9894         } /* switch */
9895
9896  out:
9897         if (cmd->ncmd.redirect)
9898                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9899         unwindredir(redir_stop);
9900         unwindlocalvars(localvar_stop);
9901         if (lastarg) {
9902                 /* dsl: I think this is intended to be used to support
9903                  * '_' in 'vi' command mode during line editing...
9904                  * However I implemented that within libedit itself.
9905                  */
9906                 setvar0("_", lastarg);
9907         }
9908         popstackmark(&smark);
9909
9910         return status;
9911 }
9912
9913 static int
9914 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9915 {
9916         char *volatile savecmdname;
9917         struct jmploc *volatile savehandler;
9918         struct jmploc jmploc;
9919         int status;
9920         int i;
9921
9922         savecmdname = commandname;
9923         savehandler = exception_handler;
9924         i = setjmp(jmploc.loc);
9925         if (i)
9926                 goto cmddone;
9927         exception_handler = &jmploc;
9928         commandname = argv[0];
9929         argptr = argv + 1;
9930         optptr = NULL;                  /* initialize nextopt */
9931         if (cmd == EVALCMD)
9932                 status = evalcmd(argc, argv, flags);
9933         else
9934                 status = (*cmd->builtin)(argc, argv);
9935         flush_stdout_stderr();
9936         status |= ferror(stdout);
9937         exitstatus = status;
9938  cmddone:
9939         clearerr(stdout);
9940         commandname = savecmdname;
9941         exception_handler = savehandler;
9942
9943         return i;
9944 }
9945
9946 static int
9947 goodname(const char *p)
9948 {
9949         return endofname(p)[0] == '\0';
9950 }
9951
9952
9953 /*
9954  * Search for a command.  This is called before we fork so that the
9955  * location of the command will be available in the parent as well as
9956  * the child.  The check for "goodname" is an overly conservative
9957  * check that the name will not be subject to expansion.
9958  */
9959 static void
9960 prehash(union node *n)
9961 {
9962         struct cmdentry entry;
9963
9964         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9965                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9966 }
9967
9968
9969 /* ============ Builtin commands
9970  *
9971  * Builtin commands whose functions are closely tied to evaluation
9972  * are implemented here.
9973  */
9974
9975 /*
9976  * Handle break and continue commands.  Break, continue, and return are
9977  * all handled by setting the evalskip flag.  The evaluation routines
9978  * above all check this flag, and if it is set they start skipping
9979  * commands rather than executing them.  The variable skipcount is
9980  * the number of loops to break/continue, or the number of function
9981  * levels to return.  (The latter is always 1.)  It should probably
9982  * be an error to break out of more loops than exist, but it isn't
9983  * in the standard shell so we don't make it one here.
9984  */
9985 static int FAST_FUNC
9986 breakcmd(int argc UNUSED_PARAM, char **argv)
9987 {
9988         int n = argv[1] ? number(argv[1]) : 1;
9989
9990         if (n <= 0)
9991                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9992         if (n > loopnest)
9993                 n = loopnest;
9994         if (n > 0) {
9995                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9996                 skipcount = n;
9997         }
9998         return 0;
9999 }
10000
10001
10002 /*
10003  * This implements the input routines used by the parser.
10004  */
10005
10006 enum {
10007         INPUT_PUSH_FILE = 1,
10008         INPUT_NOFILE_OK = 2,
10009 };
10010
10011 static smallint checkkwd;
10012 /* values of checkkwd variable */
10013 #define CHKALIAS        0x1
10014 #define CHKKWD          0x2
10015 #define CHKNL           0x4
10016 #define CHKEOFMARK      0x8
10017
10018 /*
10019  * Push a string back onto the input at this current parsefile level.
10020  * We handle aliases this way.
10021  */
10022 #if !ENABLE_ASH_ALIAS
10023 #define pushstring(s, ap) pushstring(s)
10024 #endif
10025 static void
10026 pushstring(char *s, struct alias *ap)
10027 {
10028         struct strpush *sp;
10029         int len;
10030
10031         len = strlen(s);
10032         INT_OFF;
10033         if (g_parsefile->strpush) {
10034                 sp = ckzalloc(sizeof(*sp));
10035                 sp->prev = g_parsefile->strpush;
10036         } else {
10037                 sp = &(g_parsefile->basestrpush);
10038         }
10039         g_parsefile->strpush = sp;
10040         sp->prev_string = g_parsefile->next_to_pgetc;
10041         sp->prev_left_in_line = g_parsefile->left_in_line;
10042         sp->unget = g_parsefile->unget;
10043         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10044 #if ENABLE_ASH_ALIAS
10045         sp->ap = ap;
10046         if (ap) {
10047                 ap->flag |= ALIASINUSE;
10048                 sp->string = s;
10049         }
10050 #endif
10051         g_parsefile->next_to_pgetc = s;
10052         g_parsefile->left_in_line = len;
10053         g_parsefile->unget = 0;
10054         INT_ON;
10055 }
10056
10057 static void
10058 popstring(void)
10059 {
10060         struct strpush *sp = g_parsefile->strpush;
10061
10062         INT_OFF;
10063 #if ENABLE_ASH_ALIAS
10064         if (sp->ap) {
10065                 if (g_parsefile->next_to_pgetc[-1] == ' '
10066                  || g_parsefile->next_to_pgetc[-1] == '\t'
10067                 ) {
10068                         checkkwd |= CHKALIAS;
10069                 }
10070                 if (sp->string != sp->ap->val) {
10071                         free(sp->string);
10072                 }
10073                 sp->ap->flag &= ~ALIASINUSE;
10074                 if (sp->ap->flag & ALIASDEAD) {
10075                         unalias(sp->ap->name);
10076                 }
10077         }
10078 #endif
10079         g_parsefile->next_to_pgetc = sp->prev_string;
10080         g_parsefile->left_in_line = sp->prev_left_in_line;
10081         g_parsefile->unget = sp->unget;
10082         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10083         g_parsefile->strpush = sp->prev;
10084         if (sp != &(g_parsefile->basestrpush))
10085                 free(sp);
10086         INT_ON;
10087 }
10088
10089 static int
10090 preadfd(void)
10091 {
10092         int nr;
10093         char *buf = g_parsefile->buf;
10094
10095         g_parsefile->next_to_pgetc = buf;
10096 #if ENABLE_FEATURE_EDITING
10097  retry:
10098         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10099                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10100         else {
10101                 int timeout = -1;
10102 # if ENABLE_ASH_IDLE_TIMEOUT
10103                 if (iflag) {
10104                         const char *tmout_var = lookupvar("TMOUT");
10105                         if (tmout_var) {
10106                                 timeout = atoi(tmout_var) * 1000;
10107                                 if (timeout <= 0)
10108                                         timeout = -1;
10109                         }
10110                 }
10111 # endif
10112 # if ENABLE_FEATURE_TAB_COMPLETION
10113                 line_input_state->path_lookup = pathval();
10114 # endif
10115                 reinit_unicode_for_ash();
10116                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10117                 if (nr == 0) {
10118                         /* ^C pressed, "convert" to SIGINT */
10119                         write(STDOUT_FILENO, "^C", 2);
10120                         if (trap[SIGINT]) {
10121                                 buf[0] = '\n';
10122                                 buf[1] = '\0';
10123                                 raise(SIGINT);
10124                                 return 1;
10125                         }
10126                         exitstatus = 128 + SIGINT;
10127                         bb_putchar('\n');
10128                         goto retry;
10129                 }
10130                 if (nr < 0) {
10131                         if (errno == 0) {
10132                                 /* Ctrl+D pressed */
10133                                 nr = 0;
10134                         }
10135 # if ENABLE_ASH_IDLE_TIMEOUT
10136                         else if (errno == EAGAIN && timeout > 0) {
10137                                 puts("\007timed out waiting for input: auto-logout");
10138                                 exitshell();
10139                         }
10140 # endif
10141                 }
10142         }
10143 #else
10144         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10145 #endif
10146
10147 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10148         if (nr < 0) {
10149                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10150                         int flags = fcntl(0, F_GETFL);
10151                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10152                                 flags &= ~O_NONBLOCK;
10153                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10154                                         out2str("sh: turning off NDELAY mode\n");
10155                                         goto retry;
10156                                 }
10157                         }
10158                 }
10159         }
10160 #endif
10161         return nr;
10162 }
10163
10164 /*
10165  * Refill the input buffer and return the next input character:
10166  *
10167  * 1) If a string was pushed back on the input, pop it;
10168  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10169  *    or we are reading from a string so we can't refill the buffer,
10170  *    return EOF.
10171  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10172  * 4) Process input up to the next newline, deleting nul characters.
10173  */
10174 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10175 #define pgetc_debug(...) ((void)0)
10176 static int pgetc(void);
10177 static int
10178 preadbuffer(void)
10179 {
10180         char *q;
10181         int more;
10182
10183         if (g_parsefile->strpush) {
10184 #if ENABLE_ASH_ALIAS
10185                 if (g_parsefile->left_in_line == -1
10186                  && g_parsefile->strpush->ap
10187                  && g_parsefile->next_to_pgetc[-1] != ' '
10188                  && g_parsefile->next_to_pgetc[-1] != '\t'
10189                 ) {
10190                         pgetc_debug("preadbuffer PEOA");
10191                         return PEOA;
10192                 }
10193 #endif
10194                 popstring();
10195                 return pgetc();
10196         }
10197         /* on both branches above g_parsefile->left_in_line < 0.
10198          * "pgetc" needs refilling.
10199          */
10200
10201         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10202          * pungetc() may increment it a few times.
10203          * Assuming it won't increment it to less than -90.
10204          */
10205         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10206                 pgetc_debug("preadbuffer PEOF1");
10207                 /* even in failure keep left_in_line and next_to_pgetc
10208                  * in lock step, for correct multi-layer pungetc.
10209                  * left_in_line was decremented before preadbuffer(),
10210                  * must inc next_to_pgetc: */
10211                 g_parsefile->next_to_pgetc++;
10212                 return PEOF;
10213         }
10214
10215         more = g_parsefile->left_in_buffer;
10216         if (more <= 0) {
10217                 flush_stdout_stderr();
10218  again:
10219                 more = preadfd();
10220                 if (more <= 0) {
10221                         /* don't try reading again */
10222                         g_parsefile->left_in_line = -99;
10223                         pgetc_debug("preadbuffer PEOF2");
10224                         g_parsefile->next_to_pgetc++;
10225                         return PEOF;
10226                 }
10227         }
10228
10229         /* Find out where's the end of line.
10230          * Set g_parsefile->left_in_line
10231          * and g_parsefile->left_in_buffer acordingly.
10232          * NUL chars are deleted.
10233          */
10234         q = g_parsefile->next_to_pgetc;
10235         for (;;) {
10236                 char c;
10237
10238                 more--;
10239
10240                 c = *q;
10241                 if (c == '\0') {
10242                         memmove(q, q + 1, more);
10243                 } else {
10244                         q++;
10245                         if (c == '\n') {
10246                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10247                                 break;
10248                         }
10249                 }
10250
10251                 if (more <= 0) {
10252                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10253                         if (g_parsefile->left_in_line < 0)
10254                                 goto again;
10255                         break;
10256                 }
10257         }
10258         g_parsefile->left_in_buffer = more;
10259
10260         if (vflag) {
10261                 char save = *q;
10262                 *q = '\0';
10263                 out2str(g_parsefile->next_to_pgetc);
10264                 *q = save;
10265         }
10266
10267         pgetc_debug("preadbuffer at %d:%p'%s'",
10268                         g_parsefile->left_in_line,
10269                         g_parsefile->next_to_pgetc,
10270                         g_parsefile->next_to_pgetc);
10271         return (unsigned char)*g_parsefile->next_to_pgetc++;
10272 }
10273
10274 static void
10275 nlprompt(void)
10276 {
10277         g_parsefile->linno++;
10278         setprompt_if(doprompt, 2);
10279 }
10280 static void
10281 nlnoprompt(void)
10282 {
10283         g_parsefile->linno++;
10284         needprompt = doprompt;
10285 }
10286
10287 static int
10288 pgetc(void)
10289 {
10290         int c;
10291
10292         pgetc_debug("pgetc at %d:%p'%s'",
10293                         g_parsefile->left_in_line,
10294                         g_parsefile->next_to_pgetc,
10295                         g_parsefile->next_to_pgetc);
10296         if (g_parsefile->unget)
10297                 return g_parsefile->lastc[--g_parsefile->unget];
10298
10299         if (--g_parsefile->left_in_line >= 0)
10300                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10301         else
10302                 c = preadbuffer();
10303
10304         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10305         g_parsefile->lastc[0] = c;
10306
10307         return c;
10308 }
10309
10310 #if ENABLE_ASH_ALIAS
10311 static int
10312 pgetc_without_PEOA(void)
10313 {
10314         int c;
10315         do {
10316                 pgetc_debug("pgetc at %d:%p'%s'",
10317                                 g_parsefile->left_in_line,
10318                                 g_parsefile->next_to_pgetc,
10319                                 g_parsefile->next_to_pgetc);
10320                 c = pgetc();
10321         } while (c == PEOA);
10322         return c;
10323 }
10324 #else
10325 # define pgetc_without_PEOA() pgetc()
10326 #endif
10327
10328 /*
10329  * Undo a call to pgetc.  Only two characters may be pushed back.
10330  * PEOF may be pushed back.
10331  */
10332 static void
10333 pungetc(void)
10334 {
10335         g_parsefile->unget++;
10336 }
10337
10338 /* This one eats backslash+newline */
10339 static int
10340 pgetc_eatbnl(void)
10341 {
10342         int c;
10343
10344         while ((c = pgetc()) == '\\') {
10345                 if (pgetc() != '\n') {
10346                         pungetc();
10347                         break;
10348                 }
10349
10350                 nlprompt();
10351         }
10352
10353         return c;
10354 }
10355
10356 /*
10357  * To handle the "." command, a stack of input files is used.  Pushfile
10358  * adds a new entry to the stack and popfile restores the previous level.
10359  */
10360 static void
10361 pushfile(void)
10362 {
10363         struct parsefile *pf;
10364
10365         pf = ckzalloc(sizeof(*pf));
10366         pf->prev = g_parsefile;
10367         pf->pf_fd = -1;
10368         /*pf->strpush = NULL; - ckzalloc did it */
10369         /*pf->basestrpush.prev = NULL;*/
10370         /*pf->unget = 0;*/
10371         g_parsefile = pf;
10372 }
10373
10374 static void
10375 popfile(void)
10376 {
10377         struct parsefile *pf = g_parsefile;
10378
10379         if (pf == &basepf)
10380                 return;
10381
10382         INT_OFF;
10383         if (pf->pf_fd >= 0)
10384                 close(pf->pf_fd);
10385         free(pf->buf);
10386         while (pf->strpush)
10387                 popstring();
10388         g_parsefile = pf->prev;
10389         free(pf);
10390         INT_ON;
10391 }
10392
10393 /*
10394  * Return to top level.
10395  */
10396 static void
10397 popallfiles(void)
10398 {
10399         while (g_parsefile != &basepf)
10400                 popfile();
10401 }
10402
10403 /*
10404  * Close the file(s) that the shell is reading commands from.  Called
10405  * after a fork is done.
10406  */
10407 static void
10408 closescript(void)
10409 {
10410         popallfiles();
10411         if (g_parsefile->pf_fd > 0) {
10412                 close(g_parsefile->pf_fd);
10413                 g_parsefile->pf_fd = 0;
10414         }
10415 }
10416
10417 /*
10418  * Like setinputfile, but takes an open file descriptor.  Call this with
10419  * interrupts off.
10420  */
10421 static void
10422 setinputfd(int fd, int push)
10423 {
10424         if (push) {
10425                 pushfile();
10426                 g_parsefile->buf = NULL;
10427         }
10428         g_parsefile->pf_fd = fd;
10429         if (g_parsefile->buf == NULL)
10430                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10431         g_parsefile->left_in_buffer = 0;
10432         g_parsefile->left_in_line = 0;
10433         g_parsefile->linno = 1;
10434 }
10435
10436 /*
10437  * Set the input to take input from a file.  If push is set, push the
10438  * old input onto the stack first.
10439  */
10440 static int
10441 setinputfile(const char *fname, int flags)
10442 {
10443         int fd;
10444
10445         INT_OFF;
10446         fd = open(fname, O_RDONLY);
10447         if (fd < 0) {
10448                 if (flags & INPUT_NOFILE_OK)
10449                         goto out;
10450                 exitstatus = 127;
10451                 ash_msg_and_raise_error("can't open '%s'", fname);
10452         }
10453         if (fd < 10)
10454                 fd = savefd(fd);
10455         else
10456                 close_on_exec_on(fd);
10457         setinputfd(fd, flags & INPUT_PUSH_FILE);
10458  out:
10459         INT_ON;
10460         return fd;
10461 }
10462
10463 /*
10464  * Like setinputfile, but takes input from a string.
10465  */
10466 static void
10467 setinputstring(char *string)
10468 {
10469         INT_OFF;
10470         pushfile();
10471         g_parsefile->next_to_pgetc = string;
10472         g_parsefile->left_in_line = strlen(string);
10473         g_parsefile->buf = NULL;
10474         g_parsefile->linno = 1;
10475         INT_ON;
10476 }
10477
10478
10479 /*
10480  * Routines to check for mail.
10481  */
10482
10483 #if ENABLE_ASH_MAIL
10484
10485 /* Hash of mtimes of mailboxes */
10486 static unsigned mailtime_hash;
10487 /* Set if MAIL or MAILPATH is changed. */
10488 static smallint mail_var_path_changed;
10489
10490 /*
10491  * Print appropriate message(s) if mail has arrived.
10492  * If mail_var_path_changed is set,
10493  * then the value of MAIL has mail_var_path_changed,
10494  * so we just update the values.
10495  */
10496 static void
10497 chkmail(void)
10498 {
10499         const char *mpath;
10500         char *p;
10501         char *q;
10502         unsigned new_hash;
10503         struct stackmark smark;
10504         struct stat statb;
10505
10506         setstackmark(&smark);
10507         mpath = mpathset() ? mpathval() : mailval();
10508         new_hash = 0;
10509         for (;;) {
10510                 p = path_advance(&mpath, nullstr);
10511                 if (p == NULL)
10512                         break;
10513                 if (*p == '\0')
10514                         continue;
10515                 for (q = p; *q; q++)
10516                         continue;
10517 #if DEBUG
10518                 if (q[-1] != '/')
10519                         abort();
10520 #endif
10521                 q[-1] = '\0';                   /* delete trailing '/' */
10522                 if (stat(p, &statb) < 0) {
10523                         continue;
10524                 }
10525                 /* Very simplistic "hash": just a sum of all mtimes */
10526                 new_hash += (unsigned)statb.st_mtime;
10527         }
10528         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10529                 if (mailtime_hash != 0)
10530                         out2str("you have mail\n");
10531                 mailtime_hash = new_hash;
10532         }
10533         mail_var_path_changed = 0;
10534         popstackmark(&smark);
10535 }
10536
10537 static void FAST_FUNC
10538 changemail(const char *val UNUSED_PARAM)
10539 {
10540         mail_var_path_changed = 1;
10541 }
10542
10543 #endif /* ASH_MAIL */
10544
10545
10546 /* ============ ??? */
10547
10548 /*
10549  * Set the shell parameters.
10550  */
10551 static void
10552 setparam(char **argv)
10553 {
10554         char **newparam;
10555         char **ap;
10556         int nparam;
10557
10558         for (nparam = 0; argv[nparam]; nparam++)
10559                 continue;
10560         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10561         while (*argv) {
10562                 *ap++ = ckstrdup(*argv++);
10563         }
10564         *ap = NULL;
10565         freeparam(&shellparam);
10566         shellparam.malloced = 1;
10567         shellparam.nparam = nparam;
10568         shellparam.p = newparam;
10569 #if ENABLE_ASH_GETOPTS
10570         shellparam.optind = 1;
10571         shellparam.optoff = -1;
10572 #endif
10573 }
10574
10575 /*
10576  * Process shell options.  The global variable argptr contains a pointer
10577  * to the argument list; we advance it past the options.
10578  *
10579  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10580  * For a non-interactive shell, an error condition encountered
10581  * by a special built-in ... shall cause the shell to write a diagnostic message
10582  * to standard error and exit as shown in the following table:
10583  * Error                                           Special Built-In
10584  * ...
10585  * Utility syntax error (option or operand error)  Shall exit
10586  * ...
10587  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10588  * we see that bash does not do that (set "finishes" with error code 1 instead,
10589  * and shell continues), and people rely on this behavior!
10590  * Testcase:
10591  * set -o barfoo 2>/dev/null
10592  * echo $?
10593  *
10594  * Oh well. Let's mimic that.
10595  */
10596 static int
10597 plus_minus_o(char *name, int val)
10598 {
10599         int i;
10600
10601         if (name) {
10602                 for (i = 0; i < NOPTS; i++) {
10603                         if (strcmp(name, optnames(i)) == 0) {
10604                                 optlist[i] = val;
10605                                 return 0;
10606                         }
10607                 }
10608                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10609                 return 1;
10610         }
10611         for (i = 0; i < NOPTS; i++) {
10612                 if (val) {
10613                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10614                 } else {
10615                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10616                 }
10617         }
10618         return 0;
10619 }
10620 static void
10621 setoption(int flag, int val)
10622 {
10623         int i;
10624
10625         for (i = 0; i < NOPTS; i++) {
10626                 if (optletters(i) == flag) {
10627                         optlist[i] = val;
10628                         return;
10629                 }
10630         }
10631         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10632         /* NOTREACHED */
10633 }
10634 static int
10635 options(int cmdline)
10636 {
10637         char *p;
10638         int val;
10639         int c;
10640
10641         if (cmdline)
10642                 minusc = NULL;
10643         while ((p = *argptr) != NULL) {
10644                 c = *p++;
10645                 if (c != '-' && c != '+')
10646                         break;
10647                 argptr++;
10648                 val = 0; /* val = 0 if c == '+' */
10649                 if (c == '-') {
10650                         val = 1;
10651                         if (p[0] == '\0' || LONE_DASH(p)) {
10652                                 if (!cmdline) {
10653                                         /* "-" means turn off -x and -v */
10654                                         if (p[0] == '\0')
10655                                                 xflag = vflag = 0;
10656                                         /* "--" means reset params */
10657                                         else if (*argptr == NULL)
10658                                                 setparam(argptr);
10659                                 }
10660                                 break;    /* "-" or "--" terminates options */
10661                         }
10662                 }
10663                 /* first char was + or - */
10664                 while ((c = *p++) != '\0') {
10665                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10666                         if (c == 'c' && cmdline) {
10667                                 minusc = p;     /* command is after shell args */
10668                         } else if (c == 'o') {
10669                                 if (plus_minus_o(*argptr, val)) {
10670                                         /* it already printed err message */
10671                                         return 1; /* error */
10672                                 }
10673                                 if (*argptr)
10674                                         argptr++;
10675                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10676                                 isloginsh = 1;
10677                         /* bash does not accept +-login, we also won't */
10678                         } else if (cmdline && val && (c == '-')) { /* long options */
10679                                 if (strcmp(p, "login") == 0)
10680                                         isloginsh = 1;
10681                                 break;
10682                         } else {
10683                                 setoption(c, val);
10684                         }
10685                 }
10686         }
10687         return 0;
10688 }
10689
10690 /*
10691  * The shift builtin command.
10692  */
10693 static int FAST_FUNC
10694 shiftcmd(int argc UNUSED_PARAM, char **argv)
10695 {
10696         int n;
10697         char **ap1, **ap2;
10698
10699         n = 1;
10700         if (argv[1])
10701                 n = number(argv[1]);
10702         if (n > shellparam.nparam)
10703                 n = 0; /* bash compat, was = shellparam.nparam; */
10704         INT_OFF;
10705         shellparam.nparam -= n;
10706         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10707                 if (shellparam.malloced)
10708                         free(*ap1);
10709         }
10710         ap2 = shellparam.p;
10711         while ((*ap2++ = *ap1++) != NULL)
10712                 continue;
10713 #if ENABLE_ASH_GETOPTS
10714         shellparam.optind = 1;
10715         shellparam.optoff = -1;
10716 #endif
10717         INT_ON;
10718         return 0;
10719 }
10720
10721 /*
10722  * POSIX requires that 'set' (but not export or readonly) output the
10723  * variables in lexicographic order - by the locale's collating order (sigh).
10724  * Maybe we could keep them in an ordered balanced binary tree
10725  * instead of hashed lists.
10726  * For now just roll 'em through qsort for printing...
10727  */
10728 static int
10729 showvars(const char *sep_prefix, int on, int off)
10730 {
10731         const char *sep;
10732         char **ep, **epend;
10733
10734         ep = listvars(on, off, &epend);
10735         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10736
10737         sep = *sep_prefix ? " " : sep_prefix;
10738
10739         for (; ep < epend; ep++) {
10740                 const char *p;
10741                 const char *q;
10742
10743                 p = strchrnul(*ep, '=');
10744                 q = nullstr;
10745                 if (*p)
10746                         q = single_quote(++p);
10747                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10748         }
10749         return 0;
10750 }
10751
10752 /*
10753  * The set command builtin.
10754  */
10755 static int FAST_FUNC
10756 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10757 {
10758         int retval;
10759
10760         if (!argv[1])
10761                 return showvars(nullstr, 0, VUNSET);
10762
10763         INT_OFF;
10764         retval = options(/*cmdline:*/ 0);
10765         if (retval == 0) { /* if no parse error... */
10766                 optschanged();
10767                 if (*argptr != NULL) {
10768                         setparam(argptr);
10769                 }
10770         }
10771         INT_ON;
10772         return retval;
10773 }
10774
10775 #if ENABLE_ASH_RANDOM_SUPPORT
10776 static void FAST_FUNC
10777 change_random(const char *value)
10778 {
10779         uint32_t t;
10780
10781         if (value == NULL) {
10782                 /* "get", generate */
10783                 t = next_random(&random_gen);
10784                 /* set without recursion */
10785                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10786                 vrandom.flags &= ~VNOFUNC;
10787         } else {
10788                 /* set/reset */
10789                 t = strtoul(value, NULL, 10);
10790                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10791         }
10792 }
10793 #endif
10794
10795 #if ENABLE_ASH_GETOPTS
10796 static int
10797 getopts(char *optstr, char *optvar, char **optfirst)
10798 {
10799         char *p, *q;
10800         char c = '?';
10801         int done = 0;
10802         char sbuf[2];
10803         char **optnext;
10804         int ind = shellparam.optind;
10805         int off = shellparam.optoff;
10806
10807         sbuf[1] = '\0';
10808
10809         shellparam.optind = -1;
10810         optnext = optfirst + ind - 1;
10811
10812         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10813                 p = NULL;
10814         else
10815                 p = optnext[-1] + off;
10816         if (p == NULL || *p == '\0') {
10817                 /* Current word is done, advance */
10818                 p = *optnext;
10819                 if (p == NULL || *p != '-' || *++p == '\0') {
10820  atend:
10821                         p = NULL;
10822                         done = 1;
10823                         goto out;
10824                 }
10825                 optnext++;
10826                 if (LONE_DASH(p))        /* check for "--" */
10827                         goto atend;
10828         }
10829
10830         c = *p++;
10831         for (q = optstr; *q != c;) {
10832                 if (*q == '\0') {
10833                         if (optstr[0] == ':') {
10834                                 sbuf[0] = c;
10835                                 /*sbuf[1] = '\0'; - already is */
10836                                 setvar0("OPTARG", sbuf);
10837                         } else {
10838                                 fprintf(stderr, "Illegal option -%c\n", c);
10839                                 unsetvar("OPTARG");
10840                         }
10841                         c = '?';
10842                         goto out;
10843                 }
10844                 if (*++q == ':')
10845                         q++;
10846         }
10847
10848         if (*++q == ':') {
10849                 if (*p == '\0' && (p = *optnext) == NULL) {
10850                         if (optstr[0] == ':') {
10851                                 sbuf[0] = c;
10852                                 /*sbuf[1] = '\0'; - already is */
10853                                 setvar0("OPTARG", sbuf);
10854                                 c = ':';
10855                         } else {
10856                                 fprintf(stderr, "No arg for -%c option\n", c);
10857                                 unsetvar("OPTARG");
10858                                 c = '?';
10859                         }
10860                         goto out;
10861                 }
10862
10863                 if (p == *optnext)
10864                         optnext++;
10865                 setvar0("OPTARG", p);
10866                 p = NULL;
10867         } else
10868                 setvar0("OPTARG", nullstr);
10869  out:
10870         ind = optnext - optfirst + 1;
10871         setvar("OPTIND", itoa(ind), VNOFUNC);
10872         sbuf[0] = c;
10873         /*sbuf[1] = '\0'; - already is */
10874         setvar0(optvar, sbuf);
10875
10876         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10877         shellparam.optind = ind;
10878
10879         return done;
10880 }
10881
10882 /*
10883  * The getopts builtin.  Shellparam.optnext points to the next argument
10884  * to be processed.  Shellparam.optptr points to the next character to
10885  * be processed in the current argument.  If shellparam.optnext is NULL,
10886  * then it's the first time getopts has been called.
10887  */
10888 static int FAST_FUNC
10889 getoptscmd(int argc, char **argv)
10890 {
10891         char **optbase;
10892
10893         if (argc < 3)
10894                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10895         if (argc == 3) {
10896                 optbase = shellparam.p;
10897                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10898                         shellparam.optind = 1;
10899                         shellparam.optoff = -1;
10900                 }
10901         } else {
10902                 optbase = &argv[3];
10903                 if ((unsigned)shellparam.optind > argc - 2) {
10904                         shellparam.optind = 1;
10905                         shellparam.optoff = -1;
10906                 }
10907         }
10908
10909         return getopts(argv[1], argv[2], optbase);
10910 }
10911 #endif /* ASH_GETOPTS */
10912
10913
10914 /* ============ Shell parser */
10915
10916 struct heredoc {
10917         struct heredoc *next;   /* next here document in list */
10918         union node *here;       /* redirection node */
10919         char *eofmark;          /* string indicating end of input */
10920         smallint striptabs;     /* if set, strip leading tabs */
10921 };
10922
10923 static smallint tokpushback;           /* last token pushed back */
10924 static smallint quoteflag;             /* set if (part of) last token was quoted */
10925 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10926 static struct heredoc *heredoclist;    /* list of here documents to read */
10927 static char *wordtext;                 /* text of last word returned by readtoken */
10928 static struct nodelist *backquotelist;
10929 static union node *redirnode;
10930 static struct heredoc *heredoc;
10931
10932 static const char *
10933 tokname(char *buf, int tok)
10934 {
10935         if (tok < TSEMI)
10936                 return tokname_array[tok];
10937         sprintf(buf, "\"%s\"", tokname_array[tok]);
10938         return buf;
10939 }
10940
10941 /* raise_error_unexpected_syntax:
10942  * Called when an unexpected token is read during the parse.  The argument
10943  * is the token that is expected, or -1 if more than one type of token can
10944  * occur at this point.
10945  */
10946 static void raise_error_unexpected_syntax(int) NORETURN;
10947 static void
10948 raise_error_unexpected_syntax(int token)
10949 {
10950         char msg[64];
10951         char buf[16];
10952         int l;
10953
10954         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10955         if (token >= 0)
10956                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10957         raise_error_syntax(msg);
10958         /* NOTREACHED */
10959 }
10960
10961 /* parsing is heavily cross-recursive, need these forward decls */
10962 static union node *andor(void);
10963 static union node *pipeline(void);
10964 static union node *parse_command(void);
10965 static void parseheredoc(void);
10966 static int peektoken(void);
10967 static int readtoken(void);
10968
10969 static union node *
10970 list(int nlflag)
10971 {
10972         union node *n1, *n2, *n3;
10973         int tok;
10974
10975         n1 = NULL;
10976         for (;;) {
10977                 switch (peektoken()) {
10978                 case TNL:
10979                         if (!(nlflag & 1))
10980                                 break;
10981                         parseheredoc();
10982                         return n1;
10983
10984                 case TEOF:
10985                         if (!n1 && (nlflag & 1))
10986                                 n1 = NODE_EOF;
10987                         parseheredoc();
10988                         return n1;
10989                 }
10990
10991                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10992                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10993                         return n1;
10994                 nlflag |= 2;
10995
10996                 n2 = andor();
10997                 tok = readtoken();
10998                 if (tok == TBACKGND) {
10999                         if (n2->type == NPIPE) {
11000                                 n2->npipe.pipe_backgnd = 1;
11001                         } else {
11002                                 if (n2->type != NREDIR) {
11003                                         n3 = stzalloc(sizeof(struct nredir));
11004                                         n3->nredir.n = n2;
11005                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11006                                         n2 = n3;
11007                                 }
11008                                 n2->type = NBACKGND;
11009                         }
11010                 }
11011                 if (n1 == NULL) {
11012                         n1 = n2;
11013                 } else {
11014                         n3 = stzalloc(sizeof(struct nbinary));
11015                         n3->type = NSEMI;
11016                         n3->nbinary.ch1 = n1;
11017                         n3->nbinary.ch2 = n2;
11018                         n1 = n3;
11019                 }
11020                 switch (tok) {
11021                 case TNL:
11022                 case TEOF:
11023                         tokpushback = 1;
11024                         /* fall through */
11025                 case TBACKGND:
11026                 case TSEMI:
11027                         break;
11028                 default:
11029                         if ((nlflag & 1))
11030                                 raise_error_unexpected_syntax(-1);
11031                         tokpushback = 1;
11032                         return n1;
11033                 }
11034         }
11035 }
11036
11037 static union node *
11038 andor(void)
11039 {
11040         union node *n1, *n2, *n3;
11041         int t;
11042
11043         n1 = pipeline();
11044         for (;;) {
11045                 t = readtoken();
11046                 if (t == TAND) {
11047                         t = NAND;
11048                 } else if (t == TOR) {
11049                         t = NOR;
11050                 } else {
11051                         tokpushback = 1;
11052                         return n1;
11053                 }
11054                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11055                 n2 = pipeline();
11056                 n3 = stzalloc(sizeof(struct nbinary));
11057                 n3->type = t;
11058                 n3->nbinary.ch1 = n1;
11059                 n3->nbinary.ch2 = n2;
11060                 n1 = n3;
11061         }
11062 }
11063
11064 static union node *
11065 pipeline(void)
11066 {
11067         union node *n1, *n2, *pipenode;
11068         struct nodelist *lp, *prev;
11069         int negate;
11070
11071         negate = 0;
11072         TRACE(("pipeline: entered\n"));
11073         if (readtoken() == TNOT) {
11074                 negate = !negate;
11075                 checkkwd = CHKKWD | CHKALIAS;
11076         } else
11077                 tokpushback = 1;
11078         n1 = parse_command();
11079         if (readtoken() == TPIPE) {
11080                 pipenode = stzalloc(sizeof(struct npipe));
11081                 pipenode->type = NPIPE;
11082                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11083                 lp = stzalloc(sizeof(struct nodelist));
11084                 pipenode->npipe.cmdlist = lp;
11085                 lp->n = n1;
11086                 do {
11087                         prev = lp;
11088                         lp = stzalloc(sizeof(struct nodelist));
11089                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11090                         lp->n = parse_command();
11091                         prev->next = lp;
11092                 } while (readtoken() == TPIPE);
11093                 lp->next = NULL;
11094                 n1 = pipenode;
11095         }
11096         tokpushback = 1;
11097         if (negate) {
11098                 n2 = stzalloc(sizeof(struct nnot));
11099                 n2->type = NNOT;
11100                 n2->nnot.com = n1;
11101                 return n2;
11102         }
11103         return n1;
11104 }
11105
11106 static union node *
11107 makename(void)
11108 {
11109         union node *n;
11110
11111         n = stzalloc(sizeof(struct narg));
11112         n->type = NARG;
11113         /*n->narg.next = NULL; - stzalloc did it */
11114         n->narg.text = wordtext;
11115         n->narg.backquote = backquotelist;
11116         return n;
11117 }
11118
11119 static void
11120 fixredir(union node *n, const char *text, int err)
11121 {
11122         int fd;
11123
11124         TRACE(("Fix redir %s %d\n", text, err));
11125         if (!err)
11126                 n->ndup.vname = NULL;
11127
11128         fd = bb_strtou(text, NULL, 10);
11129         if (!errno && fd >= 0)
11130                 n->ndup.dupfd = fd;
11131         else if (LONE_DASH(text))
11132                 n->ndup.dupfd = -1;
11133         else {
11134                 if (err)
11135                         raise_error_syntax("bad fd number");
11136                 n->ndup.vname = makename();
11137         }
11138 }
11139
11140 static void
11141 parsefname(void)
11142 {
11143         union node *n = redirnode;
11144
11145         if (n->type == NHERE)
11146                 checkkwd = CHKEOFMARK;
11147         if (readtoken() != TWORD)
11148                 raise_error_unexpected_syntax(-1);
11149         if (n->type == NHERE) {
11150                 struct heredoc *here = heredoc;
11151                 struct heredoc *p;
11152
11153                 if (quoteflag == 0)
11154                         n->type = NXHERE;
11155                 TRACE(("Here document %d\n", n->type));
11156                 rmescapes(wordtext, 0);
11157                 here->eofmark = wordtext;
11158                 here->next = NULL;
11159                 if (heredoclist == NULL)
11160                         heredoclist = here;
11161                 else {
11162                         for (p = heredoclist; p->next; p = p->next)
11163                                 continue;
11164                         p->next = here;
11165                 }
11166         } else if (n->type == NTOFD || n->type == NFROMFD) {
11167                 fixredir(n, wordtext, 0);
11168         } else {
11169                 n->nfile.fname = makename();
11170         }
11171 }
11172
11173 static union node *
11174 simplecmd(void)
11175 {
11176         union node *args, **app;
11177         union node *n = NULL;
11178         union node *vars, **vpp;
11179         union node **rpp, *redir;
11180         int savecheckkwd;
11181 #if BASH_TEST2
11182         smallint double_brackets_flag = 0;
11183 #endif
11184         IF_BASH_FUNCTION(smallint function_flag = 0;)
11185
11186         args = NULL;
11187         app = &args;
11188         vars = NULL;
11189         vpp = &vars;
11190         redir = NULL;
11191         rpp = &redir;
11192
11193         savecheckkwd = CHKALIAS;
11194         for (;;) {
11195                 int t;
11196                 checkkwd = savecheckkwd;
11197                 t = readtoken();
11198                 switch (t) {
11199 #if BASH_FUNCTION
11200                 case TFUNCTION:
11201                         if (peektoken() != TWORD)
11202                                 raise_error_unexpected_syntax(TWORD);
11203                         function_flag = 1;
11204                         break;
11205 #endif
11206 #if BASH_TEST2
11207                 case TAND: /* "&&" */
11208                 case TOR: /* "||" */
11209                         if (!double_brackets_flag) {
11210                                 tokpushback = 1;
11211                                 goto out;
11212                         }
11213                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11214 #endif
11215                 case TWORD:
11216                         n = stzalloc(sizeof(struct narg));
11217                         n->type = NARG;
11218                         /*n->narg.next = NULL; - stzalloc did it */
11219                         n->narg.text = wordtext;
11220 #if BASH_TEST2
11221                         if (strcmp("[[", wordtext) == 0)
11222                                 double_brackets_flag = 1;
11223                         else if (strcmp("]]", wordtext) == 0)
11224                                 double_brackets_flag = 0;
11225 #endif
11226                         n->narg.backquote = backquotelist;
11227                         if (savecheckkwd && isassignment(wordtext)) {
11228                                 *vpp = n;
11229                                 vpp = &n->narg.next;
11230                         } else {
11231                                 *app = n;
11232                                 app = &n->narg.next;
11233                                 savecheckkwd = 0;
11234                         }
11235 #if BASH_FUNCTION
11236                         if (function_flag) {
11237                                 checkkwd = CHKNL | CHKKWD;
11238                                 switch (peektoken()) {
11239                                 case TBEGIN:
11240                                 case TIF:
11241                                 case TCASE:
11242                                 case TUNTIL:
11243                                 case TWHILE:
11244                                 case TFOR:
11245                                         goto do_func;
11246                                 case TLP:
11247                                         function_flag = 0;
11248                                         break;
11249                                 case TWORD:
11250                                         if (strcmp("[[", wordtext) == 0)
11251                                                 goto do_func;
11252                                         /* fall through */
11253                                 default:
11254                                         raise_error_unexpected_syntax(-1);
11255                                 }
11256                         }
11257 #endif
11258                         break;
11259                 case TREDIR:
11260                         *rpp = n = redirnode;
11261                         rpp = &n->nfile.next;
11262                         parsefname();   /* read name of redirection file */
11263                         break;
11264                 case TLP:
11265  IF_BASH_FUNCTION(do_func:)
11266                         if (args && app == &args->narg.next
11267                          && !vars && !redir
11268                         ) {
11269                                 struct builtincmd *bcmd;
11270                                 const char *name;
11271
11272                                 /* We have a function */
11273                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11274                                         raise_error_unexpected_syntax(TRP);
11275                                 name = n->narg.text;
11276                                 if (!goodname(name)
11277                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11278                                 ) {
11279                                         raise_error_syntax("bad function name");
11280                                 }
11281                                 n->type = NDEFUN;
11282                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11283                                 n->narg.next = parse_command();
11284                                 return n;
11285                         }
11286                         IF_BASH_FUNCTION(function_flag = 0;)
11287                         /* fall through */
11288                 default:
11289                         tokpushback = 1;
11290                         goto out;
11291                 }
11292         }
11293  out:
11294         *app = NULL;
11295         *vpp = NULL;
11296         *rpp = NULL;
11297         n = stzalloc(sizeof(struct ncmd));
11298         n->type = NCMD;
11299         n->ncmd.args = args;
11300         n->ncmd.assign = vars;
11301         n->ncmd.redirect = redir;
11302         return n;
11303 }
11304
11305 static union node *
11306 parse_command(void)
11307 {
11308         union node *n1, *n2;
11309         union node *ap, **app;
11310         union node *cp, **cpp;
11311         union node *redir, **rpp;
11312         union node **rpp2;
11313         int t;
11314
11315         redir = NULL;
11316         rpp2 = &redir;
11317
11318         switch (readtoken()) {
11319         default:
11320                 raise_error_unexpected_syntax(-1);
11321                 /* NOTREACHED */
11322         case TIF:
11323                 n1 = stzalloc(sizeof(struct nif));
11324                 n1->type = NIF;
11325                 n1->nif.test = list(0);
11326                 if (readtoken() != TTHEN)
11327                         raise_error_unexpected_syntax(TTHEN);
11328                 n1->nif.ifpart = list(0);
11329                 n2 = n1;
11330                 while (readtoken() == TELIF) {
11331                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11332                         n2 = n2->nif.elsepart;
11333                         n2->type = NIF;
11334                         n2->nif.test = list(0);
11335                         if (readtoken() != TTHEN)
11336                                 raise_error_unexpected_syntax(TTHEN);
11337                         n2->nif.ifpart = list(0);
11338                 }
11339                 if (lasttoken == TELSE)
11340                         n2->nif.elsepart = list(0);
11341                 else {
11342                         n2->nif.elsepart = NULL;
11343                         tokpushback = 1;
11344                 }
11345                 t = TFI;
11346                 break;
11347         case TWHILE:
11348         case TUNTIL: {
11349                 int got;
11350                 n1 = stzalloc(sizeof(struct nbinary));
11351                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11352                 n1->nbinary.ch1 = list(0);
11353                 got = readtoken();
11354                 if (got != TDO) {
11355                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11356                                         got == TWORD ? wordtext : ""));
11357                         raise_error_unexpected_syntax(TDO);
11358                 }
11359                 n1->nbinary.ch2 = list(0);
11360                 t = TDONE;
11361                 break;
11362         }
11363         case TFOR:
11364                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11365                         raise_error_syntax("bad for loop variable");
11366                 n1 = stzalloc(sizeof(struct nfor));
11367                 n1->type = NFOR;
11368                 n1->nfor.var = wordtext;
11369                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11370                 if (readtoken() == TIN) {
11371                         app = &ap;
11372                         while (readtoken() == TWORD) {
11373                                 n2 = stzalloc(sizeof(struct narg));
11374                                 n2->type = NARG;
11375                                 /*n2->narg.next = NULL; - stzalloc did it */
11376                                 n2->narg.text = wordtext;
11377                                 n2->narg.backquote = backquotelist;
11378                                 *app = n2;
11379                                 app = &n2->narg.next;
11380                         }
11381                         *app = NULL;
11382                         n1->nfor.args = ap;
11383                         if (lasttoken != TNL && lasttoken != TSEMI)
11384                                 raise_error_unexpected_syntax(-1);
11385                 } else {
11386                         n2 = stzalloc(sizeof(struct narg));
11387                         n2->type = NARG;
11388                         /*n2->narg.next = NULL; - stzalloc did it */
11389                         n2->narg.text = (char *)dolatstr;
11390                         /*n2->narg.backquote = NULL;*/
11391                         n1->nfor.args = n2;
11392                         /*
11393                          * Newline or semicolon here is optional (but note
11394                          * that the original Bourne shell only allowed NL).
11395                          */
11396                         if (lasttoken != TSEMI)
11397                                 tokpushback = 1;
11398                 }
11399                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11400                 if (readtoken() != TDO)
11401                         raise_error_unexpected_syntax(TDO);
11402                 n1->nfor.body = list(0);
11403                 t = TDONE;
11404                 break;
11405         case TCASE:
11406                 n1 = stzalloc(sizeof(struct ncase));
11407                 n1->type = NCASE;
11408                 if (readtoken() != TWORD)
11409                         raise_error_unexpected_syntax(TWORD);
11410                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11411                 n2->type = NARG;
11412                 /*n2->narg.next = NULL; - stzalloc did it */
11413                 n2->narg.text = wordtext;
11414                 n2->narg.backquote = backquotelist;
11415                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11416                 if (readtoken() != TIN)
11417                         raise_error_unexpected_syntax(TIN);
11418                 cpp = &n1->ncase.cases;
11419  next_case:
11420                 checkkwd = CHKNL | CHKKWD;
11421                 t = readtoken();
11422                 while (t != TESAC) {
11423                         if (lasttoken == TLP)
11424                                 readtoken();
11425                         *cpp = cp = stzalloc(sizeof(struct nclist));
11426                         cp->type = NCLIST;
11427                         app = &cp->nclist.pattern;
11428                         for (;;) {
11429                                 *app = ap = stzalloc(sizeof(struct narg));
11430                                 ap->type = NARG;
11431                                 /*ap->narg.next = NULL; - stzalloc did it */
11432                                 ap->narg.text = wordtext;
11433                                 ap->narg.backquote = backquotelist;
11434                                 if (readtoken() != TPIPE)
11435                                         break;
11436                                 app = &ap->narg.next;
11437                                 readtoken();
11438                         }
11439                         //ap->narg.next = NULL;
11440                         if (lasttoken != TRP)
11441                                 raise_error_unexpected_syntax(TRP);
11442                         cp->nclist.body = list(2);
11443
11444                         cpp = &cp->nclist.next;
11445
11446                         checkkwd = CHKNL | CHKKWD;
11447                         t = readtoken();
11448                         if (t != TESAC) {
11449                                 if (t != TENDCASE)
11450                                         raise_error_unexpected_syntax(TENDCASE);
11451                                 goto next_case;
11452                         }
11453                 }
11454                 *cpp = NULL;
11455                 goto redir;
11456         case TLP:
11457                 n1 = stzalloc(sizeof(struct nredir));
11458                 n1->type = NSUBSHELL;
11459                 n1->nredir.n = list(0);
11460                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11461                 t = TRP;
11462                 break;
11463         case TBEGIN:
11464                 n1 = list(0);
11465                 t = TEND;
11466                 break;
11467         IF_BASH_FUNCTION(case TFUNCTION:)
11468         case TWORD:
11469         case TREDIR:
11470                 tokpushback = 1;
11471                 return simplecmd();
11472         }
11473
11474         if (readtoken() != t)
11475                 raise_error_unexpected_syntax(t);
11476
11477  redir:
11478         /* Now check for redirection which may follow command */
11479         checkkwd = CHKKWD | CHKALIAS;
11480         rpp = rpp2;
11481         while (readtoken() == TREDIR) {
11482                 *rpp = n2 = redirnode;
11483                 rpp = &n2->nfile.next;
11484                 parsefname();
11485         }
11486         tokpushback = 1;
11487         *rpp = NULL;
11488         if (redir) {
11489                 if (n1->type != NSUBSHELL) {
11490                         n2 = stzalloc(sizeof(struct nredir));
11491                         n2->type = NREDIR;
11492                         n2->nredir.n = n1;
11493                         n1 = n2;
11494                 }
11495                 n1->nredir.redirect = redir;
11496         }
11497         return n1;
11498 }
11499
11500 #if BASH_DOLLAR_SQUOTE
11501 static int
11502 decode_dollar_squote(void)
11503 {
11504         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11505         int c, cnt;
11506         char *p;
11507         char buf[4];
11508
11509         c = pgetc();
11510         p = strchr(C_escapes, c);
11511         if (p) {
11512                 buf[0] = c;
11513                 p = buf;
11514                 cnt = 3;
11515                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11516                         do {
11517                                 c = pgetc();
11518                                 *++p = c;
11519                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11520                         pungetc();
11521                 } else if (c == 'x') { /* \xHH */
11522                         do {
11523                                 c = pgetc();
11524                                 *++p = c;
11525                         } while (isxdigit(c) && --cnt);
11526                         pungetc();
11527                         if (cnt == 3) { /* \x but next char is "bad" */
11528                                 c = 'x';
11529                                 goto unrecognized;
11530                         }
11531                 } else { /* simple seq like \\ or \t */
11532                         p++;
11533                 }
11534                 *p = '\0';
11535                 p = buf;
11536                 c = bb_process_escape_sequence((void*)&p);
11537         } else { /* unrecognized "\z": print both chars unless ' or " */
11538                 if (c != '\'' && c != '"') {
11539  unrecognized:
11540                         c |= 0x100; /* "please encode \, then me" */
11541                 }
11542         }
11543         return c;
11544 }
11545 #endif
11546
11547 /* Used by expandstr to get here-doc like behaviour. */
11548 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11549
11550 static ALWAYS_INLINE int
11551 realeofmark(const char *eofmark)
11552 {
11553         return eofmark && eofmark != FAKEEOFMARK;
11554 }
11555
11556 /*
11557  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11558  * is not NULL, read a here document.  In the latter case, eofmark is the
11559  * word which marks the end of the document and striptabs is true if
11560  * leading tabs should be stripped from the document.  The argument c
11561  * is the first character of the input token or document.
11562  *
11563  * Because C does not have internal subroutines, I have simulated them
11564  * using goto's to implement the subroutine linkage.  The following macros
11565  * will run code that appears at the end of readtoken1.
11566  */
11567 #define CHECKEND()      {goto checkend; checkend_return:;}
11568 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11569 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11570 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11571 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11572 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11573 static int
11574 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11575 {
11576         /* NB: syntax parameter fits into smallint */
11577         /* c parameter is an unsigned char or PEOF or PEOA */
11578         char *out;
11579         size_t len;
11580         struct nodelist *bqlist;
11581         smallint quotef;
11582         smallint dblquote;
11583         smallint oldstyle;
11584         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11585         smallint pssyntax;   /* we are expanding a prompt string */
11586         int varnest;         /* levels of variables expansion */
11587         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11588         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11589         int dqvarnest;       /* levels of variables expansion within double quotes */
11590
11591         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11592
11593         startlinno = g_parsefile->linno;
11594         bqlist = NULL;
11595         quotef = 0;
11596         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11597         pssyntax = (syntax == PSSYNTAX);
11598         if (pssyntax)
11599                 syntax = DQSYNTAX;
11600         dblquote = (syntax == DQSYNTAX);
11601         varnest = 0;
11602         IF_FEATURE_SH_MATH(arinest = 0;)
11603         IF_FEATURE_SH_MATH(parenlevel = 0;)
11604         dqvarnest = 0;
11605
11606         STARTSTACKSTR(out);
11607  loop:
11608         /* For each line, until end of word */
11609         CHECKEND();     /* set c to PEOF if at end of here document */
11610         for (;;) {      /* until end of line or end of word */
11611                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11612                 switch (SIT(c, syntax)) {
11613                 case CNL:       /* '\n' */
11614                         if (syntax == BASESYNTAX)
11615                                 goto endword;   /* exit outer loop */
11616                         USTPUTC(c, out);
11617                         nlprompt();
11618                         c = pgetc();
11619                         goto loop;              /* continue outer loop */
11620                 case CWORD:
11621                         USTPUTC(c, out);
11622                         break;
11623                 case CCTL:
11624 #if BASH_DOLLAR_SQUOTE
11625                         if (c == '\\' && bash_dollar_squote) {
11626                                 c = decode_dollar_squote();
11627                                 if (c == '\0') {
11628                                         /* skip $'\000', $'\x00' (like bash) */
11629                                         break;
11630                                 }
11631                                 if (c & 0x100) {
11632                                         /* Unknown escape. Encode as '\z' */
11633                                         c = (unsigned char)c;
11634                                         if (eofmark == NULL || dblquote)
11635                                                 USTPUTC(CTLESC, out);
11636                                         USTPUTC('\\', out);
11637                                 }
11638                         }
11639 #endif
11640                         if (eofmark == NULL || dblquote)
11641                                 USTPUTC(CTLESC, out);
11642                         USTPUTC(c, out);
11643                         break;
11644                 case CBACK:     /* backslash */
11645                         c = pgetc_without_PEOA();
11646                         if (c == PEOF) {
11647                                 USTPUTC(CTLESC, out);
11648                                 USTPUTC('\\', out);
11649                                 pungetc();
11650                         } else if (c == '\n') {
11651                                 nlprompt();
11652                         } else {
11653                                 if (c == '$' && pssyntax) {
11654                                         USTPUTC(CTLESC, out);
11655                                         USTPUTC('\\', out);
11656                                 }
11657                                 /* Backslash is retained if we are in "str" and next char isn't special */
11658                                 if (dblquote
11659                                  && c != '\\'
11660                                  && c != '`'
11661                                  && c != '$'
11662                                  && (c != '"' || eofmark != NULL)
11663                                 ) {
11664                                         USTPUTC('\\', out);
11665                                 }
11666                                 USTPUTC(CTLESC, out);
11667                                 USTPUTC(c, out);
11668                                 quotef = 1;
11669                         }
11670                         break;
11671                 case CSQUOTE:
11672                         syntax = SQSYNTAX;
11673  quotemark:
11674                         if (eofmark == NULL) {
11675                                 USTPUTC(CTLQUOTEMARK, out);
11676                         }
11677                         break;
11678                 case CDQUOTE:
11679                         syntax = DQSYNTAX;
11680                         dblquote = 1;
11681                         goto quotemark;
11682                 case CENDQUOTE:
11683                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11684                         if (eofmark != NULL && varnest == 0) {
11685                                 USTPUTC(c, out);
11686                         } else {
11687                                 if (dqvarnest == 0) {
11688                                         syntax = BASESYNTAX;
11689                                         dblquote = 0;
11690                                 }
11691                                 quotef = 1;
11692                                 goto quotemark;
11693                         }
11694                         break;
11695                 case CVAR:      /* '$' */
11696                         PARSESUB();             /* parse substitution */
11697                         break;
11698                 case CENDVAR:   /* '}' */
11699                         if (varnest > 0) {
11700                                 varnest--;
11701                                 if (dqvarnest > 0) {
11702                                         dqvarnest--;
11703                                 }
11704                                 c = CTLENDVAR;
11705                         }
11706                         USTPUTC(c, out);
11707                         break;
11708 #if ENABLE_FEATURE_SH_MATH
11709                 case CLP:       /* '(' in arithmetic */
11710                         parenlevel++;
11711                         USTPUTC(c, out);
11712                         break;
11713                 case CRP:       /* ')' in arithmetic */
11714                         if (parenlevel > 0) {
11715                                 parenlevel--;
11716                         } else {
11717                                 if (pgetc_eatbnl() == ')') {
11718                                         c = CTLENDARI;
11719                                         if (--arinest == 0) {
11720                                                 syntax = prevsyntax;
11721                                         }
11722                                 } else {
11723                                         /*
11724                                          * unbalanced parens
11725                                          * (don't 2nd guess - no error)
11726                                          */
11727                                         pungetc();
11728                                 }
11729                         }
11730                         USTPUTC(c, out);
11731                         break;
11732 #endif
11733                 case CBQUOTE:   /* '`' */
11734                         PARSEBACKQOLD();
11735                         break;
11736                 case CENDFILE:
11737                         goto endword;           /* exit outer loop */
11738                 case CIGN:
11739                         break;
11740                 default:
11741                         if (varnest == 0) {
11742 #if BASH_REDIR_OUTPUT
11743                                 if (c == '&') {
11744 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11745                                         if (pgetc() == '>')
11746                                                 c = 0x100 + '>'; /* flag &> */
11747                                         pungetc();
11748                                 }
11749 #endif
11750                                 goto endword;   /* exit outer loop */
11751                         }
11752                         IF_ASH_ALIAS(if (c != PEOA))
11753                                 USTPUTC(c, out);
11754                 }
11755                 c = pgetc();
11756         } /* for (;;) */
11757  endword:
11758
11759 #if ENABLE_FEATURE_SH_MATH
11760         if (syntax == ARISYNTAX)
11761                 raise_error_syntax("missing '))'");
11762 #endif
11763         if (syntax != BASESYNTAX && eofmark == NULL)
11764                 raise_error_syntax("unterminated quoted string");
11765         if (varnest != 0) {
11766                 startlinno = g_parsefile->linno;
11767                 /* { */
11768                 raise_error_syntax("missing '}'");
11769         }
11770         USTPUTC('\0', out);
11771         len = out - (char *)stackblock();
11772         out = stackblock();
11773         if (eofmark == NULL) {
11774                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11775                  && quotef == 0
11776                 ) {
11777                         if (isdigit_str9(out)) {
11778                                 PARSEREDIR(); /* passed as params: out, c */
11779                                 lasttoken = TREDIR;
11780                                 return lasttoken;
11781                         }
11782                         /* else: non-number X seen, interpret it
11783                          * as "NNNX>file" = "NNNX >file" */
11784                 }
11785                 pungetc();
11786         }
11787         quoteflag = quotef;
11788         backquotelist = bqlist;
11789         grabstackblock(len);
11790         wordtext = out;
11791         lasttoken = TWORD;
11792         return lasttoken;
11793 /* end of readtoken routine */
11794
11795 /*
11796  * Check to see whether we are at the end of the here document.  When this
11797  * is called, c is set to the first character of the next input line.  If
11798  * we are at the end of the here document, this routine sets the c to PEOF.
11799  */
11800 checkend: {
11801         if (realeofmark(eofmark)) {
11802                 int markloc;
11803                 char *p;
11804
11805 #if ENABLE_ASH_ALIAS
11806                 if (c == PEOA)
11807                         c = pgetc_without_PEOA();
11808 #endif
11809                 if (striptabs) {
11810                         while (c == '\t') {
11811                                 c = pgetc_without_PEOA();
11812                         }
11813                 }
11814
11815                 markloc = out - (char *)stackblock();
11816                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11817                         if (c != *p)
11818                                 goto more_heredoc;
11819
11820                         c = pgetc_without_PEOA();
11821                 }
11822
11823                 if (c == '\n' || c == PEOF) {
11824                         c = PEOF;
11825                         g_parsefile->linno++;
11826                         needprompt = doprompt;
11827                 } else {
11828                         int len_here;
11829
11830  more_heredoc:
11831                         p = (char *)stackblock() + markloc + 1;
11832                         len_here = out - p;
11833
11834                         if (len_here) {
11835                                 len_here -= (c >= PEOF);
11836                                 c = p[-1];
11837
11838                                 if (len_here) {
11839                                         char *str;
11840
11841                                         str = alloca(len_here + 1);
11842                                         *(char *)mempcpy(str, p, len_here) = '\0';
11843
11844                                         pushstring(str, NULL);
11845                                 }
11846                         }
11847                 }
11848
11849                 STADJUST((char *)stackblock() + markloc - out, out);
11850         }
11851         goto checkend_return;
11852 }
11853
11854 /*
11855  * Parse a redirection operator.  The variable "out" points to a string
11856  * specifying the fd to be redirected.  The variable "c" contains the
11857  * first character of the redirection operator.
11858  */
11859 parseredir: {
11860         /* out is already checked to be a valid number or "" */
11861         int fd = (*out == '\0' ? -1 : atoi(out));
11862         union node *np;
11863
11864         np = stzalloc(sizeof(struct nfile));
11865         if (c == '>') {
11866                 np->nfile.fd = 1;
11867                 c = pgetc();
11868                 if (c == '>')
11869                         np->type = NAPPEND;
11870                 else if (c == '|')
11871                         np->type = NCLOBBER;
11872                 else if (c == '&')
11873                         np->type = NTOFD;
11874                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11875                 else {
11876                         np->type = NTO;
11877                         pungetc();
11878                 }
11879         }
11880 #if BASH_REDIR_OUTPUT
11881         else if (c == 0x100 + '>') { /* this flags &> redirection */
11882                 np->nfile.fd = 1;
11883                 pgetc(); /* this is '>', no need to check */
11884                 np->type = NTO2;
11885         }
11886 #endif
11887         else { /* c == '<' */
11888                 /*np->nfile.fd = 0; - stzalloc did it */
11889                 c = pgetc();
11890                 switch (c) {
11891                 case '<':
11892                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11893                                 np = stzalloc(sizeof(struct nhere));
11894                                 /*np->nfile.fd = 0; - stzalloc did it */
11895                         }
11896                         np->type = NHERE;
11897                         heredoc = stzalloc(sizeof(struct heredoc));
11898                         heredoc->here = np;
11899                         c = pgetc();
11900                         if (c == '-') {
11901                                 heredoc->striptabs = 1;
11902                         } else {
11903                                 /*heredoc->striptabs = 0; - stzalloc did it */
11904                                 pungetc();
11905                         }
11906                         break;
11907
11908                 case '&':
11909                         np->type = NFROMFD;
11910                         break;
11911
11912                 case '>':
11913                         np->type = NFROMTO;
11914                         break;
11915
11916                 default:
11917                         np->type = NFROM;
11918                         pungetc();
11919                         break;
11920                 }
11921         }
11922         if (fd >= 0)
11923                 np->nfile.fd = fd;
11924         redirnode = np;
11925         goto parseredir_return;
11926 }
11927
11928 /*
11929  * Parse a substitution.  At this point, we have read the dollar sign
11930  * and nothing else.
11931  */
11932
11933 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11934  * (assuming ascii char codes, as the original implementation did) */
11935 #define is_special(c) \
11936         (((unsigned)(c) - 33 < 32) \
11937                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11938 parsesub: {
11939         unsigned char subtype;
11940         int typeloc;
11941
11942         c = pgetc_eatbnl();
11943         if ((checkkwd & CHKEOFMARK)
11944          || c > 255 /* PEOA or PEOF */
11945          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11946         ) {
11947 #if BASH_DOLLAR_SQUOTE
11948                 if (syntax != DQSYNTAX && c == '\'')
11949                         bash_dollar_squote = 1;
11950                 else
11951 #endif
11952                         USTPUTC('$', out);
11953                 pungetc();
11954         } else if (c == '(') {
11955                 /* $(command) or $((arith)) */
11956                 if (pgetc_eatbnl() == '(') {
11957 #if ENABLE_FEATURE_SH_MATH
11958                         PARSEARITH();
11959 #else
11960                         raise_error_syntax("support for $((arith)) is disabled");
11961 #endif
11962                 } else {
11963                         pungetc();
11964                         PARSEBACKQNEW();
11965                 }
11966         } else {
11967                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11968                 USTPUTC(CTLVAR, out);
11969                 typeloc = out - (char *)stackblock();
11970                 STADJUST(1, out);
11971                 subtype = VSNORMAL;
11972                 if (c == '{') {
11973                         c = pgetc_eatbnl();
11974                         subtype = 0;
11975                 }
11976  varname:
11977                 if (is_name(c)) {
11978                         /* $[{[#]]NAME[}] */
11979                         do {
11980                                 STPUTC(c, out);
11981                                 c = pgetc_eatbnl();
11982                         } while (is_in_name(c));
11983                 } else if (isdigit(c)) {
11984                         /* $[{[#]]NUM[}] */
11985                         do {
11986                                 STPUTC(c, out);
11987                                 c = pgetc_eatbnl();
11988                         } while (isdigit(c));
11989                 } else if (is_special(c)) {
11990                         /* $[{[#]]<specialchar>[}] */
11991                         int cc = c;
11992
11993                         c = pgetc_eatbnl();
11994                         if (!subtype && cc == '#') {
11995                                 subtype = VSLENGTH;
11996                                 if (c == '_' || isalnum(c))
11997                                         goto varname;
11998                                 cc = c;
11999                                 c = pgetc_eatbnl();
12000                                 if (cc == '}' || c != '}') {
12001                                         pungetc();
12002                                         subtype = 0;
12003                                         c = cc;
12004                                         cc = '#';
12005                                 }
12006                         }
12007                         USTPUTC(cc, out);
12008                 } else {
12009                         goto badsub;
12010                 }
12011                 if (c != '}' && subtype == VSLENGTH) {
12012                         /* ${#VAR didn't end with } */
12013                         goto badsub;
12014                 }
12015
12016                 if (subtype == 0) {
12017                         static const char types[] ALIGN1 = "}-+?=";
12018                         /* ${VAR...} but not $VAR or ${#VAR} */
12019                         /* c == first char after VAR */
12020                         switch (c) {
12021                         case ':':
12022                                 c = pgetc_eatbnl();
12023 #if BASH_SUBSTR
12024                                 /* This check is only needed to not misinterpret
12025                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12026                                  * constructs.
12027                                  */
12028                                 if (!strchr(types, c)) {
12029                                         subtype = VSSUBSTR;
12030                                         pungetc();
12031                                         break; /* "goto badsub" is bigger (!) */
12032                                 }
12033 #endif
12034                                 subtype = VSNUL;
12035                                 /*FALLTHROUGH*/
12036                         default: {
12037                                 const char *p = strchr(types, c);
12038                                 if (p == NULL)
12039                                         break;
12040                                 subtype |= p - types + VSNORMAL;
12041                                 break;
12042                         }
12043                         case '%':
12044                         case '#': {
12045                                 int cc = c;
12046                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12047                                 c = pgetc_eatbnl();
12048                                 if (c != cc)
12049                                         goto badsub;
12050                                 subtype++;
12051                                 break;
12052                         }
12053 #if BASH_PATTERN_SUBST
12054                         case '/':
12055                                 /* ${v/[/]pattern/repl} */
12056 //TODO: encode pattern and repl separately.
12057 // Currently ${v/$var_with_slash/repl} is horribly broken
12058                                 subtype = VSREPLACE;
12059                                 c = pgetc_eatbnl();
12060                                 if (c != '/')
12061                                         goto badsub;
12062                                 subtype++; /* VSREPLACEALL */
12063                                 break;
12064 #endif
12065                         }
12066                 } else {
12067  badsub:
12068                         pungetc();
12069                 }
12070                 ((unsigned char *)stackblock())[typeloc] = subtype;
12071                 if (subtype != VSNORMAL) {
12072                         varnest++;
12073                         if (dblquote)
12074                                 dqvarnest++;
12075                 }
12076                 STPUTC('=', out);
12077         }
12078         goto parsesub_return;
12079 }
12080
12081 /*
12082  * Called to parse command substitutions.  Newstyle is set if the command
12083  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12084  * list of commands (passed by reference), and savelen is the number of
12085  * characters on the top of the stack which must be preserved.
12086  */
12087 parsebackq: {
12088         struct nodelist **nlpp;
12089         union node *n;
12090         char *str;
12091         size_t savelen;
12092         smallint saveprompt = 0;
12093
12094         str = NULL;
12095         savelen = out - (char *)stackblock();
12096         if (savelen > 0) {
12097                 /*
12098                  * FIXME: this can allocate very large block on stack and SEGV.
12099                  * Example:
12100                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12101                  * allocates 100kb for every command subst. With about
12102                  * a hundred command substitutions stack overflows.
12103                  * With larger prepended string, SEGV happens sooner.
12104                  */
12105                 str = alloca(savelen);
12106                 memcpy(str, stackblock(), savelen);
12107         }
12108
12109         if (oldstyle) {
12110                 /* We must read until the closing backquote, giving special
12111                  * treatment to some slashes, and then push the string and
12112                  * reread it as input, interpreting it normally.
12113                  */
12114                 char *pout;
12115                 size_t psavelen;
12116                 char *pstr;
12117
12118                 STARTSTACKSTR(pout);
12119                 for (;;) {
12120                         int pc;
12121
12122                         setprompt_if(needprompt, 2);
12123                         pc = pgetc();
12124                         switch (pc) {
12125                         case '`':
12126                                 goto done;
12127
12128                         case '\\':
12129                                 pc = pgetc();
12130                                 if (pc == '\n') {
12131                                         nlprompt();
12132                                         /*
12133                                          * If eating a newline, avoid putting
12134                                          * the newline into the new character
12135                                          * stream (via the STPUTC after the
12136                                          * switch).
12137                                          */
12138                                         continue;
12139                                 }
12140                                 if (pc != '\\' && pc != '`' && pc != '$'
12141                                  && (!dblquote || pc != '"')
12142                                 ) {
12143                                         STPUTC('\\', pout);
12144                                 }
12145                                 if (pc <= 255 /* not PEOA or PEOF */) {
12146                                         break;
12147                                 }
12148                                 /* fall through */
12149
12150                         case PEOF:
12151                         IF_ASH_ALIAS(case PEOA:)
12152                                 startlinno = g_parsefile->linno;
12153                                 raise_error_syntax("EOF in backquote substitution");
12154
12155                         case '\n':
12156                                 nlnoprompt();
12157                                 break;
12158
12159                         default:
12160                                 break;
12161                         }
12162                         STPUTC(pc, pout);
12163                 }
12164  done:
12165                 STPUTC('\0', pout);
12166                 psavelen = pout - (char *)stackblock();
12167                 if (psavelen > 0) {
12168                         pstr = grabstackstr(pout);
12169                         setinputstring(pstr);
12170                 }
12171         }
12172         nlpp = &bqlist;
12173         while (*nlpp)
12174                 nlpp = &(*nlpp)->next;
12175         *nlpp = stzalloc(sizeof(**nlpp));
12176         /* (*nlpp)->next = NULL; - stzalloc did it */
12177
12178         if (oldstyle) {
12179                 saveprompt = doprompt;
12180                 doprompt = 0;
12181         }
12182
12183         n = list(2);
12184
12185         if (oldstyle)
12186                 doprompt = saveprompt;
12187         else if (readtoken() != TRP)
12188                 raise_error_unexpected_syntax(TRP);
12189
12190         (*nlpp)->n = n;
12191         if (oldstyle) {
12192                 /*
12193                  * Start reading from old file again, ignoring any pushed back
12194                  * tokens left from the backquote parsing
12195                  */
12196                 popfile();
12197                 tokpushback = 0;
12198         }
12199         while (stackblocksize() <= savelen)
12200                 growstackblock();
12201         STARTSTACKSTR(out);
12202         if (str) {
12203                 memcpy(out, str, savelen);
12204                 STADJUST(savelen, out);
12205         }
12206         USTPUTC(CTLBACKQ, out);
12207         if (oldstyle)
12208                 goto parsebackq_oldreturn;
12209         goto parsebackq_newreturn;
12210 }
12211
12212 #if ENABLE_FEATURE_SH_MATH
12213 /*
12214  * Parse an arithmetic expansion (indicate start of one and set state)
12215  */
12216 parsearith: {
12217         if (++arinest == 1) {
12218                 prevsyntax = syntax;
12219                 syntax = ARISYNTAX;
12220         }
12221         USTPUTC(CTLARI, out);
12222         goto parsearith_return;
12223 }
12224 #endif
12225 } /* end of readtoken */
12226
12227 /*
12228  * Read the next input token.
12229  * If the token is a word, we set backquotelist to the list of cmds in
12230  *      backquotes.  We set quoteflag to true if any part of the word was
12231  *      quoted.
12232  * If the token is TREDIR, then we set redirnode to a structure containing
12233  *      the redirection.
12234  * In all cases, the variable startlinno is set to the number of the line
12235  *      on which the token starts.
12236  *
12237  * [Change comment:  here documents and internal procedures]
12238  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12239  *  word parsing code into a separate routine.  In this case, readtoken
12240  *  doesn't need to have any internal procedures, but parseword does.
12241  *  We could also make parseoperator in essence the main routine, and
12242  *  have parseword (readtoken1?) handle both words and redirection.]
12243  */
12244 #define NEW_xxreadtoken
12245 #ifdef NEW_xxreadtoken
12246 /* singles must be first! */
12247 static const char xxreadtoken_chars[7] ALIGN1 = {
12248         '\n', '(', ')', /* singles */
12249         '&', '|', ';',  /* doubles */
12250         0
12251 };
12252
12253 #define xxreadtoken_singles 3
12254 #define xxreadtoken_doubles 3
12255
12256 static const char xxreadtoken_tokens[] ALIGN1 = {
12257         TNL, TLP, TRP,          /* only single occurrence allowed */
12258         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12259         TEOF,                   /* corresponds to trailing nul */
12260         TAND, TOR, TENDCASE     /* if double occurrence */
12261 };
12262
12263 static int
12264 xxreadtoken(void)
12265 {
12266         int c;
12267
12268         if (tokpushback) {
12269                 tokpushback = 0;
12270                 return lasttoken;
12271         }
12272         setprompt_if(needprompt, 2);
12273         startlinno = g_parsefile->linno;
12274         for (;;) {                      /* until token or start of word found */
12275                 c = pgetc();
12276                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12277                         continue;
12278
12279                 if (c == '#') {
12280                         while ((c = pgetc()) != '\n' && c != PEOF)
12281                                 continue;
12282                         pungetc();
12283                 } else if (c == '\\') {
12284                         if (pgetc() != '\n') {
12285                                 pungetc();
12286                                 break; /* return readtoken1(...) */
12287                         }
12288                         nlprompt();
12289                 } else {
12290                         const char *p;
12291
12292                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12293                         if (c != PEOF) {
12294                                 if (c == '\n') {
12295                                         nlnoprompt();
12296                                 }
12297
12298                                 p = strchr(xxreadtoken_chars, c);
12299                                 if (p == NULL)
12300                                         break; /* return readtoken1(...) */
12301
12302                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12303                                         int cc = pgetc();
12304                                         if (cc == c) {    /* double occurrence? */
12305                                                 p += xxreadtoken_doubles + 1;
12306                                         } else {
12307                                                 pungetc();
12308 #if BASH_REDIR_OUTPUT
12309                                                 if (c == '&' && cc == '>') /* &> */
12310                                                         break; /* return readtoken1(...) */
12311 #endif
12312                                         }
12313                                 }
12314                         }
12315                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12316                         return lasttoken;
12317                 }
12318         } /* for (;;) */
12319
12320         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12321 }
12322 #else /* old xxreadtoken */
12323 #define RETURN(token)   return lasttoken = token
12324 static int
12325 xxreadtoken(void)
12326 {
12327         int c;
12328
12329         if (tokpushback) {
12330                 tokpushback = 0;
12331                 return lasttoken;
12332         }
12333         setprompt_if(needprompt, 2);
12334         startlinno = g_parsefile->linno;
12335         for (;;) {      /* until token or start of word found */
12336                 c = pgetc();
12337                 switch (c) {
12338                 case ' ': case '\t':
12339                 IF_ASH_ALIAS(case PEOA:)
12340                         continue;
12341                 case '#':
12342                         while ((c = pgetc()) != '\n' && c != PEOF)
12343                                 continue;
12344                         pungetc();
12345                         continue;
12346                 case '\\':
12347                         if (pgetc() == '\n') {
12348                                 nlprompt();
12349                                 continue;
12350                         }
12351                         pungetc();
12352                         goto breakloop;
12353                 case '\n':
12354                         nlnoprompt();
12355                         RETURN(TNL);
12356                 case PEOF:
12357                         RETURN(TEOF);
12358                 case '&':
12359                         if (pgetc() == '&')
12360                                 RETURN(TAND);
12361                         pungetc();
12362                         RETURN(TBACKGND);
12363                 case '|':
12364                         if (pgetc() == '|')
12365                                 RETURN(TOR);
12366                         pungetc();
12367                         RETURN(TPIPE);
12368                 case ';':
12369                         if (pgetc() == ';')
12370                                 RETURN(TENDCASE);
12371                         pungetc();
12372                         RETURN(TSEMI);
12373                 case '(':
12374                         RETURN(TLP);
12375                 case ')':
12376                         RETURN(TRP);
12377                 default:
12378                         goto breakloop;
12379                 }
12380         }
12381  breakloop:
12382         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12383 #undef RETURN
12384 }
12385 #endif /* old xxreadtoken */
12386
12387 static int
12388 readtoken(void)
12389 {
12390         int t;
12391         int kwd = checkkwd;
12392 #if DEBUG
12393         smallint alreadyseen = tokpushback;
12394 #endif
12395
12396 #if ENABLE_ASH_ALIAS
12397  top:
12398 #endif
12399
12400         t = xxreadtoken();
12401
12402         /*
12403          * eat newlines
12404          */
12405         if (kwd & CHKNL) {
12406                 while (t == TNL) {
12407                         parseheredoc();
12408                         t = xxreadtoken();
12409                 }
12410         }
12411
12412         if (t != TWORD || quoteflag) {
12413                 goto out;
12414         }
12415
12416         /*
12417          * check for keywords
12418          */
12419         if (kwd & CHKKWD) {
12420                 const char *const *pp;
12421
12422                 pp = findkwd(wordtext);
12423                 if (pp) {
12424                         lasttoken = t = pp - tokname_array;
12425                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12426                         goto out;
12427                 }
12428         }
12429
12430         if (checkkwd & CHKALIAS) {
12431 #if ENABLE_ASH_ALIAS
12432                 struct alias *ap;
12433                 ap = lookupalias(wordtext, 1);
12434                 if (ap != NULL) {
12435                         if (*ap->val) {
12436                                 pushstring(ap->val, ap);
12437                         }
12438                         goto top;
12439                 }
12440 #endif
12441         }
12442  out:
12443         checkkwd = 0;
12444 #if DEBUG
12445         if (!alreadyseen)
12446                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12447         else
12448                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12449 #endif
12450         return t;
12451 }
12452
12453 static int
12454 peektoken(void)
12455 {
12456         int t;
12457
12458         t = readtoken();
12459         tokpushback = 1;
12460         return t;
12461 }
12462
12463 /*
12464  * Read and parse a command.  Returns NODE_EOF on end of file.
12465  * (NULL is a valid parse tree indicating a blank line.)
12466  */
12467 static union node *
12468 parsecmd(int interact)
12469 {
12470         tokpushback = 0;
12471         checkkwd = 0;
12472         heredoclist = 0;
12473         doprompt = interact;
12474         setprompt_if(doprompt, doprompt);
12475         needprompt = 0;
12476         return list(1);
12477 }
12478
12479 /*
12480  * Input any here documents.
12481  */
12482 static void
12483 parseheredoc(void)
12484 {
12485         struct heredoc *here;
12486         union node *n;
12487
12488         here = heredoclist;
12489         heredoclist = NULL;
12490
12491         while (here) {
12492                 setprompt_if(needprompt, 2);
12493                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12494                                 here->eofmark, here->striptabs);
12495                 n = stzalloc(sizeof(struct narg));
12496                 n->narg.type = NARG;
12497                 /*n->narg.next = NULL; - stzalloc did it */
12498                 n->narg.text = wordtext;
12499                 n->narg.backquote = backquotelist;
12500                 here->here->nhere.doc = n;
12501                 here = here->next;
12502         }
12503 }
12504
12505
12506 static const char *
12507 expandstr(const char *ps, int syntax_type)
12508 {
12509         union node n;
12510         int saveprompt;
12511
12512         /* XXX Fix (char *) cast. */
12513         setinputstring((char *)ps);
12514
12515         saveprompt = doprompt;
12516         doprompt = 0;
12517         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12518         doprompt = saveprompt;
12519
12520         popfile();
12521
12522         n.narg.type = NARG;
12523         n.narg.next = NULL;
12524         n.narg.text = wordtext;
12525         n.narg.backquote = backquotelist;
12526
12527         expandarg(&n, NULL, EXP_QUOTED);
12528         return stackblock();
12529 }
12530
12531 static inline int
12532 parser_eof(void)
12533 {
12534         return tokpushback && lasttoken == TEOF;
12535 }
12536
12537 /*
12538  * Execute a command or commands contained in a string.
12539  */
12540 static int
12541 evalstring(char *s, int flags)
12542 {
12543         struct jmploc *volatile savehandler;
12544         struct jmploc jmploc;
12545         int ex;
12546
12547         union node *n;
12548         struct stackmark smark;
12549         int status;
12550
12551         s = sstrdup(s);
12552         setinputstring(s);
12553         setstackmark(&smark);
12554
12555         status = 0;
12556         /* On exception inside execution loop, we must popfile().
12557          * Try interactively:
12558          *      readonly a=a
12559          *      command eval "a=b"  # throws "is read only" error
12560          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12561          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12562          */
12563         savehandler = exception_handler;
12564         ex = setjmp(jmploc.loc);
12565         if (ex)
12566                 goto out;
12567         exception_handler = &jmploc;
12568
12569         while ((n = parsecmd(0)) != NODE_EOF) {
12570                 int i;
12571
12572                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12573                 if (n)
12574                         status = i;
12575                 popstackmark(&smark);
12576                 if (evalskip)
12577                         break;
12578         }
12579  out:
12580         popstackmark(&smark);
12581         popfile();
12582         stunalloc(s);
12583
12584         exception_handler = savehandler;
12585         if (ex)
12586                 longjmp(exception_handler->loc, ex);
12587
12588         return status;
12589 }
12590
12591 /*
12592  * The eval command.
12593  */
12594 static int FAST_FUNC
12595 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12596 {
12597         char *p;
12598         char *concat;
12599
12600         if (argv[1]) {
12601                 p = argv[1];
12602                 argv += 2;
12603                 if (argv[0]) {
12604                         STARTSTACKSTR(concat);
12605                         for (;;) {
12606                                 concat = stack_putstr(p, concat);
12607                                 p = *argv++;
12608                                 if (p == NULL)
12609                                         break;
12610                                 STPUTC(' ', concat);
12611                         }
12612                         STPUTC('\0', concat);
12613                         p = grabstackstr(concat);
12614                 }
12615                 return evalstring(p, flags & EV_TESTED);
12616         }
12617         return 0;
12618 }
12619
12620 /*
12621  * Read and execute commands.
12622  * "Top" is nonzero for the top level command loop;
12623  * it turns on prompting if the shell is interactive.
12624  */
12625 static int
12626 cmdloop(int top)
12627 {
12628         union node *n;
12629         struct stackmark smark;
12630         int inter;
12631         int status = 0;
12632         int numeof = 0;
12633
12634         TRACE(("cmdloop(%d) called\n", top));
12635         for (;;) {
12636                 int skip;
12637
12638                 setstackmark(&smark);
12639 #if JOBS
12640                 if (doing_jobctl)
12641                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12642 #endif
12643                 inter = 0;
12644                 if (iflag && top) {
12645                         inter++;
12646                         chkmail();
12647                 }
12648                 n = parsecmd(inter);
12649 #if DEBUG
12650                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12651                         showtree(n);
12652 #endif
12653                 if (n == NODE_EOF) {
12654                         if (!top || numeof >= 50)
12655                                 break;
12656                         if (!stoppedjobs()) {
12657                                 if (!Iflag)
12658                                         break;
12659                                 out2str("\nUse \"exit\" to leave shell.\n");
12660                         }
12661                         numeof++;
12662                 } else if (nflag == 0) {
12663                         int i;
12664
12665                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12666                         job_warning >>= 1;
12667                         numeof = 0;
12668                         i = evaltree(n, 0);
12669                         if (n)
12670                                 status = i;
12671                 }
12672                 popstackmark(&smark);
12673                 skip = evalskip;
12674
12675                 if (skip) {
12676                         evalskip &= ~SKIPFUNC;
12677                         break;
12678                 }
12679         }
12680         return status;
12681 }
12682
12683 /*
12684  * Take commands from a file.  To be compatible we should do a path
12685  * search for the file, which is necessary to find sub-commands.
12686  */
12687 static char *
12688 find_dot_file(char *name)
12689 {
12690         char *fullname;
12691         const char *path = pathval();
12692         struct stat statb;
12693
12694         /* don't try this for absolute or relative paths */
12695         if (strchr(name, '/'))
12696                 return name;
12697
12698         while ((fullname = path_advance(&path, name)) != NULL) {
12699                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12700                         /*
12701                          * Don't bother freeing here, since it will
12702                          * be freed by the caller.
12703                          */
12704                         return fullname;
12705                 }
12706                 if (fullname != name)
12707                         stunalloc(fullname);
12708         }
12709
12710         /* not found in the PATH */
12711         ash_msg_and_raise_error("%s: not found", name);
12712         /* NOTREACHED */
12713 }
12714
12715 static int FAST_FUNC
12716 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12717 {
12718         /* "false; . empty_file; echo $?" should print 0, not 1: */
12719         int status = 0;
12720         char *fullname;
12721         char **argv;
12722         char *args_need_save;
12723         volatile struct shparam saveparam;
12724
12725 //???
12726 //      struct strlist *sp;
12727 //      for (sp = cmdenviron; sp; sp = sp->next)
12728 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12729
12730         nextopt(nullstr); /* handle possible "--" */
12731         argv = argptr;
12732
12733         if (!argv[0]) {
12734                 /* bash says: "bash: .: filename argument required" */
12735                 return 2; /* bash compat */
12736         }
12737
12738         /* This aborts if file isn't found, which is POSIXly correct.
12739          * bash returns exitcode 1 instead.
12740          */
12741         fullname = find_dot_file(argv[0]);
12742         argv++;
12743         args_need_save = argv[0];
12744         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12745                 int argc;
12746                 saveparam = shellparam;
12747                 shellparam.malloced = 0;
12748                 argc = 1;
12749                 while (argv[argc])
12750                         argc++;
12751                 shellparam.nparam = argc;
12752                 shellparam.p = argv;
12753         };
12754
12755         /* This aborts if file can't be opened, which is POSIXly correct.
12756          * bash returns exitcode 1 instead.
12757          */
12758         setinputfile(fullname, INPUT_PUSH_FILE);
12759         commandname = fullname;
12760         status = cmdloop(0);
12761         popfile();
12762
12763         if (args_need_save) {
12764                 freeparam(&shellparam);
12765                 shellparam = saveparam;
12766         };
12767
12768         return status;
12769 }
12770
12771 static int FAST_FUNC
12772 exitcmd(int argc UNUSED_PARAM, char **argv)
12773 {
12774         if (stoppedjobs())
12775                 return 0;
12776         if (argv[1])
12777                 exitstatus = number(argv[1]);
12778         raise_exception(EXEXIT);
12779         /* NOTREACHED */
12780 }
12781
12782 /*
12783  * Read a file containing shell functions.
12784  */
12785 static void
12786 readcmdfile(char *name)
12787 {
12788         setinputfile(name, INPUT_PUSH_FILE);
12789         cmdloop(0);
12790         popfile();
12791 }
12792
12793
12794 /* ============ find_command inplementation */
12795
12796 /*
12797  * Resolve a command name.  If you change this routine, you may have to
12798  * change the shellexec routine as well.
12799  */
12800 static void
12801 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12802 {
12803         struct tblentry *cmdp;
12804         int idx;
12805         int prev;
12806         char *fullname;
12807         struct stat statb;
12808         int e;
12809         int updatetbl;
12810         struct builtincmd *bcmd;
12811
12812         /* If name contains a slash, don't use PATH or hash table */
12813         if (strchr(name, '/') != NULL) {
12814                 entry->u.index = -1;
12815                 if (act & DO_ABS) {
12816                         while (stat(name, &statb) < 0) {
12817 #ifdef SYSV
12818                                 if (errno == EINTR)
12819                                         continue;
12820 #endif
12821                                 entry->cmdtype = CMDUNKNOWN;
12822                                 return;
12823                         }
12824                 }
12825                 entry->cmdtype = CMDNORMAL;
12826                 return;
12827         }
12828
12829 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12830
12831         updatetbl = (path == pathval());
12832         if (!updatetbl) {
12833                 act |= DO_ALTPATH;
12834                 if (strstr(path, "%builtin") != NULL)
12835                         act |= DO_ALTBLTIN;
12836         }
12837
12838         /* If name is in the table, check answer will be ok */
12839         cmdp = cmdlookup(name, 0);
12840         if (cmdp != NULL) {
12841                 int bit;
12842
12843                 switch (cmdp->cmdtype) {
12844                 default:
12845 #if DEBUG
12846                         abort();
12847 #endif
12848                 case CMDNORMAL:
12849                         bit = DO_ALTPATH;
12850                         break;
12851                 case CMDFUNCTION:
12852                         bit = DO_NOFUNC;
12853                         break;
12854                 case CMDBUILTIN:
12855                         bit = DO_ALTBLTIN;
12856                         break;
12857                 }
12858                 if (act & bit) {
12859                         updatetbl = 0;
12860                         cmdp = NULL;
12861                 } else if (cmdp->rehash == 0)
12862                         /* if not invalidated by cd, we're done */
12863                         goto success;
12864         }
12865
12866         /* If %builtin not in path, check for builtin next */
12867         bcmd = find_builtin(name);
12868         if (bcmd) {
12869                 if (IS_BUILTIN_REGULAR(bcmd))
12870                         goto builtin_success;
12871                 if (act & DO_ALTPATH) {
12872                         if (!(act & DO_ALTBLTIN))
12873                                 goto builtin_success;
12874                 } else if (builtinloc <= 0) {
12875                         goto builtin_success;
12876                 }
12877         }
12878
12879 #if ENABLE_FEATURE_SH_STANDALONE
12880         {
12881                 int applet_no = find_applet_by_name(name);
12882                 if (applet_no >= 0) {
12883                         entry->cmdtype = CMDNORMAL;
12884                         entry->u.index = -2 - applet_no;
12885                         return;
12886                 }
12887         }
12888 #endif
12889
12890         /* We have to search path. */
12891         prev = -1;              /* where to start */
12892         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12893                 if (cmdp->cmdtype == CMDBUILTIN)
12894                         prev = builtinloc;
12895                 else
12896                         prev = cmdp->param.index;
12897         }
12898
12899         e = ENOENT;
12900         idx = -1;
12901  loop:
12902         while ((fullname = path_advance(&path, name)) != NULL) {
12903                 stunalloc(fullname);
12904                 /* NB: code below will still use fullname
12905                  * despite it being "unallocated" */
12906                 idx++;
12907                 if (pathopt) {
12908                         if (prefix(pathopt, "builtin")) {
12909                                 if (bcmd)
12910                                         goto builtin_success;
12911                                 continue;
12912                         }
12913                         if ((act & DO_NOFUNC)
12914                          || !prefix(pathopt, "func")
12915                         ) {     /* ignore unimplemented options */
12916                                 continue;
12917                         }
12918                 }
12919                 /* if rehash, don't redo absolute path names */
12920                 if (fullname[0] == '/' && idx <= prev) {
12921                         if (idx < prev)
12922                                 continue;
12923                         TRACE(("searchexec \"%s\": no change\n", name));
12924                         goto success;
12925                 }
12926                 while (stat(fullname, &statb) < 0) {
12927 #ifdef SYSV
12928                         if (errno == EINTR)
12929                                 continue;
12930 #endif
12931                         if (errno != ENOENT && errno != ENOTDIR)
12932                                 e = errno;
12933                         goto loop;
12934                 }
12935                 e = EACCES;     /* if we fail, this will be the error */
12936                 if (!S_ISREG(statb.st_mode))
12937                         continue;
12938                 if (pathopt) {          /* this is a %func directory */
12939                         stalloc(strlen(fullname) + 1);
12940                         /* NB: stalloc will return space pointed by fullname
12941                          * (because we don't have any intervening allocations
12942                          * between stunalloc above and this stalloc) */
12943                         readcmdfile(fullname);
12944                         cmdp = cmdlookup(name, 0);
12945                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12946                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12947                         stunalloc(fullname);
12948                         goto success;
12949                 }
12950                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12951                 if (!updatetbl) {
12952                         entry->cmdtype = CMDNORMAL;
12953                         entry->u.index = idx;
12954                         return;
12955                 }
12956                 INT_OFF;
12957                 cmdp = cmdlookup(name, 1);
12958                 cmdp->cmdtype = CMDNORMAL;
12959                 cmdp->param.index = idx;
12960                 INT_ON;
12961                 goto success;
12962         }
12963
12964         /* We failed.  If there was an entry for this command, delete it */
12965         if (cmdp && updatetbl)
12966                 delete_cmd_entry();
12967         if (act & DO_ERR)
12968                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12969         entry->cmdtype = CMDUNKNOWN;
12970         return;
12971
12972  builtin_success:
12973         if (!updatetbl) {
12974                 entry->cmdtype = CMDBUILTIN;
12975                 entry->u.cmd = bcmd;
12976                 return;
12977         }
12978         INT_OFF;
12979         cmdp = cmdlookup(name, 1);
12980         cmdp->cmdtype = CMDBUILTIN;
12981         cmdp->param.cmd = bcmd;
12982         INT_ON;
12983  success:
12984         cmdp->rehash = 0;
12985         entry->cmdtype = cmdp->cmdtype;
12986         entry->u = cmdp->param;
12987 }
12988
12989
12990 /*
12991  * The trap builtin.
12992  */
12993 static int FAST_FUNC
12994 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12995 {
12996         char *action;
12997         char **ap;
12998         int signo, exitcode;
12999
13000         nextopt(nullstr);
13001         ap = argptr;
13002         if (!*ap) {
13003                 for (signo = 0; signo < NSIG; signo++) {
13004                         char *tr = trap_ptr[signo];
13005                         if (tr) {
13006                                 /* note: bash adds "SIG", but only if invoked
13007                                  * as "bash". If called as "sh", or if set -o posix,
13008                                  * then it prints short signal names.
13009                                  * We are printing short names: */
13010                                 out1fmt("trap -- %s %s\n",
13011                                                 single_quote(tr),
13012                                                 get_signame(signo));
13013                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13014                  * In this case, we will exit very soon, no need to free(). */
13015                                 /* if (trap_ptr != trap && tp[0]) */
13016                                 /*      free(tr); */
13017                         }
13018                 }
13019                 /*
13020                 if (trap_ptr != trap) {
13021                         free(trap_ptr);
13022                         trap_ptr = trap;
13023                 }
13024                 */
13025                 return 0;
13026         }
13027
13028         /* Why the second check?
13029          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13030          * In this case, NUM is signal no, not an action.
13031          */
13032         action = NULL;
13033         if (ap[1] && !is_number(ap[0]))
13034                 action = *ap++;
13035
13036         exitcode = 0;
13037         while (*ap) {
13038                 signo = get_signum(*ap);
13039                 if (signo < 0) {
13040                         /* Mimic bash message exactly */
13041                         ash_msg("%s: invalid signal specification", *ap);
13042                         exitcode = 1;
13043                         goto next;
13044                 }
13045                 INT_OFF;
13046                 if (action) {
13047                         if (LONE_DASH(action))
13048                                 action = NULL;
13049                         else {
13050                                 if (action[0]) /* not NULL and not "" and not "-" */
13051                                         may_have_traps = 1;
13052                                 action = ckstrdup(action);
13053                         }
13054                 }
13055                 free(trap[signo]);
13056                 trap[signo] = action;
13057                 if (signo != 0)
13058                         setsignal(signo);
13059                 INT_ON;
13060  next:
13061                 ap++;
13062         }
13063         return exitcode;
13064 }
13065
13066
13067 /* ============ Builtins */
13068
13069 #if ENABLE_ASH_HELP
13070 static int FAST_FUNC
13071 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13072 {
13073         unsigned col;
13074         unsigned i;
13075
13076         out1fmt(
13077                 "Built-in commands:\n"
13078                 "------------------\n");
13079         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13080                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13081                                         builtintab[i].name + 1);
13082                 if (col > 60) {
13083                         out1fmt("\n");
13084                         col = 0;
13085                 }
13086         }
13087 # if ENABLE_FEATURE_SH_STANDALONE
13088         {
13089                 const char *a = applet_names;
13090                 while (*a) {
13091                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13092                         if (col > 60) {
13093                                 out1fmt("\n");
13094                                 col = 0;
13095                         }
13096                         while (*a++ != '\0')
13097                                 continue;
13098                 }
13099         }
13100 # endif
13101         newline_and_flush(stdout);
13102         return EXIT_SUCCESS;
13103 }
13104 #endif
13105
13106 #if MAX_HISTORY
13107 static int FAST_FUNC
13108 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13109 {
13110         show_history(line_input_state);
13111         return EXIT_SUCCESS;
13112 }
13113 #endif
13114
13115 /*
13116  * The export and readonly commands.
13117  */
13118 static int FAST_FUNC
13119 exportcmd(int argc UNUSED_PARAM, char **argv)
13120 {
13121         struct var *vp;
13122         char *name;
13123         const char *p;
13124         char **aptr;
13125         char opt;
13126         int flag;
13127         int flag_off;
13128
13129         /* "readonly" in bash accepts, but ignores -n.
13130          * We do the same: it saves a conditional in nextopt's param.
13131          */
13132         flag_off = 0;
13133         while ((opt = nextopt("np")) != '\0') {
13134                 if (opt == 'n')
13135                         flag_off = VEXPORT;
13136         }
13137         flag = VEXPORT;
13138         if (argv[0][0] == 'r') {
13139                 flag = VREADONLY;
13140                 flag_off = 0; /* readonly ignores -n */
13141         }
13142         flag_off = ~flag_off;
13143
13144         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13145         {
13146                 aptr = argptr;
13147                 name = *aptr;
13148                 if (name) {
13149                         do {
13150                                 p = strchr(name, '=');
13151                                 if (p != NULL) {
13152                                         p++;
13153                                 } else {
13154                                         vp = *findvar(hashvar(name), name);
13155                                         if (vp) {
13156                                                 vp->flags = ((vp->flags | flag) & flag_off);
13157                                                 continue;
13158                                         }
13159                                 }
13160                                 setvar(name, p, (flag & flag_off));
13161                         } while ((name = *++aptr) != NULL);
13162                         return 0;
13163                 }
13164         }
13165
13166         /* No arguments. Show the list of exported or readonly vars.
13167          * -n is ignored.
13168          */
13169         showvars(argv[0], flag, 0);
13170         return 0;
13171 }
13172
13173 /*
13174  * Delete a function if it exists.
13175  */
13176 static void
13177 unsetfunc(const char *name)
13178 {
13179         struct tblentry *cmdp;
13180
13181         cmdp = cmdlookup(name, 0);
13182         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13183                 delete_cmd_entry();
13184 }
13185
13186 /*
13187  * The unset builtin command.  We unset the function before we unset the
13188  * variable to allow a function to be unset when there is a readonly variable
13189  * with the same name.
13190  */
13191 static int FAST_FUNC
13192 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13193 {
13194         char **ap;
13195         int i;
13196         int flag = 0;
13197
13198         while ((i = nextopt("vf")) != 0) {
13199                 flag = i;
13200         }
13201
13202         for (ap = argptr; *ap; ap++) {
13203                 if (flag != 'f') {
13204                         unsetvar(*ap);
13205                         continue;
13206                 }
13207                 if (flag != 'v')
13208                         unsetfunc(*ap);
13209         }
13210         return 0;
13211 }
13212
13213 static const unsigned char timescmd_str[] ALIGN1 = {
13214         ' ',  offsetof(struct tms, tms_utime),
13215         '\n', offsetof(struct tms, tms_stime),
13216         ' ',  offsetof(struct tms, tms_cutime),
13217         '\n', offsetof(struct tms, tms_cstime),
13218         0
13219 };
13220 static int FAST_FUNC
13221 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13222 {
13223         unsigned long clk_tck, s, t;
13224         const unsigned char *p;
13225         struct tms buf;
13226
13227         clk_tck = bb_clk_tck();
13228         times(&buf);
13229
13230         p = timescmd_str;
13231         do {
13232                 t = *(clock_t *)(((char *) &buf) + p[1]);
13233                 s = t / clk_tck;
13234                 t = t % clk_tck;
13235                 out1fmt("%lum%lu.%03lus%c",
13236                         s / 60, s % 60,
13237                         (t * 1000) / clk_tck,
13238                         p[0]);
13239                 p += 2;
13240         } while (*p);
13241
13242         return 0;
13243 }
13244
13245 #if ENABLE_FEATURE_SH_MATH
13246 /*
13247  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13248  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13249  *
13250  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13251  */
13252 static int FAST_FUNC
13253 letcmd(int argc UNUSED_PARAM, char **argv)
13254 {
13255         arith_t i;
13256
13257         argv++;
13258         if (!*argv)
13259                 ash_msg_and_raise_error("expression expected");
13260         do {
13261                 i = ash_arith(*argv);
13262         } while (*++argv);
13263
13264         return !i;
13265 }
13266 #endif
13267
13268 /*
13269  * The read builtin. Options:
13270  *      -r              Do not interpret '\' specially
13271  *      -s              Turn off echo (tty only)
13272  *      -n NCHARS       Read NCHARS max
13273  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13274  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13275  *      -u FD           Read from given FD instead of fd 0
13276  * This uses unbuffered input, which may be avoidable in some cases.
13277  * TODO: bash also has:
13278  *      -a ARRAY        Read into array[0],[1],etc
13279  *      -d DELIM        End on DELIM char, not newline
13280  *      -e              Use line editing (tty only)
13281  */
13282 static int FAST_FUNC
13283 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13284 {
13285         char *opt_n = NULL;
13286         char *opt_p = NULL;
13287         char *opt_t = NULL;
13288         char *opt_u = NULL;
13289         int read_flags = 0;
13290         const char *r;
13291         int i;
13292
13293         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13294                 switch (i) {
13295                 case 'p':
13296                         opt_p = optionarg;
13297                         break;
13298                 case 'n':
13299                         opt_n = optionarg;
13300                         break;
13301                 case 's':
13302                         read_flags |= BUILTIN_READ_SILENT;
13303                         break;
13304                 case 't':
13305                         opt_t = optionarg;
13306                         break;
13307                 case 'r':
13308                         read_flags |= BUILTIN_READ_RAW;
13309                         break;
13310                 case 'u':
13311                         opt_u = optionarg;
13312                         break;
13313                 default:
13314                         break;
13315                 }
13316         }
13317
13318         /* "read -s" needs to save/restore termios, can't allow ^C
13319          * to jump out of it.
13320          */
13321  again:
13322         INT_OFF;
13323         r = shell_builtin_read(setvar0,
13324                 argptr,
13325                 bltinlookup("IFS"), /* can be NULL */
13326                 read_flags,
13327                 opt_n,
13328                 opt_p,
13329                 opt_t,
13330                 opt_u
13331         );
13332         INT_ON;
13333
13334         if ((uintptr_t)r == 1 && errno == EINTR) {
13335                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13336                 if (pending_sig == 0)
13337                         goto again;
13338         }
13339
13340         if ((uintptr_t)r > 1)
13341                 ash_msg_and_raise_error(r);
13342
13343         return (uintptr_t)r;
13344 }
13345
13346 static int FAST_FUNC
13347 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13348 {
13349         static const char permuser[3] ALIGN1 = "ogu";
13350
13351         mode_t mask;
13352         int symbolic_mode = 0;
13353
13354         while (nextopt("S") != '\0') {
13355                 symbolic_mode = 1;
13356         }
13357
13358         INT_OFF;
13359         mask = umask(0);
13360         umask(mask);
13361         INT_ON;
13362
13363         if (*argptr == NULL) {
13364                 if (symbolic_mode) {
13365                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13366                         char *p = buf;
13367                         int i;
13368
13369                         i = 2;
13370                         for (;;) {
13371                                 *p++ = ',';
13372                                 *p++ = permuser[i];
13373                                 *p++ = '=';
13374                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13375                                 if (!(mask & 0400)) *p++ = 'r';
13376                                 if (!(mask & 0200)) *p++ = 'w';
13377                                 if (!(mask & 0100)) *p++ = 'x';
13378                                 mask <<= 3;
13379                                 if (--i < 0)
13380                                         break;
13381                         }
13382                         *p = '\0';
13383                         puts(buf + 1);
13384                 } else {
13385                         out1fmt("%04o\n", mask);
13386                 }
13387         } else {
13388                 char *modestr = *argptr;
13389                 /* numeric umasks are taken as-is */
13390                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13391                 if (!isdigit(modestr[0]))
13392                         mask ^= 0777;
13393                 mask = bb_parse_mode(modestr, mask);
13394                 if ((unsigned)mask > 0777) {
13395                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13396                 }
13397                 if (!isdigit(modestr[0]))
13398                         mask ^= 0777;
13399                 umask(mask);
13400         }
13401         return 0;
13402 }
13403
13404 static int FAST_FUNC
13405 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13406 {
13407         return shell_builtin_ulimit(argv);
13408 }
13409
13410 /* ============ main() and helpers */
13411
13412 /*
13413  * Called to exit the shell.
13414  */
13415 static void
13416 exitshell(void)
13417 {
13418         struct jmploc loc;
13419         char *p;
13420         int status;
13421
13422 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13423         save_history(line_input_state);
13424 #endif
13425         status = exitstatus;
13426         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13427         if (setjmp(loc.loc)) {
13428                 if (exception_type == EXEXIT)
13429                         status = exitstatus;
13430                 goto out;
13431         }
13432         exception_handler = &loc;
13433         p = trap[0];
13434         if (p) {
13435                 trap[0] = NULL;
13436                 evalskip = 0;
13437                 evalstring(p, 0);
13438                 /*free(p); - we'll exit soon */
13439         }
13440  out:
13441         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13442          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13443          */
13444         setjobctl(0);
13445         flush_stdout_stderr();
13446         _exit(status);
13447         /* NOTREACHED */
13448 }
13449
13450 static void
13451 init(void)
13452 {
13453         /* we will never free this */
13454         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13455
13456         sigmode[SIGCHLD - 1] = S_DFL;
13457         setsignal(SIGCHLD);
13458
13459         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13460          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13461          */
13462         signal(SIGHUP, SIG_DFL);
13463
13464         {
13465                 char **envp;
13466                 const char *p;
13467                 struct stat st1, st2;
13468
13469                 initvar();
13470                 for (envp = environ; envp && *envp; envp++) {
13471                         p = endofname(*envp);
13472                         if (p != *envp && *p == '=') {
13473                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13474                         }
13475                 }
13476
13477                 setvareq((char*)defoptindvar, VTEXTFIXED);
13478
13479                 setvar0("PPID", utoa(getppid()));
13480 #if BASH_SHLVL_VAR
13481                 p = lookupvar("SHLVL");
13482                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13483 #endif
13484 #if BASH_HOSTNAME_VAR
13485                 if (!lookupvar("HOSTNAME")) {
13486                         struct utsname uts;
13487                         uname(&uts);
13488                         setvar0("HOSTNAME", uts.nodename);
13489                 }
13490 #endif
13491                 p = lookupvar("PWD");
13492                 if (p) {
13493                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13494                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13495                         ) {
13496                                 p = NULL;
13497                         }
13498                 }
13499                 setpwd(p, 0);
13500         }
13501 }
13502
13503
13504 //usage:#define ash_trivial_usage
13505 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13506 //usage:#define ash_full_usage "\n\n"
13507 //usage:        "Unix shell interpreter"
13508
13509 /*
13510  * Process the shell command line arguments.
13511  */
13512 static void
13513 procargs(char **argv)
13514 {
13515         int i;
13516         const char *xminusc;
13517         char **xargv;
13518
13519         xargv = argv;
13520         arg0 = xargv[0];
13521         /* if (xargv[0]) - mmm, this is always true! */
13522                 xargv++;
13523         for (i = 0; i < NOPTS; i++)
13524                 optlist[i] = 2;
13525         argptr = xargv;
13526         if (options(/*cmdline:*/ 1)) {
13527                 /* it already printed err message */
13528                 raise_exception(EXERROR);
13529         }
13530         xargv = argptr;
13531         xminusc = minusc;
13532         if (*xargv == NULL) {
13533                 if (xminusc)
13534                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13535                 sflag = 1;
13536         }
13537         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13538                 iflag = 1;
13539         if (mflag == 2)
13540                 mflag = iflag;
13541         for (i = 0; i < NOPTS; i++)
13542                 if (optlist[i] == 2)
13543                         optlist[i] = 0;
13544 #if DEBUG == 2
13545         debug = 1;
13546 #endif
13547         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13548         if (xminusc) {
13549                 minusc = *xargv++;
13550                 if (*xargv)
13551                         goto setarg0;
13552         } else if (!sflag) {
13553                 setinputfile(*xargv, 0);
13554  setarg0:
13555                 arg0 = *xargv++;
13556                 commandname = arg0;
13557         }
13558
13559         shellparam.p = xargv;
13560 #if ENABLE_ASH_GETOPTS
13561         shellparam.optind = 1;
13562         shellparam.optoff = -1;
13563 #endif
13564         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13565         while (*xargv) {
13566                 shellparam.nparam++;
13567                 xargv++;
13568         }
13569         optschanged();
13570 }
13571
13572 /*
13573  * Read /etc/profile, ~/.profile, $ENV.
13574  */
13575 static void
13576 read_profile(const char *name)
13577 {
13578         name = expandstr(name, DQSYNTAX);
13579         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13580                 return;
13581         cmdloop(0);
13582         popfile();
13583 }
13584
13585 /*
13586  * This routine is called when an error or an interrupt occurs in an
13587  * interactive shell and control is returned to the main command loop.
13588  * (In dash, this function is auto-generated by build machinery).
13589  */
13590 static void
13591 reset(void)
13592 {
13593         /* from eval.c: */
13594         evalskip = 0;
13595         loopnest = 0;
13596
13597         /* from expand.c: */
13598         ifsfree();
13599
13600         /* from input.c: */
13601         g_parsefile->left_in_buffer = 0;
13602         g_parsefile->left_in_line = 0;      /* clear input buffer */
13603         popallfiles();
13604
13605         /* from redir.c: */
13606         unwindredir(NULL);
13607
13608         /* from var.c: */
13609         unwindlocalvars(NULL);
13610 }
13611
13612 #if PROFILE
13613 static short profile_buf[16384];
13614 extern int etext();
13615 #endif
13616
13617 /*
13618  * Main routine.  We initialize things, parse the arguments, execute
13619  * profiles if we're a login shell, and then call cmdloop to execute
13620  * commands.  The setjmp call sets up the location to jump to when an
13621  * exception occurs.  When an exception occurs the variable "state"
13622  * is used to figure out how far we had gotten.
13623  */
13624 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13625 int ash_main(int argc UNUSED_PARAM, char **argv)
13626 {
13627         volatile smallint state;
13628         struct jmploc jmploc;
13629         struct stackmark smark;
13630
13631         /* Initialize global data */
13632         INIT_G_misc();
13633         INIT_G_memstack();
13634         INIT_G_var();
13635 #if ENABLE_ASH_ALIAS
13636         INIT_G_alias();
13637 #endif
13638         INIT_G_cmdtable();
13639
13640 #if PROFILE
13641         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13642 #endif
13643
13644 #if ENABLE_FEATURE_EDITING
13645         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13646 #endif
13647         state = 0;
13648         if (setjmp(jmploc.loc)) {
13649                 smallint e;
13650                 smallint s;
13651
13652                 reset();
13653
13654                 e = exception_type;
13655                 s = state;
13656                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13657                         exitshell();
13658                 }
13659                 if (e == EXINT) {
13660                         newline_and_flush(stderr);
13661                 }
13662
13663                 popstackmark(&smark);
13664                 FORCE_INT_ON; /* enable interrupts */
13665                 if (s == 1)
13666                         goto state1;
13667                 if (s == 2)
13668                         goto state2;
13669                 if (s == 3)
13670                         goto state3;
13671                 goto state4;
13672         }
13673         exception_handler = &jmploc;
13674         rootpid = getpid();
13675
13676         init();
13677         setstackmark(&smark);
13678         procargs(argv);
13679 #if DEBUG
13680         TRACE(("Shell args: "));
13681         trace_puts_args(argv);
13682 #endif
13683
13684         if (argv[0] && argv[0][0] == '-')
13685                 isloginsh = 1;
13686         if (isloginsh) {
13687                 const char *hp;
13688
13689                 state = 1;
13690                 read_profile("/etc/profile");
13691  state1:
13692                 state = 2;
13693                 hp = lookupvar("HOME");
13694                 if (hp)
13695                         read_profile("$HOME/.profile");
13696         }
13697  state2:
13698         state = 3;
13699         if (
13700 #ifndef linux
13701          getuid() == geteuid() && getgid() == getegid() &&
13702 #endif
13703          iflag
13704         ) {
13705                 const char *shinit = lookupvar("ENV");
13706                 if (shinit != NULL && *shinit != '\0')
13707                         read_profile(shinit);
13708         }
13709         popstackmark(&smark);
13710  state3:
13711         state = 4;
13712         if (minusc) {
13713                 /* evalstring pushes parsefile stack.
13714                  * Ensure we don't falsely claim that 0 (stdin)
13715                  * is one of stacked source fds.
13716                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13717                 // if (!sflag) g_parsefile->pf_fd = -1;
13718                 // ^^ not necessary since now we special-case fd 0
13719                 // in is_hidden_fd() to not be considered "hidden fd"
13720                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13721         }
13722
13723         if (sflag || minusc == NULL) {
13724 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13725                 if (iflag) {
13726                         const char *hp = lookupvar("HISTFILE");
13727                         if (!hp) {
13728                                 hp = lookupvar("HOME");
13729                                 if (hp) {
13730                                         INT_OFF;
13731                                         hp = concat_path_file(hp, ".ash_history");
13732                                         setvar0("HISTFILE", hp);
13733                                         free((char*)hp);
13734                                         INT_ON;
13735                                         hp = lookupvar("HISTFILE");
13736                                 }
13737                         }
13738                         if (hp)
13739                                 line_input_state->hist_file = hp;
13740 # if ENABLE_FEATURE_SH_HISTFILESIZE
13741                         hp = lookupvar("HISTFILESIZE");
13742                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13743 # endif
13744                 }
13745 #endif
13746  state4: /* XXX ??? - why isn't this before the "if" statement */
13747                 cmdloop(1);
13748         }
13749 #if PROFILE
13750         monitor(0);
13751 #endif
13752 #ifdef GPROF
13753         {
13754                 extern void _mcleanup(void);
13755                 _mcleanup();
13756         }
13757 #endif
13758         TRACE(("End of main reached\n"));
13759         exitshell();
13760         /* NOTREACHED */
13761 }
13762
13763
13764 /*-
13765  * Copyright (c) 1989, 1991, 1993, 1994
13766  *      The Regents of the University of California.  All rights reserved.
13767  *
13768  * This code is derived from software contributed to Berkeley by
13769  * Kenneth Almquist.
13770  *
13771  * Redistribution and use in source and binary forms, with or without
13772  * modification, are permitted provided that the following conditions
13773  * are met:
13774  * 1. Redistributions of source code must retain the above copyright
13775  *    notice, this list of conditions and the following disclaimer.
13776  * 2. Redistributions in binary form must reproduce the above copyright
13777  *    notice, this list of conditions and the following disclaimer in the
13778  *    documentation and/or other materials provided with the distribution.
13779  * 3. Neither the name of the University nor the names of its contributors
13780  *    may be used to endorse or promote products derived from this software
13781  *    without specific prior written permission.
13782  *
13783  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13784  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13785  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13786  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13787  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13788  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13789  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13790  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13791  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13792  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13793  * SUCH DAMAGE.
13794  */