ash: remove REDIR_SAVEFD2
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps, int syntax_type);
2492 /* Values for syntax param */
2493 #define BASESYNTAX 0    /* not in quotes */
2494 #define DQSYNTAX   1    /* in double quotes */
2495 #define SQSYNTAX   2    /* in single quotes */
2496 #define ARISYNTAX  3    /* in arithmetic */
2497 #if ENABLE_ASH_EXPAND_PRMT
2498 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2499 #endif
2500 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2501
2502 /*
2503  * called by editline -- any expansions to the prompt should be added here.
2504  */
2505 static void
2506 setprompt_if(smallint do_set, int whichprompt)
2507 {
2508         const char *prompt;
2509         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2510
2511         if (!do_set)
2512                 return;
2513
2514         needprompt = 0;
2515
2516         switch (whichprompt) {
2517         case 1:
2518                 prompt = ps1val();
2519                 break;
2520         case 2:
2521                 prompt = ps2val();
2522                 break;
2523         default:                        /* 0 */
2524                 prompt = nullstr;
2525         }
2526 #if ENABLE_ASH_EXPAND_PRMT
2527         pushstackmark(&smark, stackblocksize());
2528         putprompt(expandstr(prompt, PSSYNTAX));
2529         popstackmark(&smark);
2530 #else
2531         putprompt(prompt);
2532 #endif
2533 }
2534
2535
2536 /* ============ The cd and pwd commands */
2537
2538 #define CD_PHYSICAL 1
2539 #define CD_PRINT 2
2540
2541 static int
2542 cdopt(void)
2543 {
2544         int flags = 0;
2545         int i, j;
2546
2547         j = 'L';
2548         while ((i = nextopt("LP")) != '\0') {
2549                 if (i != j) {
2550                         flags ^= CD_PHYSICAL;
2551                         j = i;
2552                 }
2553         }
2554
2555         return flags;
2556 }
2557
2558 /*
2559  * Update curdir (the name of the current directory) in response to a
2560  * cd command.
2561  */
2562 static const char *
2563 updatepwd(const char *dir)
2564 {
2565         char *new;
2566         char *p;
2567         char *cdcomppath;
2568         const char *lim;
2569
2570         cdcomppath = sstrdup(dir);
2571         STARTSTACKSTR(new);
2572         if (*dir != '/') {
2573                 if (curdir == nullstr)
2574                         return 0;
2575                 new = stack_putstr(curdir, new);
2576         }
2577         new = makestrspace(strlen(dir) + 2, new);
2578         lim = (char *)stackblock() + 1;
2579         if (*dir != '/') {
2580                 if (new[-1] != '/')
2581                         USTPUTC('/', new);
2582                 if (new > lim && *lim == '/')
2583                         lim++;
2584         } else {
2585                 USTPUTC('/', new);
2586                 cdcomppath++;
2587                 if (dir[1] == '/' && dir[2] != '/') {
2588                         USTPUTC('/', new);
2589                         cdcomppath++;
2590                         lim++;
2591                 }
2592         }
2593         p = strtok(cdcomppath, "/");
2594         while (p) {
2595                 switch (*p) {
2596                 case '.':
2597                         if (p[1] == '.' && p[2] == '\0') {
2598                                 while (new > lim) {
2599                                         STUNPUTC(new);
2600                                         if (new[-1] == '/')
2601                                                 break;
2602                                 }
2603                                 break;
2604                         }
2605                         if (p[1] == '\0')
2606                                 break;
2607                         /* fall through */
2608                 default:
2609                         new = stack_putstr(p, new);
2610                         USTPUTC('/', new);
2611                 }
2612                 p = strtok(NULL, "/");
2613         }
2614         if (new > lim)
2615                 STUNPUTC(new);
2616         *new = 0;
2617         return stackblock();
2618 }
2619
2620 /*
2621  * Find out what the current directory is. If we already know the current
2622  * directory, this routine returns immediately.
2623  */
2624 static char *
2625 getpwd(void)
2626 {
2627         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2628         return dir ? dir : nullstr;
2629 }
2630
2631 static void
2632 setpwd(const char *val, int setold)
2633 {
2634         char *oldcur, *dir;
2635
2636         oldcur = dir = curdir;
2637
2638         if (setold) {
2639                 setvar("OLDPWD", oldcur, VEXPORT);
2640         }
2641         INT_OFF;
2642         if (physdir != nullstr) {
2643                 if (physdir != oldcur)
2644                         free(physdir);
2645                 physdir = nullstr;
2646         }
2647         if (oldcur == val || !val) {
2648                 char *s = getpwd();
2649                 physdir = s;
2650                 if (!val)
2651                         dir = s;
2652         } else
2653                 dir = ckstrdup(val);
2654         if (oldcur != dir && oldcur != nullstr) {
2655                 free(oldcur);
2656         }
2657         curdir = dir;
2658         INT_ON;
2659         setvar("PWD", dir, VEXPORT);
2660 }
2661
2662 static void hashcd(void);
2663
2664 /*
2665  * Actually do the chdir.  We also call hashcd to let other routines
2666  * know that the current directory has changed.
2667  */
2668 static int
2669 docd(const char *dest, int flags)
2670 {
2671         const char *dir = NULL;
2672         int err;
2673
2674         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2675
2676         INT_OFF;
2677         if (!(flags & CD_PHYSICAL)) {
2678                 dir = updatepwd(dest);
2679                 if (dir)
2680                         dest = dir;
2681         }
2682         err = chdir(dest);
2683         if (err)
2684                 goto out;
2685         setpwd(dir, 1);
2686         hashcd();
2687  out:
2688         INT_ON;
2689         return err;
2690 }
2691
2692 static int FAST_FUNC
2693 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2694 {
2695         const char *dest;
2696         const char *path;
2697         const char *p;
2698         char c;
2699         struct stat statb;
2700         int flags;
2701
2702         flags = cdopt();
2703         dest = *argptr;
2704         if (!dest)
2705                 dest = bltinlookup("HOME");
2706         else if (LONE_DASH(dest)) {
2707                 dest = bltinlookup("OLDPWD");
2708                 flags |= CD_PRINT;
2709         }
2710         if (!dest)
2711                 dest = nullstr;
2712         if (*dest == '/')
2713                 goto step6;
2714         if (*dest == '.') {
2715                 c = dest[1];
2716  dotdot:
2717                 switch (c) {
2718                 case '\0':
2719                 case '/':
2720                         goto step6;
2721                 case '.':
2722                         c = dest[2];
2723                         if (c != '.')
2724                                 goto dotdot;
2725                 }
2726         }
2727         if (!*dest)
2728                 dest = ".";
2729         path = bltinlookup("CDPATH");
2730         while (path) {
2731                 c = *path;
2732                 p = path_advance(&path, dest);
2733                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2734                         if (c && c != ':')
2735                                 flags |= CD_PRINT;
2736  docd:
2737                         if (!docd(p, flags))
2738                                 goto out;
2739                         goto err;
2740                 }
2741         }
2742
2743  step6:
2744         p = dest;
2745         goto docd;
2746
2747  err:
2748         ash_msg_and_raise_error("can't cd to %s", dest);
2749         /* NOTREACHED */
2750  out:
2751         if (flags & CD_PRINT)
2752                 out1fmt("%s\n", curdir);
2753         return 0;
2754 }
2755
2756 static int FAST_FUNC
2757 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2758 {
2759         int flags;
2760         const char *dir = curdir;
2761
2762         flags = cdopt();
2763         if (flags) {
2764                 if (physdir == nullstr)
2765                         setpwd(dir, 0);
2766                 dir = physdir;
2767         }
2768         out1fmt("%s\n", dir);
2769         return 0;
2770 }
2771
2772
2773 /* ============ ... */
2774
2775
2776 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2777
2778 /* Syntax classes */
2779 #define CWORD     0             /* character is nothing special */
2780 #define CNL       1             /* newline character */
2781 #define CBACK     2             /* a backslash character */
2782 #define CSQUOTE   3             /* single quote */
2783 #define CDQUOTE   4             /* double quote */
2784 #define CENDQUOTE 5             /* a terminating quote */
2785 #define CBQUOTE   6             /* backwards single quote */
2786 #define CVAR      7             /* a dollar sign */
2787 #define CENDVAR   8             /* a '}' character */
2788 #define CLP       9             /* a left paren in arithmetic */
2789 #define CRP      10             /* a right paren in arithmetic */
2790 #define CENDFILE 11             /* end of file */
2791 #define CCTL     12             /* like CWORD, except it must be escaped */
2792 #define CSPCL    13             /* these terminate a word */
2793 #define CIGN     14             /* character should be ignored */
2794
2795 #define PEOF     256
2796 #if ENABLE_ASH_ALIAS
2797 # define PEOA    257
2798 #endif
2799
2800 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2801
2802 #if ENABLE_FEATURE_SH_MATH
2803 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2804 #else
2805 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2806 #endif
2807 static const uint16_t S_I_T[] ALIGN2 = {
2808 #if ENABLE_ASH_ALIAS
2809         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2810 #endif
2811         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2812         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2813         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2814         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2815         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2816         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2817         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2818         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2819         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2820         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2821         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2822 #if !USE_SIT_FUNCTION
2823         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2824         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2825         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2826 #endif
2827 #undef SIT_ITEM
2828 };
2829 /* Constants below must match table above */
2830 enum {
2831 #if ENABLE_ASH_ALIAS
2832         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2833 #endif
2834         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2835         CNL_CNL_CNL_CNL                    , /*  2 */
2836         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2837         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2838         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2839         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2840         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2841         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2842         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2843         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2844         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2845         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2846         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2847         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2848 };
2849
2850 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2851  * caller must ensure proper cast on it if c is *char_ptr!
2852  */
2853 #if USE_SIT_FUNCTION
2854
2855 static int
2856 SIT(int c, int syntax)
2857 {
2858         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2859         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2860         /*
2861          * This causes '/' to be prepended with CTLESC in dquoted string,
2862          * making "./file"* treated incorrectly because we feed
2863          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2864          * The "homegrown" glob implementation is okay with that,
2865          * but glibc one isn't. With '/' always treated as CWORD,
2866          * both work fine.
2867          */
2868 # if ENABLE_ASH_ALIAS
2869         static const uint8_t syntax_index_table[] ALIGN1 = {
2870                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2871                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2872                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2873                 11, 3                           /* "}~" */
2874         };
2875 # else
2876         static const uint8_t syntax_index_table[] ALIGN1 = {
2877                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2878                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2879                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2880                 10, 2                           /* "}~" */
2881         };
2882 # endif
2883         const char *s;
2884         int indx;
2885
2886         if (c == PEOF)
2887                 return CENDFILE;
2888 # if ENABLE_ASH_ALIAS
2889         if (c == PEOA)
2890                 indx = 0;
2891         else
2892 # endif
2893         {
2894                 /* Cast is purely for paranoia here,
2895                  * just in case someone passed signed char to us */
2896                 if ((unsigned char)c >= CTL_FIRST
2897                  && (unsigned char)c <= CTL_LAST
2898                 ) {
2899                         return CCTL;
2900                 }
2901                 s = strchrnul(spec_symbls, c);
2902                 if (*s == '\0')
2903                         return CWORD;
2904                 indx = syntax_index_table[s - spec_symbls];
2905         }
2906         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2907 }
2908
2909 #else   /* !USE_SIT_FUNCTION */
2910
2911 static const uint8_t syntax_index_table[] ALIGN1 = {
2912         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2913         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2923         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2924         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2946         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2947         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2948         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2950         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2952         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2953         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2954         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2955         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2956         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2958         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2960 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2961         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2973         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2974         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2975         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2978         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3006         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3007         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3008         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3009         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3011         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3039         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3040         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3041         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3042         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3043         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3044         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3045         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3046         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3047         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3048         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3049         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3050         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3051         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3170         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3171 # if ENABLE_ASH_ALIAS
3172         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3173 # endif
3174 };
3175
3176 #if 1
3177 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3178 #else /* debug version, caught one signed char bug */
3179 # define SIT(c, syntax) \
3180         ({ \
3181                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3182                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3183                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3184                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3185                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3186         })
3187 #endif
3188
3189 #endif  /* !USE_SIT_FUNCTION */
3190
3191
3192 /* ============ Alias handling */
3193
3194 #if ENABLE_ASH_ALIAS
3195
3196 #define ALIASINUSE 1
3197 #define ALIASDEAD  2
3198
3199 struct alias {
3200         struct alias *next;
3201         char *name;
3202         char *val;
3203         int flag;
3204 };
3205
3206
3207 static struct alias **atab; // [ATABSIZE];
3208 #define INIT_G_alias() do { \
3209         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3210 } while (0)
3211
3212
3213 static struct alias **
3214 __lookupalias(const char *name)
3215 {
3216         unsigned int hashval;
3217         struct alias **app;
3218         const char *p;
3219         unsigned int ch;
3220
3221         p = name;
3222
3223         ch = (unsigned char)*p;
3224         hashval = ch << 4;
3225         while (ch) {
3226                 hashval += ch;
3227                 ch = (unsigned char)*++p;
3228         }
3229         app = &atab[hashval % ATABSIZE];
3230
3231         for (; *app; app = &(*app)->next) {
3232                 if (strcmp(name, (*app)->name) == 0) {
3233                         break;
3234                 }
3235         }
3236
3237         return app;
3238 }
3239
3240 static struct alias *
3241 lookupalias(const char *name, int check)
3242 {
3243         struct alias *ap = *__lookupalias(name);
3244
3245         if (check && ap && (ap->flag & ALIASINUSE))
3246                 return NULL;
3247         return ap;
3248 }
3249
3250 static struct alias *
3251 freealias(struct alias *ap)
3252 {
3253         struct alias *next;
3254
3255         if (ap->flag & ALIASINUSE) {
3256                 ap->flag |= ALIASDEAD;
3257                 return ap;
3258         }
3259
3260         next = ap->next;
3261         free(ap->name);
3262         free(ap->val);
3263         free(ap);
3264         return next;
3265 }
3266
3267 static void
3268 setalias(const char *name, const char *val)
3269 {
3270         struct alias *ap, **app;
3271
3272         app = __lookupalias(name);
3273         ap = *app;
3274         INT_OFF;
3275         if (ap) {
3276                 if (!(ap->flag & ALIASINUSE)) {
3277                         free(ap->val);
3278                 }
3279                 ap->val = ckstrdup(val);
3280                 ap->flag &= ~ALIASDEAD;
3281         } else {
3282                 /* not found */
3283                 ap = ckzalloc(sizeof(struct alias));
3284                 ap->name = ckstrdup(name);
3285                 ap->val = ckstrdup(val);
3286                 /*ap->flag = 0; - ckzalloc did it */
3287                 /*ap->next = NULL;*/
3288                 *app = ap;
3289         }
3290         INT_ON;
3291 }
3292
3293 static int
3294 unalias(const char *name)
3295 {
3296         struct alias **app;
3297
3298         app = __lookupalias(name);
3299
3300         if (*app) {
3301                 INT_OFF;
3302                 *app = freealias(*app);
3303                 INT_ON;
3304                 return 0;
3305         }
3306
3307         return 1;
3308 }
3309
3310 static void
3311 rmaliases(void)
3312 {
3313         struct alias *ap, **app;
3314         int i;
3315
3316         INT_OFF;
3317         for (i = 0; i < ATABSIZE; i++) {
3318                 app = &atab[i];
3319                 for (ap = *app; ap; ap = *app) {
3320                         *app = freealias(*app);
3321                         if (ap == *app) {
3322                                 app = &ap->next;
3323                         }
3324                 }
3325         }
3326         INT_ON;
3327 }
3328
3329 static void
3330 printalias(const struct alias *ap)
3331 {
3332         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3333 }
3334
3335 /*
3336  * TODO - sort output
3337  */
3338 static int FAST_FUNC
3339 aliascmd(int argc UNUSED_PARAM, char **argv)
3340 {
3341         char *n, *v;
3342         int ret = 0;
3343         struct alias *ap;
3344
3345         if (!argv[1]) {
3346                 int i;
3347
3348                 for (i = 0; i < ATABSIZE; i++) {
3349                         for (ap = atab[i]; ap; ap = ap->next) {
3350                                 printalias(ap);
3351                         }
3352                 }
3353                 return 0;
3354         }
3355         while ((n = *++argv) != NULL) {
3356                 v = strchr(n+1, '=');
3357                 if (v == NULL) { /* n+1: funny ksh stuff */
3358                         ap = *__lookupalias(n);
3359                         if (ap == NULL) {
3360                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3361                                 ret = 1;
3362                         } else
3363                                 printalias(ap);
3364                 } else {
3365                         *v++ = '\0';
3366                         setalias(n, v);
3367                 }
3368         }
3369
3370         return ret;
3371 }
3372
3373 static int FAST_FUNC
3374 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3375 {
3376         int i;
3377
3378         while (nextopt("a") != '\0') {
3379                 rmaliases();
3380                 return 0;
3381         }
3382         for (i = 0; *argptr; argptr++) {
3383                 if (unalias(*argptr)) {
3384                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3385                         i = 1;
3386                 }
3387         }
3388
3389         return i;
3390 }
3391
3392 #endif /* ASH_ALIAS */
3393
3394
3395 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3396 #define FORK_FG    0
3397 #define FORK_BG    1
3398 #define FORK_NOJOB 2
3399
3400 /* mode flags for showjob(s) */
3401 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3402 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3403 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3404 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3405
3406 /*
3407  * A job structure contains information about a job.  A job is either a
3408  * single process or a set of processes contained in a pipeline.  In the
3409  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3410  * array of pids.
3411  */
3412 struct procstat {
3413         pid_t   ps_pid;         /* process id */
3414         int     ps_status;      /* last process status from wait() */
3415         char    *ps_cmd;        /* text of command being run */
3416 };
3417
3418 struct job {
3419         struct procstat ps0;    /* status of process */
3420         struct procstat *ps;    /* status or processes when more than one */
3421 #if JOBS
3422         int stopstatus;         /* status of a stopped job */
3423 #endif
3424         unsigned nprocs;        /* number of processes */
3425
3426 #define JOBRUNNING      0       /* at least one proc running */
3427 #define JOBSTOPPED      1       /* all procs are stopped */
3428 #define JOBDONE         2       /* all procs are completed */
3429         unsigned
3430                 state: 8,
3431 #if JOBS
3432                 sigint: 1,      /* job was killed by SIGINT */
3433                 jobctl: 1,      /* job running under job control */
3434 #endif
3435                 waited: 1,      /* true if this entry has been waited for */
3436                 used: 1,        /* true if this entry is in used */
3437                 changed: 1;     /* true if status has changed */
3438         struct job *prev_job;   /* previous job */
3439 };
3440
3441 static struct job *makejob(/*union node *,*/ int);
3442 static int forkshell(struct job *, union node *, int);
3443 static int waitforjob(struct job *);
3444
3445 #if !JOBS
3446 enum { doing_jobctl = 0 };
3447 #define setjobctl(on) do {} while (0)
3448 #else
3449 static smallint doing_jobctl; //references:8
3450 static void setjobctl(int);
3451 #endif
3452
3453 /*
3454  * Ignore a signal.
3455  */
3456 static void
3457 ignoresig(int signo)
3458 {
3459         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3460         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3461                 /* No, need to do it */
3462                 signal(signo, SIG_IGN);
3463         }
3464         sigmode[signo - 1] = S_HARD_IGN;
3465 }
3466
3467 /*
3468  * Only one usage site - in setsignal()
3469  */
3470 static void
3471 signal_handler(int signo)
3472 {
3473         if (signo == SIGCHLD) {
3474                 got_sigchld = 1;
3475                 if (!trap[SIGCHLD])
3476                         return;
3477         }
3478
3479         gotsig[signo - 1] = 1;
3480         pending_sig = signo;
3481
3482         if (signo == SIGINT && !trap[SIGINT]) {
3483                 if (!suppress_int) {
3484                         pending_sig = 0;
3485                         raise_interrupt(); /* does not return */
3486                 }
3487                 pending_int = 1;
3488         }
3489 }
3490
3491 /*
3492  * Set the signal handler for the specified signal.  The routine figures
3493  * out what it should be set to.
3494  */
3495 static void
3496 setsignal(int signo)
3497 {
3498         char *t;
3499         char cur_act, new_act;
3500         struct sigaction act;
3501
3502         t = trap[signo];
3503         new_act = S_DFL;
3504         if (t != NULL) { /* trap for this sig is set */
3505                 new_act = S_CATCH;
3506                 if (t[0] == '\0') /* trap is "": ignore this sig */
3507                         new_act = S_IGN;
3508         }
3509
3510         if (rootshell && new_act == S_DFL) {
3511                 switch (signo) {
3512                 case SIGINT:
3513                         if (iflag || minusc || sflag == 0)
3514                                 new_act = S_CATCH;
3515                         break;
3516                 case SIGQUIT:
3517 #if DEBUG
3518                         if (debug)
3519                                 break;
3520 #endif
3521                         /* man bash:
3522                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3523                          * commands run by bash have signal handlers
3524                          * set to the values inherited by the shell
3525                          * from its parent". */
3526                         new_act = S_IGN;
3527                         break;
3528                 case SIGTERM:
3529                         if (iflag)
3530                                 new_act = S_IGN;
3531                         break;
3532 #if JOBS
3533                 case SIGTSTP:
3534                 case SIGTTOU:
3535                         if (mflag)
3536                                 new_act = S_IGN;
3537                         break;
3538 #endif
3539                 }
3540         }
3541 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3542 //whereas we have to restore it to what shell got on entry
3543 //from the parent. See comment above
3544
3545         if (signo == SIGCHLD)
3546                 new_act = S_CATCH;
3547
3548         t = &sigmode[signo - 1];
3549         cur_act = *t;
3550         if (cur_act == 0) {
3551                 /* current setting is not yet known */
3552                 if (sigaction(signo, NULL, &act)) {
3553                         /* pretend it worked; maybe we should give a warning,
3554                          * but other shells don't. We don't alter sigmode,
3555                          * so we retry every time.
3556                          * btw, in Linux it never fails. --vda */
3557                         return;
3558                 }
3559                 if (act.sa_handler == SIG_IGN) {
3560                         cur_act = S_HARD_IGN;
3561                         if (mflag
3562                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3563                         ) {
3564                                 cur_act = S_IGN;   /* don't hard ignore these */
3565                         }
3566                 }
3567         }
3568         if (cur_act == S_HARD_IGN || cur_act == new_act)
3569                 return;
3570
3571         act.sa_handler = SIG_DFL;
3572         switch (new_act) {
3573         case S_CATCH:
3574                 act.sa_handler = signal_handler;
3575                 break;
3576         case S_IGN:
3577                 act.sa_handler = SIG_IGN;
3578                 break;
3579         }
3580
3581         /* flags and mask matter only if !DFL and !IGN, but we do it
3582          * for all cases for more deterministic behavior:
3583          */
3584         act.sa_flags = 0;
3585         sigfillset(&act.sa_mask);
3586
3587         sigaction_set(signo, &act);
3588
3589         *t = new_act;
3590 }
3591
3592 /* mode flags for set_curjob */
3593 #define CUR_DELETE 2
3594 #define CUR_RUNNING 1
3595 #define CUR_STOPPED 0
3596
3597 #if JOBS
3598 /* pgrp of shell on invocation */
3599 static int initialpgrp; //references:2
3600 static int ttyfd = -1; //5
3601 #endif
3602 /* array of jobs */
3603 static struct job *jobtab; //5
3604 /* size of array */
3605 static unsigned njobs; //4
3606 /* current job */
3607 static struct job *curjob; //lots
3608 /* number of presumed living untracked jobs */
3609 static int jobless; //4
3610
3611 #if 0
3612 /* Bash has a feature: it restores termios after a successful wait for
3613  * a foreground job which had at least one stopped or sigkilled member.
3614  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3615  * properly restoring tty state. Should we do this too?
3616  * A reproducer: ^Z an interactive python:
3617  *
3618  * # python
3619  * Python 2.7.12 (...)
3620  * >>> ^Z
3621  *      { python leaves tty in -icanon -echo state. We do survive that... }
3622  *  [1]+  Stopped                    python
3623  *      { ...however, next program (python #2) does not survive it well: }
3624  * # python
3625  * Python 2.7.12 (...)
3626  * >>> Traceback (most recent call last):
3627  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3628  *   File "<stdin>", line 1, in <module>
3629  * NameError: name 'qwerty' is not defined
3630  *
3631  * The implementation below is modeled on bash code and seems to work.
3632  * However, I'm not sure we should do this. For one: what if I'd fg
3633  * the stopped python instead? It'll be confused by "restored" tty state.
3634  */
3635 static struct termios shell_tty_info;
3636 static void
3637 get_tty_state(void)
3638 {
3639         if (rootshell && ttyfd >= 0)
3640                 tcgetattr(ttyfd, &shell_tty_info);
3641 }
3642 static void
3643 set_tty_state(void)
3644 {
3645         /* if (rootshell) - caller ensures this */
3646         if (ttyfd >= 0)
3647                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3648 }
3649 static int
3650 job_signal_status(struct job *jp)
3651 {
3652         int status;
3653         unsigned i;
3654         struct procstat *ps = jp->ps;
3655         for (i = 0; i < jp->nprocs; i++) {
3656                 status = ps[i].ps_status;
3657                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3658                         return status;
3659         }
3660         return 0;
3661 }
3662 static void
3663 restore_tty_if_stopped_or_signaled(struct job *jp)
3664 {
3665 //TODO: check what happens if we come from waitforjob() in expbackq()
3666         if (rootshell) {
3667                 int s = job_signal_status(jp);
3668                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3669                         set_tty_state();
3670         }
3671 }
3672 #else
3673 # define get_tty_state() ((void)0)
3674 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3675 #endif
3676
3677 static void
3678 set_curjob(struct job *jp, unsigned mode)
3679 {
3680         struct job *jp1;
3681         struct job **jpp, **curp;
3682
3683         /* first remove from list */
3684         jpp = curp = &curjob;
3685         while (1) {
3686                 jp1 = *jpp;
3687                 if (jp1 == jp)
3688                         break;
3689                 jpp = &jp1->prev_job;
3690         }
3691         *jpp = jp1->prev_job;
3692
3693         /* Then re-insert in correct position */
3694         jpp = curp;
3695         switch (mode) {
3696         default:
3697 #if DEBUG
3698                 abort();
3699 #endif
3700         case CUR_DELETE:
3701                 /* job being deleted */
3702                 break;
3703         case CUR_RUNNING:
3704                 /* newly created job or backgrounded job,
3705                  * put after all stopped jobs.
3706                  */
3707                 while (1) {
3708                         jp1 = *jpp;
3709 #if JOBS
3710                         if (!jp1 || jp1->state != JOBSTOPPED)
3711 #endif
3712                                 break;
3713                         jpp = &jp1->prev_job;
3714                 }
3715                 /* FALLTHROUGH */
3716 #if JOBS
3717         case CUR_STOPPED:
3718 #endif
3719                 /* newly stopped job - becomes curjob */
3720                 jp->prev_job = *jpp;
3721                 *jpp = jp;
3722                 break;
3723         }
3724 }
3725
3726 #if JOBS || DEBUG
3727 static int
3728 jobno(const struct job *jp)
3729 {
3730         return jp - jobtab + 1;
3731 }
3732 #endif
3733
3734 /*
3735  * Convert a job name to a job structure.
3736  */
3737 #if !JOBS
3738 #define getjob(name, getctl) getjob(name)
3739 #endif
3740 static struct job *
3741 getjob(const char *name, int getctl)
3742 {
3743         struct job *jp;
3744         struct job *found;
3745         const char *err_msg = "%s: no such job";
3746         unsigned num;
3747         int c;
3748         const char *p;
3749         char *(*match)(const char *, const char *);
3750
3751         jp = curjob;
3752         p = name;
3753         if (!p)
3754                 goto currentjob;
3755
3756         if (*p != '%')
3757                 goto err;
3758
3759         c = *++p;
3760         if (!c)
3761                 goto currentjob;
3762
3763         if (!p[1]) {
3764                 if (c == '+' || c == '%') {
3765  currentjob:
3766                         err_msg = "No current job";
3767                         goto check;
3768                 }
3769                 if (c == '-') {
3770                         if (jp)
3771                                 jp = jp->prev_job;
3772                         err_msg = "No previous job";
3773  check:
3774                         if (!jp)
3775                                 goto err;
3776                         goto gotit;
3777                 }
3778         }
3779
3780         if (is_number(p)) {
3781                 num = atoi(p);
3782                 if (num > 0 && num <= njobs) {
3783                         jp = jobtab + num - 1;
3784                         if (jp->used)
3785                                 goto gotit;
3786                         goto err;
3787                 }
3788         }
3789
3790         match = prefix;
3791         if (*p == '?') {
3792                 match = strstr;
3793                 p++;
3794         }
3795
3796         found = NULL;
3797         while (jp) {
3798                 if (match(jp->ps[0].ps_cmd, p)) {
3799                         if (found)
3800                                 goto err;
3801                         found = jp;
3802                         err_msg = "%s: ambiguous";
3803                 }
3804                 jp = jp->prev_job;
3805         }
3806         if (!found)
3807                 goto err;
3808         jp = found;
3809
3810  gotit:
3811 #if JOBS
3812         err_msg = "job %s not created under job control";
3813         if (getctl && jp->jobctl == 0)
3814                 goto err;
3815 #endif
3816         return jp;
3817  err:
3818         ash_msg_and_raise_error(err_msg, name);
3819 }
3820
3821 /*
3822  * Mark a job structure as unused.
3823  */
3824 static void
3825 freejob(struct job *jp)
3826 {
3827         struct procstat *ps;
3828         int i;
3829
3830         INT_OFF;
3831         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3832                 if (ps->ps_cmd != nullstr)
3833                         free(ps->ps_cmd);
3834         }
3835         if (jp->ps != &jp->ps0)
3836                 free(jp->ps);
3837         jp->used = 0;
3838         set_curjob(jp, CUR_DELETE);
3839         INT_ON;
3840 }
3841
3842 #if JOBS
3843 static void
3844 xtcsetpgrp(int fd, pid_t pgrp)
3845 {
3846         if (tcsetpgrp(fd, pgrp))
3847                 ash_msg_and_raise_perror("can't set tty process group");
3848 }
3849
3850 /*
3851  * Turn job control on and off.
3852  *
3853  * Note:  This code assumes that the third arg to ioctl is a character
3854  * pointer, which is true on Berkeley systems but not System V.  Since
3855  * System V doesn't have job control yet, this isn't a problem now.
3856  *
3857  * Called with interrupts off.
3858  */
3859 static void
3860 setjobctl(int on)
3861 {
3862         int fd;
3863         int pgrp;
3864
3865         if (on == doing_jobctl || rootshell == 0)
3866                 return;
3867         if (on) {
3868                 int ofd;
3869                 ofd = fd = open(_PATH_TTY, O_RDWR);
3870                 if (fd < 0) {
3871         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3872          * That sometimes helps to acquire controlling tty.
3873          * Obviously, a workaround for bugs when someone
3874          * failed to provide a controlling tty to bash! :) */
3875                         fd = 2;
3876                         while (!isatty(fd))
3877                                 if (--fd < 0)
3878                                         goto out;
3879                 }
3880                 /* fd is a tty at this point */
3881                 fd = fcntl(fd, F_DUPFD, 10);
3882                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3883                         close(ofd);
3884                 if (fd < 0)
3885                         goto out; /* F_DUPFD failed */
3886                 close_on_exec_on(fd);
3887                 while (1) { /* while we are in the background */
3888                         pgrp = tcgetpgrp(fd);
3889                         if (pgrp < 0) {
3890  out:
3891                                 ash_msg("can't access tty; job control turned off");
3892                                 mflag = on = 0;
3893                                 goto close;
3894                         }
3895                         if (pgrp == getpgrp())
3896                                 break;
3897                         killpg(0, SIGTTIN);
3898                 }
3899                 initialpgrp = pgrp;
3900
3901                 setsignal(SIGTSTP);
3902                 setsignal(SIGTTOU);
3903                 setsignal(SIGTTIN);
3904                 pgrp = rootpid;
3905                 setpgid(0, pgrp);
3906                 xtcsetpgrp(fd, pgrp);
3907         } else {
3908                 /* turning job control off */
3909                 fd = ttyfd;
3910                 pgrp = initialpgrp;
3911                 /* was xtcsetpgrp, but this can make exiting ash
3912                  * loop forever if pty is already deleted */
3913                 tcsetpgrp(fd, pgrp);
3914                 setpgid(0, pgrp);
3915                 setsignal(SIGTSTP);
3916                 setsignal(SIGTTOU);
3917                 setsignal(SIGTTIN);
3918  close:
3919                 if (fd >= 0)
3920                         close(fd);
3921                 fd = -1;
3922         }
3923         ttyfd = fd;
3924         doing_jobctl = on;
3925 }
3926
3927 static int FAST_FUNC
3928 killcmd(int argc, char **argv)
3929 {
3930         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3931                 int i = 1;
3932                 do {
3933                         if (argv[i][0] == '%') {
3934                                 /*
3935                                  * "kill %N" - job kill
3936                                  * Converting to pgrp / pid kill
3937                                  */
3938                                 struct job *jp;
3939                                 char *dst;
3940                                 int j, n;
3941
3942                                 jp = getjob(argv[i], 0);
3943                                 /*
3944                                  * In jobs started under job control, we signal
3945                                  * entire process group by kill -PGRP_ID.
3946                                  * This happens, f.e., in interactive shell.
3947                                  *
3948                                  * Otherwise, we signal each child via
3949                                  * kill PID1 PID2 PID3.
3950                                  * Testcases:
3951                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3952                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3953                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3954                                  */
3955                                 n = jp->nprocs; /* can't be 0 (I hope) */
3956                                 if (jp->jobctl)
3957                                         n = 1;
3958                                 dst = alloca(n * sizeof(int)*4);
3959                                 argv[i] = dst;
3960                                 for (j = 0; j < n; j++) {
3961                                         struct procstat *ps = &jp->ps[j];
3962                                         /* Skip non-running and not-stopped members
3963                                          * (i.e. dead members) of the job
3964                                          */
3965                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3966                                                 continue;
3967                                         /*
3968                                          * kill_main has matching code to expect
3969                                          * leading space. Needed to not confuse
3970                                          * negative pids with "kill -SIGNAL_NO" syntax
3971                                          */
3972                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3973                                 }
3974                                 *dst = '\0';
3975                         }
3976                 } while (argv[++i]);
3977         }
3978         return kill_main(argc, argv);
3979 }
3980
3981 static void
3982 showpipe(struct job *jp /*, FILE *out*/)
3983 {
3984         struct procstat *ps;
3985         struct procstat *psend;
3986
3987         psend = jp->ps + jp->nprocs;
3988         for (ps = jp->ps + 1; ps < psend; ps++)
3989                 printf(" | %s", ps->ps_cmd);
3990         newline_and_flush(stdout);
3991         flush_stdout_stderr();
3992 }
3993
3994
3995 static int
3996 restartjob(struct job *jp, int mode)
3997 {
3998         struct procstat *ps;
3999         int i;
4000         int status;
4001         pid_t pgid;
4002
4003         INT_OFF;
4004         if (jp->state == JOBDONE)
4005                 goto out;
4006         jp->state = JOBRUNNING;
4007         pgid = jp->ps[0].ps_pid;
4008         if (mode == FORK_FG) {
4009                 get_tty_state();
4010                 xtcsetpgrp(ttyfd, pgid);
4011         }
4012         killpg(pgid, SIGCONT);
4013         ps = jp->ps;
4014         i = jp->nprocs;
4015         do {
4016                 if (WIFSTOPPED(ps->ps_status)) {
4017                         ps->ps_status = -1;
4018                 }
4019                 ps++;
4020         } while (--i);
4021  out:
4022         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4023         INT_ON;
4024         return status;
4025 }
4026
4027 static int FAST_FUNC
4028 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4029 {
4030         struct job *jp;
4031         int mode;
4032         int retval;
4033
4034         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4035         nextopt(nullstr);
4036         argv = argptr;
4037         do {
4038                 jp = getjob(*argv, 1);
4039                 if (mode == FORK_BG) {
4040                         set_curjob(jp, CUR_RUNNING);
4041                         printf("[%d] ", jobno(jp));
4042                 }
4043                 out1str(jp->ps[0].ps_cmd);
4044                 showpipe(jp /*, stdout*/);
4045                 retval = restartjob(jp, mode);
4046         } while (*argv && *++argv);
4047         return retval;
4048 }
4049 #endif
4050
4051 static int
4052 sprint_status48(char *s, int status, int sigonly)
4053 {
4054         int col;
4055         int st;
4056
4057         col = 0;
4058         if (!WIFEXITED(status)) {
4059 #if JOBS
4060                 if (WIFSTOPPED(status))
4061                         st = WSTOPSIG(status);
4062                 else
4063 #endif
4064                         st = WTERMSIG(status);
4065                 if (sigonly) {
4066                         if (st == SIGINT || st == SIGPIPE)
4067                                 goto out;
4068 #if JOBS
4069                         if (WIFSTOPPED(status))
4070                                 goto out;
4071 #endif
4072                 }
4073                 st &= 0x7f;
4074 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4075                 col = fmtstr(s, 32, strsignal(st));
4076                 if (WCOREDUMP(status)) {
4077                         strcpy(s + col, " (core dumped)");
4078                         col += sizeof(" (core dumped)")-1;
4079                 }
4080         } else if (!sigonly) {
4081                 st = WEXITSTATUS(status);
4082                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4083         }
4084  out:
4085         return col;
4086 }
4087
4088 static int
4089 wait_block_or_sig(int *status)
4090 {
4091         int pid;
4092
4093         do {
4094                 sigset_t mask;
4095
4096                 /* Poll all children for changes in their state */
4097                 got_sigchld = 0;
4098                 /* if job control is active, accept stopped processes too */
4099                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4100                 if (pid != 0)
4101                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4102
4103                 /* Children exist, but none are ready. Sleep until interesting signal */
4104 #if 1
4105                 sigfillset(&mask);
4106                 sigprocmask(SIG_SETMASK, &mask, &mask);
4107                 while (!got_sigchld && !pending_sig)
4108                         sigsuspend(&mask);
4109                 sigprocmask(SIG_SETMASK, &mask, NULL);
4110 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4111                 while (!got_sigchld && !pending_sig)
4112                         pause();
4113 #endif
4114
4115                 /* If it was SIGCHLD, poll children again */
4116         } while (got_sigchld);
4117
4118         return pid;
4119 }
4120
4121 #define DOWAIT_NONBLOCK 0
4122 #define DOWAIT_BLOCK    1
4123 #define DOWAIT_BLOCK_OR_SIG 2
4124
4125 static int
4126 dowait(int block, struct job *job)
4127 {
4128         int pid;
4129         int status;
4130         struct job *jp;
4131         struct job *thisjob = NULL;
4132
4133         TRACE(("dowait(0x%x) called\n", block));
4134
4135         /* It's wrong to call waitpid() outside of INT_OFF region:
4136          * signal can arrive just after syscall return and handler can
4137          * longjmp away, losing stop/exit notification processing.
4138          * Thus, for "jobs" builtin, and for waiting for a fg job,
4139          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4140          *
4141          * However, for "wait" builtin it is wrong to simply call waitpid()
4142          * in INT_OFF region: "wait" needs to wait for any running job
4143          * to change state, but should exit on any trap too.
4144          * In INT_OFF region, a signal just before syscall entry can set
4145          * pending_sig variables, but we can't check them, and we would
4146          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4147          *
4148          * Because of this, we run inside INT_OFF, but use a special routine
4149          * which combines waitpid() and sigsuspend().
4150          * This is the reason why we need to have a handler for SIGCHLD:
4151          * SIG_DFL handler does not wake sigsuspend().
4152          */
4153         INT_OFF;
4154         if (block == DOWAIT_BLOCK_OR_SIG) {
4155                 pid = wait_block_or_sig(&status);
4156         } else {
4157                 int wait_flags = 0;
4158                 if (block == DOWAIT_NONBLOCK)
4159                         wait_flags = WNOHANG;
4160                 /* if job control is active, accept stopped processes too */
4161                 if (doing_jobctl)
4162                         wait_flags |= WUNTRACED;
4163                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4164                 pid = waitpid(-1, &status, wait_flags);
4165         }
4166         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4167                                 pid, status, errno, strerror(errno)));
4168         if (pid <= 0)
4169                 goto out;
4170
4171         thisjob = NULL;
4172         for (jp = curjob; jp; jp = jp->prev_job) {
4173                 int jobstate;
4174                 struct procstat *ps;
4175                 struct procstat *psend;
4176                 if (jp->state == JOBDONE)
4177                         continue;
4178                 jobstate = JOBDONE;
4179                 ps = jp->ps;
4180                 psend = ps + jp->nprocs;
4181                 do {
4182                         if (ps->ps_pid == pid) {
4183                                 TRACE(("Job %d: changing status of proc %d "
4184                                         "from 0x%x to 0x%x\n",
4185                                         jobno(jp), pid, ps->ps_status, status));
4186                                 ps->ps_status = status;
4187                                 thisjob = jp;
4188                         }
4189                         if (ps->ps_status == -1)
4190                                 jobstate = JOBRUNNING;
4191 #if JOBS
4192                         if (jobstate == JOBRUNNING)
4193                                 continue;
4194                         if (WIFSTOPPED(ps->ps_status)) {
4195                                 jp->stopstatus = ps->ps_status;
4196                                 jobstate = JOBSTOPPED;
4197                         }
4198 #endif
4199                 } while (++ps < psend);
4200                 if (!thisjob)
4201                         continue;
4202
4203                 /* Found the job where one of its processes changed its state.
4204                  * Is there at least one live and running process in this job? */
4205                 if (jobstate != JOBRUNNING) {
4206                         /* No. All live processes in the job are stopped
4207                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4208                          */
4209                         thisjob->changed = 1;
4210                         if (thisjob->state != jobstate) {
4211                                 TRACE(("Job %d: changing state from %d to %d\n",
4212                                         jobno(thisjob), thisjob->state, jobstate));
4213                                 thisjob->state = jobstate;
4214 #if JOBS
4215                                 if (jobstate == JOBSTOPPED)
4216                                         set_curjob(thisjob, CUR_STOPPED);
4217 #endif
4218                         }
4219                 }
4220                 goto out;
4221         }
4222         /* The process wasn't found in job list */
4223 #if JOBS
4224         if (!WIFSTOPPED(status))
4225                 jobless--;
4226 #endif
4227  out:
4228         INT_ON;
4229
4230         if (thisjob && thisjob == job) {
4231                 char s[48 + 1];
4232                 int len;
4233
4234                 len = sprint_status48(s, status, 1);
4235                 if (len) {
4236                         s[len] = '\n';
4237                         s[len + 1] = '\0';
4238                         out2str(s);
4239                 }
4240         }
4241         return pid;
4242 }
4243
4244 #if JOBS
4245 static void
4246 showjob(struct job *jp, int mode)
4247 {
4248         struct procstat *ps;
4249         struct procstat *psend;
4250         int col;
4251         int indent_col;
4252         char s[16 + 16 + 48];
4253         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4254
4255         ps = jp->ps;
4256
4257         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4258                 /* just output process (group) id of pipeline */
4259                 fprintf(out, "%d\n", ps->ps_pid);
4260                 return;
4261         }
4262
4263         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4264         indent_col = col;
4265
4266         if (jp == curjob)
4267                 s[col - 3] = '+';
4268         else if (curjob && jp == curjob->prev_job)
4269                 s[col - 3] = '-';
4270
4271         if (mode & SHOW_PIDS)
4272                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4273
4274         psend = ps + jp->nprocs;
4275
4276         if (jp->state == JOBRUNNING) {
4277                 strcpy(s + col, "Running");
4278                 col += sizeof("Running") - 1;
4279         } else {
4280                 int status = psend[-1].ps_status;
4281                 if (jp->state == JOBSTOPPED)
4282                         status = jp->stopstatus;
4283                 col += sprint_status48(s + col, status, 0);
4284         }
4285         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4286
4287         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4288          * or prints several "PID             | <cmdN>" lines,
4289          * depending on SHOW_PIDS bit.
4290          * We do not print status of individual processes
4291          * between PID and <cmdN>. bash does it, but not very well:
4292          * first line shows overall job status, not process status,
4293          * making it impossible to know 1st process status.
4294          */
4295         goto start;
4296         do {
4297                 /* for each process */
4298                 s[0] = '\0';
4299                 col = 33;
4300                 if (mode & SHOW_PIDS)
4301                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4302  start:
4303                 fprintf(out, "%s%*c%s%s",
4304                                 s,
4305                                 33 - col >= 0 ? 33 - col : 0, ' ',
4306                                 ps == jp->ps ? "" : "| ",
4307                                 ps->ps_cmd
4308                 );
4309         } while (++ps != psend);
4310         newline_and_flush(out);
4311
4312         jp->changed = 0;
4313
4314         if (jp->state == JOBDONE) {
4315                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4316                 freejob(jp);
4317         }
4318 }
4319
4320 /*
4321  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4322  * statuses have changed since the last call to showjobs.
4323  */
4324 static void
4325 showjobs(int mode)
4326 {
4327         struct job *jp;
4328
4329         TRACE(("showjobs(0x%x) called\n", mode));
4330
4331         /* Handle all finished jobs */
4332         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4333                 continue;
4334
4335         for (jp = curjob; jp; jp = jp->prev_job) {
4336                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4337                         showjob(jp, mode);
4338                 }
4339         }
4340 }
4341
4342 static int FAST_FUNC
4343 jobscmd(int argc UNUSED_PARAM, char **argv)
4344 {
4345         int mode, m;
4346
4347         mode = 0;
4348         while ((m = nextopt("lp")) != '\0') {
4349                 if (m == 'l')
4350                         mode |= SHOW_PIDS;
4351                 else
4352                         mode |= SHOW_ONLY_PGID;
4353         }
4354
4355         argv = argptr;
4356         if (*argv) {
4357                 do
4358                         showjob(getjob(*argv, 0), mode);
4359                 while (*++argv);
4360         } else {
4361                 showjobs(mode);
4362         }
4363
4364         return 0;
4365 }
4366 #endif /* JOBS */
4367
4368 /* Called only on finished or stopped jobs (no members are running) */
4369 static int
4370 getstatus(struct job *job)
4371 {
4372         int status;
4373         int retval;
4374         struct procstat *ps;
4375
4376         /* Fetch last member's status */
4377         ps = job->ps + job->nprocs - 1;
4378         status = ps->ps_status;
4379         if (pipefail) {
4380                 /* "set -o pipefail" mode: use last _nonzero_ status */
4381                 while (status == 0 && --ps >= job->ps)
4382                         status = ps->ps_status;
4383         }
4384
4385         retval = WEXITSTATUS(status);
4386         if (!WIFEXITED(status)) {
4387 #if JOBS
4388                 retval = WSTOPSIG(status);
4389                 if (!WIFSTOPPED(status))
4390 #endif
4391                 {
4392                         /* XXX: limits number of signals */
4393                         retval = WTERMSIG(status);
4394 #if JOBS
4395                         if (retval == SIGINT)
4396                                 job->sigint = 1;
4397 #endif
4398                 }
4399                 retval += 128;
4400         }
4401         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4402                 jobno(job), job->nprocs, status, retval));
4403         return retval;
4404 }
4405
4406 static int FAST_FUNC
4407 waitcmd(int argc UNUSED_PARAM, char **argv)
4408 {
4409         struct job *job;
4410         int retval;
4411         struct job *jp;
4412
4413         nextopt(nullstr);
4414         retval = 0;
4415
4416         argv = argptr;
4417         if (!*argv) {
4418                 /* wait for all jobs */
4419                 for (;;) {
4420                         jp = curjob;
4421                         while (1) {
4422                                 if (!jp) /* no running procs */
4423                                         goto ret;
4424                                 if (jp->state == JOBRUNNING)
4425                                         break;
4426                                 jp->waited = 1;
4427                                 jp = jp->prev_job;
4428                         }
4429         /* man bash:
4430          * "When bash is waiting for an asynchronous command via
4431          * the wait builtin, the reception of a signal for which a trap
4432          * has been set will cause the wait builtin to return immediately
4433          * with an exit status greater than 128, immediately after which
4434          * the trap is executed."
4435          */
4436                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4437         /* if child sends us a signal *and immediately exits*,
4438          * dowait() returns pid > 0. Check this case,
4439          * not "if (dowait() < 0)"!
4440          */
4441                         if (pending_sig)
4442                                 goto sigout;
4443                 }
4444         }
4445
4446         retval = 127;
4447         do {
4448                 if (**argv != '%') {
4449                         pid_t pid = number(*argv);
4450                         job = curjob;
4451                         while (1) {
4452                                 if (!job)
4453                                         goto repeat;
4454                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4455                                         break;
4456                                 job = job->prev_job;
4457                         }
4458                 } else {
4459                         job = getjob(*argv, 0);
4460                 }
4461                 /* loop until process terminated or stopped */
4462                 while (job->state == JOBRUNNING) {
4463                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4464                         if (pending_sig)
4465                                 goto sigout;
4466                 }
4467                 job->waited = 1;
4468                 retval = getstatus(job);
4469  repeat: ;
4470         } while (*++argv);
4471
4472  ret:
4473         return retval;
4474  sigout:
4475         retval = 128 + pending_sig;
4476         return retval;
4477 }
4478
4479 static struct job *
4480 growjobtab(void)
4481 {
4482         size_t len;
4483         ptrdiff_t offset;
4484         struct job *jp, *jq;
4485
4486         len = njobs * sizeof(*jp);
4487         jq = jobtab;
4488         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4489
4490         offset = (char *)jp - (char *)jq;
4491         if (offset) {
4492                 /* Relocate pointers */
4493                 size_t l = len;
4494
4495                 jq = (struct job *)((char *)jq + l);
4496                 while (l) {
4497                         l -= sizeof(*jp);
4498                         jq--;
4499 #define joff(p) ((struct job *)((char *)(p) + l))
4500 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4501                         if (joff(jp)->ps == &jq->ps0)
4502                                 jmove(joff(jp)->ps);
4503                         if (joff(jp)->prev_job)
4504                                 jmove(joff(jp)->prev_job);
4505                 }
4506                 if (curjob)
4507                         jmove(curjob);
4508 #undef joff
4509 #undef jmove
4510         }
4511
4512         njobs += 4;
4513         jobtab = jp;
4514         jp = (struct job *)((char *)jp + len);
4515         jq = jp + 3;
4516         do {
4517                 jq->used = 0;
4518         } while (--jq >= jp);
4519         return jp;
4520 }
4521
4522 /*
4523  * Return a new job structure.
4524  * Called with interrupts off.
4525  */
4526 static struct job *
4527 makejob(/*union node *node,*/ int nprocs)
4528 {
4529         int i;
4530         struct job *jp;
4531
4532         for (i = njobs, jp = jobtab; ; jp++) {
4533                 if (--i < 0) {
4534                         jp = growjobtab();
4535                         break;
4536                 }
4537                 if (jp->used == 0)
4538                         break;
4539                 if (jp->state != JOBDONE || !jp->waited)
4540                         continue;
4541 #if JOBS
4542                 if (doing_jobctl)
4543                         continue;
4544 #endif
4545                 freejob(jp);
4546                 break;
4547         }
4548         memset(jp, 0, sizeof(*jp));
4549 #if JOBS
4550         /* jp->jobctl is a bitfield.
4551          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4552         if (doing_jobctl)
4553                 jp->jobctl = 1;
4554 #endif
4555         jp->prev_job = curjob;
4556         curjob = jp;
4557         jp->used = 1;
4558         jp->ps = &jp->ps0;
4559         if (nprocs > 1) {
4560                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4561         }
4562         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4563                                 jobno(jp)));
4564         return jp;
4565 }
4566
4567 #if JOBS
4568 /*
4569  * Return a string identifying a command (to be printed by the
4570  * jobs command).
4571  */
4572 static char *cmdnextc;
4573
4574 static void
4575 cmdputs(const char *s)
4576 {
4577         static const char vstype[VSTYPE + 1][3] = {
4578                 "", "}", "-", "+", "?", "=",
4579                 "%", "%%", "#", "##"
4580                 IF_BASH_SUBSTR(, ":")
4581                 IF_BASH_PATTERN_SUBST(, "/", "//")
4582         };
4583
4584         const char *p, *str;
4585         char cc[2];
4586         char *nextc;
4587         unsigned char c;
4588         unsigned char subtype = 0;
4589         int quoted = 0;
4590
4591         cc[1] = '\0';
4592         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4593         p = s;
4594         while ((c = *p++) != '\0') {
4595                 str = NULL;
4596                 switch (c) {
4597                 case CTLESC:
4598                         c = *p++;
4599                         break;
4600                 case CTLVAR:
4601                         subtype = *p++;
4602                         if ((subtype & VSTYPE) == VSLENGTH)
4603                                 str = "${#";
4604                         else
4605                                 str = "${";
4606                         goto dostr;
4607                 case CTLENDVAR:
4608                         str = "\"}" + !(quoted & 1);
4609                         quoted >>= 1;
4610                         subtype = 0;
4611                         goto dostr;
4612                 case CTLBACKQ:
4613                         str = "$(...)";
4614                         goto dostr;
4615 #if ENABLE_FEATURE_SH_MATH
4616                 case CTLARI:
4617                         str = "$((";
4618                         goto dostr;
4619                 case CTLENDARI:
4620                         str = "))";
4621                         goto dostr;
4622 #endif
4623                 case CTLQUOTEMARK:
4624                         quoted ^= 1;
4625                         c = '"';
4626                         break;
4627                 case '=':
4628                         if (subtype == 0)
4629                                 break;
4630                         if ((subtype & VSTYPE) != VSNORMAL)
4631                                 quoted <<= 1;
4632                         str = vstype[subtype & VSTYPE];
4633                         if (subtype & VSNUL)
4634                                 c = ':';
4635                         else
4636                                 goto checkstr;
4637                         break;
4638                 case '\'':
4639                 case '\\':
4640                 case '"':
4641                 case '$':
4642                         /* These can only happen inside quotes */
4643                         cc[0] = c;
4644                         str = cc;
4645                         c = '\\';
4646                         break;
4647                 default:
4648                         break;
4649                 }
4650                 USTPUTC(c, nextc);
4651  checkstr:
4652                 if (!str)
4653                         continue;
4654  dostr:
4655                 while ((c = *str++) != '\0') {
4656                         USTPUTC(c, nextc);
4657                 }
4658         } /* while *p++ not NUL */
4659
4660         if (quoted & 1) {
4661                 USTPUTC('"', nextc);
4662         }
4663         *nextc = 0;
4664         cmdnextc = nextc;
4665 }
4666
4667 /* cmdtxt() and cmdlist() call each other */
4668 static void cmdtxt(union node *n);
4669
4670 static void
4671 cmdlist(union node *np, int sep)
4672 {
4673         for (; np; np = np->narg.next) {
4674                 if (!sep)
4675                         cmdputs(" ");
4676                 cmdtxt(np);
4677                 if (sep && np->narg.next)
4678                         cmdputs(" ");
4679         }
4680 }
4681
4682 static void
4683 cmdtxt(union node *n)
4684 {
4685         union node *np;
4686         struct nodelist *lp;
4687         const char *p;
4688
4689         if (!n)
4690                 return;
4691         switch (n->type) {
4692         default:
4693 #if DEBUG
4694                 abort();
4695 #endif
4696         case NPIPE:
4697                 lp = n->npipe.cmdlist;
4698                 for (;;) {
4699                         cmdtxt(lp->n);
4700                         lp = lp->next;
4701                         if (!lp)
4702                                 break;
4703                         cmdputs(" | ");
4704                 }
4705                 break;
4706         case NSEMI:
4707                 p = "; ";
4708                 goto binop;
4709         case NAND:
4710                 p = " && ";
4711                 goto binop;
4712         case NOR:
4713                 p = " || ";
4714  binop:
4715                 cmdtxt(n->nbinary.ch1);
4716                 cmdputs(p);
4717                 n = n->nbinary.ch2;
4718                 goto donode;
4719         case NREDIR:
4720         case NBACKGND:
4721                 n = n->nredir.n;
4722                 goto donode;
4723         case NNOT:
4724                 cmdputs("!");
4725                 n = n->nnot.com;
4726  donode:
4727                 cmdtxt(n);
4728                 break;
4729         case NIF:
4730                 cmdputs("if ");
4731                 cmdtxt(n->nif.test);
4732                 cmdputs("; then ");
4733                 if (n->nif.elsepart) {
4734                         cmdtxt(n->nif.ifpart);
4735                         cmdputs("; else ");
4736                         n = n->nif.elsepart;
4737                 } else {
4738                         n = n->nif.ifpart;
4739                 }
4740                 p = "; fi";
4741                 goto dotail;
4742         case NSUBSHELL:
4743                 cmdputs("(");
4744                 n = n->nredir.n;
4745                 p = ")";
4746                 goto dotail;
4747         case NWHILE:
4748                 p = "while ";
4749                 goto until;
4750         case NUNTIL:
4751                 p = "until ";
4752  until:
4753                 cmdputs(p);
4754                 cmdtxt(n->nbinary.ch1);
4755                 n = n->nbinary.ch2;
4756                 p = "; done";
4757  dodo:
4758                 cmdputs("; do ");
4759  dotail:
4760                 cmdtxt(n);
4761                 goto dotail2;
4762         case NFOR:
4763                 cmdputs("for ");
4764                 cmdputs(n->nfor.var);
4765                 cmdputs(" in ");
4766                 cmdlist(n->nfor.args, 1);
4767                 n = n->nfor.body;
4768                 p = "; done";
4769                 goto dodo;
4770         case NDEFUN:
4771                 cmdputs(n->narg.text);
4772                 p = "() { ... }";
4773                 goto dotail2;
4774         case NCMD:
4775                 cmdlist(n->ncmd.args, 1);
4776                 cmdlist(n->ncmd.redirect, 0);
4777                 break;
4778         case NARG:
4779                 p = n->narg.text;
4780  dotail2:
4781                 cmdputs(p);
4782                 break;
4783         case NHERE:
4784         case NXHERE:
4785                 p = "<<...";
4786                 goto dotail2;
4787         case NCASE:
4788                 cmdputs("case ");
4789                 cmdputs(n->ncase.expr->narg.text);
4790                 cmdputs(" in ");
4791                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4792                         cmdtxt(np->nclist.pattern);
4793                         cmdputs(") ");
4794                         cmdtxt(np->nclist.body);
4795                         cmdputs(";; ");
4796                 }
4797                 p = "esac";
4798                 goto dotail2;
4799         case NTO:
4800                 p = ">";
4801                 goto redir;
4802         case NCLOBBER:
4803                 p = ">|";
4804                 goto redir;
4805         case NAPPEND:
4806                 p = ">>";
4807                 goto redir;
4808 #if BASH_REDIR_OUTPUT
4809         case NTO2:
4810 #endif
4811         case NTOFD:
4812                 p = ">&";
4813                 goto redir;
4814         case NFROM:
4815                 p = "<";
4816                 goto redir;
4817         case NFROMFD:
4818                 p = "<&";
4819                 goto redir;
4820         case NFROMTO:
4821                 p = "<>";
4822  redir:
4823                 cmdputs(utoa(n->nfile.fd));
4824                 cmdputs(p);
4825                 if (n->type == NTOFD || n->type == NFROMFD) {
4826                         cmdputs(utoa(n->ndup.dupfd));
4827                         break;
4828                 }
4829                 n = n->nfile.fname;
4830                 goto donode;
4831         }
4832 }
4833
4834 static char *
4835 commandtext(union node *n)
4836 {
4837         char *name;
4838
4839         STARTSTACKSTR(cmdnextc);
4840         cmdtxt(n);
4841         name = stackblock();
4842         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4843         return ckstrdup(name);
4844 }
4845 #endif /* JOBS */
4846
4847 /*
4848  * Fork off a subshell.  If we are doing job control, give the subshell its
4849  * own process group.  Jp is a job structure that the job is to be added to.
4850  * N is the command that will be evaluated by the child.  Both jp and n may
4851  * be NULL.  The mode parameter can be one of the following:
4852  *      FORK_FG - Fork off a foreground process.
4853  *      FORK_BG - Fork off a background process.
4854  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4855  *                   process group even if job control is on.
4856  *
4857  * When job control is turned off, background processes have their standard
4858  * input redirected to /dev/null (except for the second and later processes
4859  * in a pipeline).
4860  *
4861  * Called with interrupts off.
4862  */
4863 /*
4864  * Clear traps on a fork.
4865  */
4866 static void
4867 clear_traps(void)
4868 {
4869         char **tp;
4870
4871         INT_OFF;
4872         for (tp = trap; tp < &trap[NSIG]; tp++) {
4873                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4874                         if (trap_ptr == trap)
4875                                 free(*tp);
4876                         /* else: it "belongs" to trap_ptr vector, don't free */
4877                         *tp = NULL;
4878                         if ((tp - trap) != 0)
4879                                 setsignal(tp - trap);
4880                 }
4881         }
4882         may_have_traps = 0;
4883         INT_ON;
4884 }
4885
4886 /* Lives far away from here, needed for forkchild */
4887 static void closescript(void);
4888
4889 /* Called after fork(), in child */
4890 /* jp and n are NULL when called by openhere() for heredoc support */
4891 static NOINLINE void
4892 forkchild(struct job *jp, union node *n, int mode)
4893 {
4894         int oldlvl;
4895
4896         TRACE(("Child shell %d\n", getpid()));
4897         oldlvl = shlvl;
4898         shlvl++;
4899
4900         /* man bash: "Non-builtin commands run by bash have signal handlers
4901          * set to the values inherited by the shell from its parent".
4902          * Do we do it correctly? */
4903
4904         closescript();
4905
4906         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4907          && n && n->type == NCMD        /* is it single cmd? */
4908         /* && n->ncmd.args->type == NARG - always true? */
4909          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4910          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4911         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4912         ) {
4913                 TRACE(("Trap hack\n"));
4914                 /* Awful hack for `trap` or $(trap).
4915                  *
4916                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4917                  * contains an example where "trap" is executed in a subshell:
4918                  *
4919                  * save_traps=$(trap)
4920                  * ...
4921                  * eval "$save_traps"
4922                  *
4923                  * Standard does not say that "trap" in subshell shall print
4924                  * parent shell's traps. It only says that its output
4925                  * must have suitable form, but then, in the above example
4926                  * (which is not supposed to be normative), it implies that.
4927                  *
4928                  * bash (and probably other shell) does implement it
4929                  * (traps are reset to defaults, but "trap" still shows them),
4930                  * but as a result, "trap" logic is hopelessly messed up:
4931                  *
4932                  * # trap
4933                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4934                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4935                  * # true | trap   <--- trap is in subshell - no output (ditto)
4936                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4937                  * trap -- 'echo Ho' SIGWINCH
4938                  * # echo `(trap)`         <--- in subshell in subshell - output
4939                  * trap -- 'echo Ho' SIGWINCH
4940                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4941                  * trap -- 'echo Ho' SIGWINCH
4942                  *
4943                  * The rules when to forget and when to not forget traps
4944                  * get really complex and nonsensical.
4945                  *
4946                  * Our solution: ONLY bare $(trap) or `trap` is special.
4947                  */
4948                 /* Save trap handler strings for trap builtin to print */
4949                 trap_ptr = xmemdup(trap, sizeof(trap));
4950                 /* Fall through into clearing traps */
4951         }
4952         clear_traps();
4953 #if JOBS
4954         /* do job control only in root shell */
4955         doing_jobctl = 0;
4956         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4957                 pid_t pgrp;
4958
4959                 if (jp->nprocs == 0)
4960                         pgrp = getpid();
4961                 else
4962                         pgrp = jp->ps[0].ps_pid;
4963                 /* this can fail because we are doing it in the parent also */
4964                 setpgid(0, pgrp);
4965                 if (mode == FORK_FG)
4966                         xtcsetpgrp(ttyfd, pgrp);
4967                 setsignal(SIGTSTP);
4968                 setsignal(SIGTTOU);
4969         } else
4970 #endif
4971         if (mode == FORK_BG) {
4972                 /* man bash: "When job control is not in effect,
4973                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4974                 ignoresig(SIGINT);
4975                 ignoresig(SIGQUIT);
4976                 if (jp->nprocs == 0) {
4977                         close(0);
4978                         if (open(bb_dev_null, O_RDONLY) != 0)
4979                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4980                 }
4981         }
4982         if (oldlvl == 0) {
4983                 if (iflag) { /* why if iflag only? */
4984                         setsignal(SIGINT);
4985                         setsignal(SIGTERM);
4986                 }
4987                 /* man bash:
4988                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4989                  * commands run by bash have signal handlers
4990                  * set to the values inherited by the shell
4991                  * from its parent".
4992                  * Take care of the second rule: */
4993                 setsignal(SIGQUIT);
4994         }
4995 #if JOBS
4996         if (n && n->type == NCMD
4997          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4998         ) {
4999                 TRACE(("Job hack\n"));
5000                 /* "jobs": we do not want to clear job list for it,
5001                  * instead we remove only _its_ own_ job from job list.
5002                  * This makes "jobs .... | cat" more useful.
5003                  */
5004                 freejob(curjob);
5005                 return;
5006         }
5007 #endif
5008         for (jp = curjob; jp; jp = jp->prev_job)
5009                 freejob(jp);
5010         jobless = 0;
5011 }
5012
5013 /* Called after fork(), in parent */
5014 #if !JOBS
5015 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5016 #endif
5017 static void
5018 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5019 {
5020         TRACE(("In parent shell: child = %d\n", pid));
5021         if (!jp) {
5022                 /* jp is NULL when called by openhere() for heredoc support */
5023                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5024                         continue;
5025                 jobless++;
5026                 return;
5027         }
5028 #if JOBS
5029         if (mode != FORK_NOJOB && jp->jobctl) {
5030                 int pgrp;
5031
5032                 if (jp->nprocs == 0)
5033                         pgrp = pid;
5034                 else
5035                         pgrp = jp->ps[0].ps_pid;
5036                 /* This can fail because we are doing it in the child also */
5037                 setpgid(pid, pgrp);
5038         }
5039 #endif
5040         if (mode == FORK_BG) {
5041                 backgndpid = pid;               /* set $! */
5042                 set_curjob(jp, CUR_RUNNING);
5043         }
5044         if (jp) {
5045                 struct procstat *ps = &jp->ps[jp->nprocs++];
5046                 ps->ps_pid = pid;
5047                 ps->ps_status = -1;
5048                 ps->ps_cmd = nullstr;
5049 #if JOBS
5050                 if (doing_jobctl && n)
5051                         ps->ps_cmd = commandtext(n);
5052 #endif
5053         }
5054 }
5055
5056 /* jp and n are NULL when called by openhere() for heredoc support */
5057 static int
5058 forkshell(struct job *jp, union node *n, int mode)
5059 {
5060         int pid;
5061
5062         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5063         pid = fork();
5064         if (pid < 0) {
5065                 TRACE(("Fork failed, errno=%d", errno));
5066                 if (jp)
5067                         freejob(jp);
5068                 ash_msg_and_raise_error("can't fork");
5069         }
5070         if (pid == 0) {
5071                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5072                 forkchild(jp, n, mode);
5073         } else {
5074                 forkparent(jp, n, mode, pid);
5075         }
5076         return pid;
5077 }
5078
5079 /*
5080  * Wait for job to finish.
5081  *
5082  * Under job control we have the problem that while a child process
5083  * is running interrupts generated by the user are sent to the child
5084  * but not to the shell.  This means that an infinite loop started by
5085  * an interactive user may be hard to kill.  With job control turned off,
5086  * an interactive user may place an interactive program inside a loop.
5087  * If the interactive program catches interrupts, the user doesn't want
5088  * these interrupts to also abort the loop.  The approach we take here
5089  * is to have the shell ignore interrupt signals while waiting for a
5090  * foreground process to terminate, and then send itself an interrupt
5091  * signal if the child process was terminated by an interrupt signal.
5092  * Unfortunately, some programs want to do a bit of cleanup and then
5093  * exit on interrupt; unless these processes terminate themselves by
5094  * sending a signal to themselves (instead of calling exit) they will
5095  * confuse this approach.
5096  *
5097  * Called with interrupts off.
5098  */
5099 static int
5100 waitforjob(struct job *jp)
5101 {
5102         int st;
5103
5104         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5105
5106         INT_OFF;
5107         while (jp->state == JOBRUNNING) {
5108                 /* In non-interactive shells, we _can_ get
5109                  * a keyboard signal here and be EINTRed,
5110                  * but we just loop back, waiting for command to complete.
5111                  *
5112                  * man bash:
5113                  * "If bash is waiting for a command to complete and receives
5114                  * a signal for which a trap has been set, the trap
5115                  * will not be executed until the command completes."
5116                  *
5117                  * Reality is that even if trap is not set, bash
5118                  * will not act on the signal until command completes.
5119                  * Try this. sleep5intoff.c:
5120                  * #include <signal.h>
5121                  * #include <unistd.h>
5122                  * int main() {
5123                  *         sigset_t set;
5124                  *         sigemptyset(&set);
5125                  *         sigaddset(&set, SIGINT);
5126                  *         sigaddset(&set, SIGQUIT);
5127                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5128                  *         sleep(5);
5129                  *         return 0;
5130                  * }
5131                  * $ bash -c './sleep5intoff; echo hi'
5132                  * ^C^C^C^C <--- pressing ^C once a second
5133                  * $ _
5134                  * $ bash -c './sleep5intoff; echo hi'
5135                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5136                  * $ _
5137                  */
5138                 dowait(DOWAIT_BLOCK, jp);
5139         }
5140         INT_ON;
5141
5142         st = getstatus(jp);
5143 #if JOBS
5144         if (jp->jobctl) {
5145                 xtcsetpgrp(ttyfd, rootpid);
5146                 restore_tty_if_stopped_or_signaled(jp);
5147
5148                 /*
5149                  * This is truly gross.
5150                  * If we're doing job control, then we did a TIOCSPGRP which
5151                  * caused us (the shell) to no longer be in the controlling
5152                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5153                  * intuit from the subprocess exit status whether a SIGINT
5154                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5155                  */
5156                 if (jp->sigint) /* TODO: do the same with all signals */
5157                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5158         }
5159         if (jp->state == JOBDONE)
5160 #endif
5161                 freejob(jp);
5162         return st;
5163 }
5164
5165 /*
5166  * return 1 if there are stopped jobs, otherwise 0
5167  */
5168 static int
5169 stoppedjobs(void)
5170 {
5171         struct job *jp;
5172         int retval;
5173
5174         retval = 0;
5175         if (job_warning)
5176                 goto out;
5177         jp = curjob;
5178         if (jp && jp->state == JOBSTOPPED) {
5179                 out2str("You have stopped jobs.\n");
5180                 job_warning = 2;
5181                 retval++;
5182         }
5183  out:
5184         return retval;
5185 }
5186
5187
5188 /*
5189  * Code for dealing with input/output redirection.
5190  */
5191
5192 #undef EMPTY
5193 #undef CLOSED
5194 #define EMPTY -2                /* marks an unused slot in redirtab */
5195 #define CLOSED -3               /* marks a slot of previously-closed fd */
5196
5197 /*
5198  * Handle here documents.  Normally we fork off a process to write the
5199  * data to a pipe.  If the document is short, we can stuff the data in
5200  * the pipe without forking.
5201  */
5202 /* openhere needs this forward reference */
5203 static void expandhere(union node *arg, int fd);
5204 static int
5205 openhere(union node *redir)
5206 {
5207         int pip[2];
5208         size_t len = 0;
5209
5210         if (pipe(pip) < 0)
5211                 ash_msg_and_raise_error("pipe call failed");
5212         if (redir->type == NHERE) {
5213                 len = strlen(redir->nhere.doc->narg.text);
5214                 if (len <= PIPE_BUF) {
5215                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5216                         goto out;
5217                 }
5218         }
5219         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5220                 /* child */
5221                 close(pip[0]);
5222                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5223                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5224                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5225                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5226                 signal(SIGPIPE, SIG_DFL);
5227                 if (redir->type == NHERE)
5228                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5229                 else /* NXHERE */
5230                         expandhere(redir->nhere.doc, pip[1]);
5231                 _exit(EXIT_SUCCESS);
5232         }
5233  out:
5234         close(pip[1]);
5235         return pip[0];
5236 }
5237
5238 static int
5239 openredirect(union node *redir)
5240 {
5241         struct stat sb;
5242         char *fname;
5243         int f;
5244
5245         switch (redir->nfile.type) {
5246 /* Can't happen, our single caller does this itself */
5247 //      case NTOFD:
5248 //      case NFROMFD:
5249 //              return -1;
5250         case NHERE:
5251         case NXHERE:
5252                 return openhere(redir);
5253         }
5254
5255         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5256          * allocated space. Do it only when we know it is safe.
5257          */
5258         fname = redir->nfile.expfname;
5259
5260         switch (redir->nfile.type) {
5261         default:
5262 #if DEBUG
5263                 abort();
5264 #endif
5265         case NFROM:
5266                 f = open(fname, O_RDONLY);
5267                 if (f < 0)
5268                         goto eopen;
5269                 break;
5270         case NFROMTO:
5271                 f = open(fname, O_RDWR|O_CREAT, 0666);
5272                 if (f < 0)
5273                         goto ecreate;
5274                 break;
5275         case NTO:
5276 #if BASH_REDIR_OUTPUT
5277         case NTO2:
5278 #endif
5279                 /* Take care of noclobber mode. */
5280                 if (Cflag) {
5281                         if (stat(fname, &sb) < 0) {
5282                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5283                                 if (f < 0)
5284                                         goto ecreate;
5285                         } else if (!S_ISREG(sb.st_mode)) {
5286                                 f = open(fname, O_WRONLY, 0666);
5287                                 if (f < 0)
5288                                         goto ecreate;
5289                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5290                                         close(f);
5291                                         errno = EEXIST;
5292                                         goto ecreate;
5293                                 }
5294                         } else {
5295                                 errno = EEXIST;
5296                                 goto ecreate;
5297                         }
5298                         break;
5299                 }
5300                 /* FALLTHROUGH */
5301         case NCLOBBER:
5302                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5303                 if (f < 0)
5304                         goto ecreate;
5305                 break;
5306         case NAPPEND:
5307                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5308                 if (f < 0)
5309                         goto ecreate;
5310                 break;
5311         }
5312
5313         return f;
5314  ecreate:
5315         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5316  eopen:
5317         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5318 }
5319
5320 /*
5321  * Copy a file descriptor to be >= 10. Throws exception on error.
5322  */
5323 static int
5324 savefd(int from)
5325 {
5326         int newfd;
5327         int err;
5328
5329         newfd = fcntl(from, F_DUPFD, 10);
5330         err = newfd < 0 ? errno : 0;
5331         if (err != EBADF) {
5332                 if (err)
5333                         ash_msg_and_raise_perror("%d", from);
5334                 close(from);
5335                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5336         }
5337
5338         return newfd;
5339 }
5340 static int
5341 dup2_or_raise(int from, int to)
5342 {
5343         int newfd;
5344
5345         newfd = (from != to) ? dup2(from, to) : to;
5346         if (newfd < 0) {
5347                 /* Happens when source fd is not open: try "echo >&99" */
5348                 ash_msg_and_raise_perror("%d", from);
5349         }
5350         return newfd;
5351 }
5352
5353 /* Struct def and variable are moved down to the first usage site */
5354 struct two_fd_t {
5355         int orig, copy;
5356 };
5357 struct redirtab {
5358         struct redirtab *next;
5359         int pair_count;
5360         struct two_fd_t two_fd[];
5361 };
5362 #define redirlist (G_var.redirlist)
5363 enum {
5364         COPYFD_RESTORE = (int)~(INT_MAX),
5365 };
5366
5367 static int
5368 need_to_remember(struct redirtab *rp, int fd)
5369 {
5370         int i;
5371
5372         if (!rp) /* remembering was not requested */
5373                 return 0;
5374
5375         for (i = 0; i < rp->pair_count; i++) {
5376                 if (rp->two_fd[i].orig == fd) {
5377                         /* already remembered */
5378                         return 0;
5379                 }
5380         }
5381         return 1;
5382 }
5383
5384 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5385 static int
5386 is_hidden_fd(struct redirtab *rp, int fd)
5387 {
5388         int i;
5389         struct parsefile *pf;
5390
5391         if (fd == -1)
5392                 return 0;
5393         /* Check open scripts' fds */
5394         pf = g_parsefile;
5395         while (pf) {
5396                 /* We skip pf_fd == 0 case because of the following case:
5397                  * $ ash  # running ash interactively
5398                  * $ . ./script.sh
5399                  * and in script.sh: "exec 9>&0".
5400                  * Even though top-level pf_fd _is_ 0,
5401                  * it's still ok to use it: "read" builtin uses it,
5402                  * why should we cripple "exec" builtin?
5403                  */
5404                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5405                         return 1;
5406                 }
5407                 pf = pf->prev;
5408         }
5409
5410         if (!rp)
5411                 return 0;
5412         /* Check saved fds of redirects */
5413         fd |= COPYFD_RESTORE;
5414         for (i = 0; i < rp->pair_count; i++) {
5415                 if (rp->two_fd[i].copy == fd) {
5416                         return 1;
5417                 }
5418         }
5419         return 0;
5420 }
5421
5422 /*
5423  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5424  * old file descriptors are stashed away so that the redirection can be
5425  * undone by calling popredir.
5426  */
5427 /* flags passed to redirect */
5428 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5429 static void
5430 redirect(union node *redir, int flags)
5431 {
5432         struct redirtab *sv;
5433         int sv_pos;
5434         int fd;
5435         int newfd;
5436
5437         if (!redir)
5438                 return;
5439         sv = NULL;
5440         INT_OFF;
5441         if (flags & REDIR_PUSH)
5442                 sv = redirlist;
5443         sv_pos = 0;
5444         do {
5445                 int right_fd = -1;
5446                 fd = redir->nfile.fd;
5447                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5448                         right_fd = redir->ndup.dupfd;
5449                         //bb_error_msg("doing %d > %d", fd, right_fd);
5450                         /* redirect from/to same file descriptor? */
5451                         if (right_fd == fd)
5452                                 continue;
5453                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5454                         if (is_hidden_fd(sv, right_fd)) {
5455                                 errno = EBADF; /* as if it is closed */
5456                                 ash_msg_and_raise_perror("%d", right_fd);
5457                         }
5458                         newfd = -1;
5459                 } else {
5460                         newfd = openredirect(redir); /* always >= 0 */
5461                         if (fd == newfd) {
5462                                 /* Descriptor wasn't open before redirect.
5463                                  * Mark it for close in the future */
5464                                 if (need_to_remember(sv, fd)) {
5465                                         goto remember_to_close;
5466                                 }
5467                                 continue;
5468                         }
5469                 }
5470 #if BASH_REDIR_OUTPUT
5471  redirect_more:
5472 #endif
5473                 if (need_to_remember(sv, fd)) {
5474                         /* Copy old descriptor */
5475                         /* Careful to not accidentally "save"
5476                          * to the same fd as right side fd in N>&M */
5477                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5478 #if defined(F_DUPFD_CLOEXEC)
5479                         int copy = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5480 #else
5481                         int copy = fcntl(fd, F_DUPFD, minfd);
5482 #endif
5483                         if (copy == -1) {
5484                                 int e = errno;
5485                                 if (e != EBADF) {
5486                                         /* Strange error (e.g. "too many files" EMFILE?) */
5487                                         if (newfd >= 0)
5488                                                 close(newfd);
5489                                         errno = e;
5490                                         ash_msg_and_raise_perror("%d", fd);
5491                                         /* NOTREACHED */
5492                                 }
5493                                 /* EBADF: it is not open - good, remember to close it */
5494  remember_to_close:
5495                                 copy = CLOSED;
5496                         } else { /* fd is open, save its copy */
5497 #if !defined(F_DUPFD_CLOEXEC)
5498                                 fcntl(copy, F_SETFD, FD_CLOEXEC);
5499 #endif
5500                                 /* "exec fd>&-" should not close fds
5501                                  * which point to script file(s).
5502                                  * Force them to be restored afterwards */
5503                                 if (is_hidden_fd(sv, fd))
5504                                         copy |= COPYFD_RESTORE;
5505                         }
5506                         /* if we move stderr, let "set -x" code know */
5507                         if (fd == preverrout_fd)
5508                                 preverrout_fd = copy;
5509                         sv->two_fd[sv_pos].orig = fd;
5510                         sv->two_fd[sv_pos].copy = copy;
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         INT_ON;
5539
5540 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5541 #define REDIR_SAVEFD2 0
5542         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5543         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5544         // not only for calls with flags containing REDIR_SAVEFD2.
5545         // We do this unconditionally (see code above).
5546         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5547         //      preverrout_fd = copied_fd2;
5548 }
5549
5550 static int
5551 redirectsafe(union node *redir, int flags)
5552 {
5553         int err;
5554         volatile int saveint;
5555         struct jmploc *volatile savehandler = exception_handler;
5556         struct jmploc jmploc;
5557
5558         SAVE_INT(saveint);
5559         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5560         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5561         if (!err) {
5562                 exception_handler = &jmploc;
5563                 redirect(redir, flags);
5564         }
5565         exception_handler = savehandler;
5566         if (err && exception_type != EXERROR)
5567                 longjmp(exception_handler->loc, 1);
5568         RESTORE_INT(saveint);
5569         return err;
5570 }
5571
5572 static struct redirtab*
5573 pushredir(union node *redir)
5574 {
5575         struct redirtab *sv;
5576         int i;
5577
5578         if (!redir)
5579                 return redirlist;
5580
5581         i = 0;
5582         do {
5583                 i++;
5584 #if BASH_REDIR_OUTPUT
5585                 if (redir->nfile.type == NTO2)
5586                         i++;
5587 #endif
5588                 redir = redir->nfile.next;
5589         } while (redir);
5590
5591         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5592         sv->pair_count = i;
5593         while (--i >= 0)
5594                 sv->two_fd[i].orig = sv->two_fd[i].copy = EMPTY;
5595         sv->next = redirlist;
5596         redirlist = sv;
5597         return sv->next;
5598 }
5599
5600 /*
5601  * Undo the effects of the last redirection.
5602  */
5603 static void
5604 popredir(int drop, int restore)
5605 {
5606         struct redirtab *rp;
5607         int i;
5608
5609         if (redirlist == NULL)
5610                 return;
5611         INT_OFF;
5612         rp = redirlist;
5613         for (i = 0; i < rp->pair_count; i++) {
5614                 int fd = rp->two_fd[i].orig;
5615                 int copy = rp->two_fd[i].copy;
5616                 if (copy == CLOSED) {
5617                         if (!drop)
5618                                 close(fd);
5619                         continue;
5620                 }
5621                 if (copy != EMPTY) {
5622                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5623                                 copy &= ~COPYFD_RESTORE;
5624                                 /*close(fd);*/
5625                                 dup2_or_raise(copy, fd);
5626                         }
5627                         close(copy & ~COPYFD_RESTORE);
5628                 }
5629         }
5630         redirlist = rp->next;
5631         free(rp);
5632         INT_ON;
5633 }
5634
5635 static void
5636 unwindredir(struct redirtab *stop)
5637 {
5638         while (redirlist != stop)
5639                 popredir(/*drop:*/ 0, /*restore:*/ 0);
5640 }
5641
5642
5643 /* ============ Routines to expand arguments to commands
5644  *
5645  * We have to deal with backquotes, shell variables, and file metacharacters.
5646  */
5647
5648 #if ENABLE_FEATURE_SH_MATH
5649 static arith_t
5650 ash_arith(const char *s)
5651 {
5652         arith_state_t math_state;
5653         arith_t result;
5654
5655         math_state.lookupvar = lookupvar;
5656         math_state.setvar    = setvar0;
5657         //math_state.endofname = endofname;
5658
5659         INT_OFF;
5660         result = arith(&math_state, s);
5661         if (math_state.errmsg)
5662                 ash_msg_and_raise_error(math_state.errmsg);
5663         INT_ON;
5664
5665         return result;
5666 }
5667 #endif
5668
5669 /*
5670  * expandarg flags
5671  */
5672 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5673 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5674 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5675 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5676 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5677  * POSIX says for this case:
5678  *  Pathname expansion shall not be performed on the word by a
5679  *  non-interactive shell; an interactive shell may perform it, but shall
5680  *  do so only when the expansion would result in one word.
5681  * Currently, our code complies to the above rule by never globbing
5682  * redirection filenames.
5683  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5684  * (this means that on a typical Linux distro, bash almost always
5685  * performs globbing, and thus diverges from what we do).
5686  */
5687 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5688 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5689 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5690 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5691 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5692 /*
5693  * rmescape() flags
5694  */
5695 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5696 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5697 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5698 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5699 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5700
5701 /* Add CTLESC when necessary. */
5702 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5703 /* Do not skip NUL characters. */
5704 #define QUOTES_KEEPNUL EXP_TILDE
5705
5706 /*
5707  * Structure specifying which parts of the string should be searched
5708  * for IFS characters.
5709  */
5710 struct ifsregion {
5711         struct ifsregion *next; /* next region in list */
5712         int begoff;             /* offset of start of region */
5713         int endoff;             /* offset of end of region */
5714         int nulonly;            /* search for nul bytes only */
5715 };
5716
5717 struct arglist {
5718         struct strlist *list;
5719         struct strlist **lastp;
5720 };
5721
5722 /* output of current string */
5723 static char *expdest;
5724 /* list of back quote expressions */
5725 static struct nodelist *argbackq;
5726 /* first struct in list of ifs regions */
5727 static struct ifsregion ifsfirst;
5728 /* last struct in list */
5729 static struct ifsregion *ifslastp;
5730 /* holds expanded arg list */
5731 static struct arglist exparg;
5732
5733 /*
5734  * Our own itoa().
5735  * cvtnum() is used even if math support is off (to prepare $? values and such).
5736  */
5737 static int
5738 cvtnum(arith_t num)
5739 {
5740         int len;
5741
5742         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5743         len = sizeof(arith_t) * 3;
5744         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5745         if (sizeof(arith_t) < 4) len += 2;
5746
5747         expdest = makestrspace(len, expdest);
5748         len = fmtstr(expdest, len, ARITH_FMT, num);
5749         STADJUST(len, expdest);
5750         return len;
5751 }
5752
5753 /*
5754  * Break the argument string into pieces based upon IFS and add the
5755  * strings to the argument list.  The regions of the string to be
5756  * searched for IFS characters have been stored by recordregion.
5757  */
5758 static void
5759 ifsbreakup(char *string, struct arglist *arglist)
5760 {
5761         struct ifsregion *ifsp;
5762         struct strlist *sp;
5763         char *start;
5764         char *p;
5765         char *q;
5766         const char *ifs, *realifs;
5767         int ifsspc;
5768         int nulonly;
5769
5770         start = string;
5771         if (ifslastp != NULL) {
5772                 ifsspc = 0;
5773                 nulonly = 0;
5774                 realifs = ifsset() ? ifsval() : defifs;
5775                 ifsp = &ifsfirst;
5776                 do {
5777                         p = string + ifsp->begoff;
5778                         nulonly = ifsp->nulonly;
5779                         ifs = nulonly ? nullstr : realifs;
5780                         ifsspc = 0;
5781                         while (p < string + ifsp->endoff) {
5782                                 q = p;
5783                                 if ((unsigned char)*p == CTLESC)
5784                                         p++;
5785                                 if (!strchr(ifs, *p)) {
5786                                         p++;
5787                                         continue;
5788                                 }
5789                                 if (!nulonly)
5790                                         ifsspc = (strchr(defifs, *p) != NULL);
5791                                 /* Ignore IFS whitespace at start */
5792                                 if (q == start && ifsspc) {
5793                                         p++;
5794                                         start = p;
5795                                         continue;
5796                                 }
5797                                 *q = '\0';
5798                                 sp = stzalloc(sizeof(*sp));
5799                                 sp->text = start;
5800                                 *arglist->lastp = sp;
5801                                 arglist->lastp = &sp->next;
5802                                 p++;
5803                                 if (!nulonly) {
5804                                         for (;;) {
5805                                                 if (p >= string + ifsp->endoff) {
5806                                                         break;
5807                                                 }
5808                                                 q = p;
5809                                                 if ((unsigned char)*p == CTLESC)
5810                                                         p++;
5811                                                 if (strchr(ifs, *p) == NULL) {
5812                                                         p = q;
5813                                                         break;
5814                                                 }
5815                                                 if (strchr(defifs, *p) == NULL) {
5816                                                         if (ifsspc) {
5817                                                                 p++;
5818                                                                 ifsspc = 0;
5819                                                         } else {
5820                                                                 p = q;
5821                                                                 break;
5822                                                         }
5823                                                 } else
5824                                                         p++;
5825                                         }
5826                                 }
5827                                 start = p;
5828                         } /* while */
5829                         ifsp = ifsp->next;
5830                 } while (ifsp != NULL);
5831                 if (nulonly)
5832                         goto add;
5833         }
5834
5835         if (!*start)
5836                 return;
5837
5838  add:
5839         sp = stzalloc(sizeof(*sp));
5840         sp->text = start;
5841         *arglist->lastp = sp;
5842         arglist->lastp = &sp->next;
5843 }
5844
5845 static void
5846 ifsfree(void)
5847 {
5848         struct ifsregion *p = ifsfirst.next;
5849
5850         if (!p)
5851                 goto out;
5852
5853         INT_OFF;
5854         do {
5855                 struct ifsregion *ifsp;
5856                 ifsp = p->next;
5857                 free(p);
5858                 p = ifsp;
5859         } while (p);
5860         ifsfirst.next = NULL;
5861         INT_ON;
5862  out:
5863         ifslastp = NULL;
5864 }
5865
5866 static size_t
5867 esclen(const char *start, const char *p)
5868 {
5869         size_t esc = 0;
5870
5871         while (p > start && (unsigned char)*--p == CTLESC) {
5872                 esc++;
5873         }
5874         return esc;
5875 }
5876
5877 /*
5878  * Remove any CTLESC characters from a string.
5879  */
5880 static char *
5881 rmescapes(char *str, int flag)
5882 {
5883         static const char qchars[] ALIGN1 = {
5884                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5885
5886         char *p, *q, *r;
5887         unsigned inquotes;
5888         unsigned protect_against_glob;
5889         unsigned globbing;
5890         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5891
5892         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5893         if (!p)
5894                 return str;
5895
5896         q = p;
5897         r = str;
5898         if (flag & RMESCAPE_ALLOC) {
5899                 size_t len = p - str;
5900                 size_t fulllen = len + strlen(p) + 1;
5901
5902                 if (flag & RMESCAPE_GROW) {
5903                         int strloc = str - (char *)stackblock();
5904                         r = makestrspace(fulllen, expdest);
5905                         /* p and str may be invalidated by makestrspace */
5906                         str = (char *)stackblock() + strloc;
5907                         p = str + len;
5908                 } else if (flag & RMESCAPE_HEAP) {
5909                         r = ckmalloc(fulllen);
5910                 } else {
5911                         r = stalloc(fulllen);
5912                 }
5913                 q = r;
5914                 if (len > 0) {
5915                         q = (char *)mempcpy(q, str, len);
5916                 }
5917         }
5918
5919         inquotes = 0;
5920         globbing = flag & RMESCAPE_GLOB;
5921         protect_against_glob = globbing;
5922         while (*p) {
5923                 if ((unsigned char)*p == CTLQUOTEMARK) {
5924 // Note: both inquotes and protect_against_glob only affect whether
5925 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5926                         inquotes = ~inquotes;
5927                         p++;
5928                         protect_against_glob = globbing;
5929                         continue;
5930                 }
5931                 if ((unsigned char)*p == CTLESC) {
5932                         p++;
5933 #if DEBUG
5934                         if (*p == '\0')
5935                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5936 #endif
5937                         if (protect_against_glob) {
5938                                 /*
5939                                  * We used to trust glob() and fnmatch() to eat
5940                                  * superfluous escapes (\z where z has no
5941                                  * special meaning anyway). But this causes
5942                                  * bugs such as string of one greek letter rho
5943                                  * (unicode-encoded as two bytes "cf,81")
5944                                  * getting encoded as "cf,CTLESC,81"
5945                                  * and here, converted to "cf,\,81" -
5946                                  * which does not go well with some flavors
5947                                  * of fnmatch() in unicode locales
5948                                  * (for example, glibc <= 2.22).
5949                                  *
5950                                  * Lets add "\" only on the chars which need it.
5951                                  * Testcases for less obvious chars are shown.
5952                                  */
5953                                 if (*p == '*'
5954                                  || *p == '?'
5955                                  || *p == '['
5956                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5957                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5958                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5959                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5960                                 /* Some libc support [^negate], that's why "^" also needs love */
5961                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5962                                 ) {
5963                                         *q++ = '\\';
5964                                 }
5965                         }
5966                 } else if (*p == '\\' && !inquotes) {
5967                         /* naked back slash */
5968                         protect_against_glob = 0;
5969                         goto copy;
5970                 }
5971 #if BASH_PATTERN_SUBST
5972                 else if (*p == '/' && slash) {
5973                         /* stop handling globbing and mark location of slash */
5974                         globbing = slash = 0;
5975                         *p = CTLESC;
5976                 }
5977 #endif
5978                 protect_against_glob = globbing;
5979  copy:
5980                 *q++ = *p++;
5981         }
5982         *q = '\0';
5983         if (flag & RMESCAPE_GROW) {
5984                 expdest = r;
5985                 STADJUST(q - r + 1, expdest);
5986         }
5987         return r;
5988 }
5989 #define pmatch(a, b) !fnmatch((a), (b), 0)
5990
5991 /*
5992  * Prepare a pattern for a expmeta (internal glob(3)) call.
5993  *
5994  * Returns an stalloced string.
5995  */
5996 static char *
5997 preglob(const char *pattern, int flag)
5998 {
5999         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6000 }
6001
6002 /*
6003  * Put a string on the stack.
6004  */
6005 static void
6006 memtodest(const char *p, size_t len, int syntax, int quotes)
6007 {
6008         char *q;
6009
6010         if (!len)
6011                 return;
6012
6013         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6014
6015         do {
6016                 unsigned char c = *p++;
6017                 if (c) {
6018                         if (quotes & QUOTES_ESC) {
6019                                 int n = SIT(c, syntax);
6020                                 if (n == CCTL
6021                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6022                                      && n == CBACK
6023                                     )
6024                                 ) {
6025                                         USTPUTC(CTLESC, q);
6026                                 }
6027                         }
6028                 } else if (!(quotes & QUOTES_KEEPNUL))
6029                         continue;
6030                 USTPUTC(c, q);
6031         } while (--len);
6032
6033         expdest = q;
6034 }
6035
6036 static size_t
6037 strtodest(const char *p, int syntax, int quotes)
6038 {
6039         size_t len = strlen(p);
6040         memtodest(p, len, syntax, quotes);
6041         return len;
6042 }
6043
6044 /*
6045  * Record the fact that we have to scan this region of the
6046  * string for IFS characters.
6047  */
6048 static void
6049 recordregion(int start, int end, int nulonly)
6050 {
6051         struct ifsregion *ifsp;
6052
6053         if (ifslastp == NULL) {
6054                 ifsp = &ifsfirst;
6055         } else {
6056                 INT_OFF;
6057                 ifsp = ckzalloc(sizeof(*ifsp));
6058                 /*ifsp->next = NULL; - ckzalloc did it */
6059                 ifslastp->next = ifsp;
6060                 INT_ON;
6061         }
6062         ifslastp = ifsp;
6063         ifslastp->begoff = start;
6064         ifslastp->endoff = end;
6065         ifslastp->nulonly = nulonly;
6066 }
6067
6068 static void
6069 removerecordregions(int endoff)
6070 {
6071         if (ifslastp == NULL)
6072                 return;
6073
6074         if (ifsfirst.endoff > endoff) {
6075                 while (ifsfirst.next) {
6076                         struct ifsregion *ifsp;
6077                         INT_OFF;
6078                         ifsp = ifsfirst.next->next;
6079                         free(ifsfirst.next);
6080                         ifsfirst.next = ifsp;
6081                         INT_ON;
6082                 }
6083                 if (ifsfirst.begoff > endoff) {
6084                         ifslastp = NULL;
6085                 } else {
6086                         ifslastp = &ifsfirst;
6087                         ifsfirst.endoff = endoff;
6088                 }
6089                 return;
6090         }
6091
6092         ifslastp = &ifsfirst;
6093         while (ifslastp->next && ifslastp->next->begoff < endoff)
6094                 ifslastp = ifslastp->next;
6095         while (ifslastp->next) {
6096                 struct ifsregion *ifsp;
6097                 INT_OFF;
6098                 ifsp = ifslastp->next->next;
6099                 free(ifslastp->next);
6100                 ifslastp->next = ifsp;
6101                 INT_ON;
6102         }
6103         if (ifslastp->endoff > endoff)
6104                 ifslastp->endoff = endoff;
6105 }
6106
6107 static char *
6108 exptilde(char *startp, char *p, int flags)
6109 {
6110         unsigned char c;
6111         char *name;
6112         struct passwd *pw;
6113         const char *home;
6114         int quotes = flags & QUOTES_ESC;
6115
6116         name = p + 1;
6117
6118         while ((c = *++p) != '\0') {
6119                 switch (c) {
6120                 case CTLESC:
6121                         return startp;
6122                 case CTLQUOTEMARK:
6123                         return startp;
6124                 case ':':
6125                         if (flags & EXP_VARTILDE)
6126                                 goto done;
6127                         break;
6128                 case '/':
6129                 case CTLENDVAR:
6130                         goto done;
6131                 }
6132         }
6133  done:
6134         *p = '\0';
6135         if (*name == '\0') {
6136                 home = lookupvar("HOME");
6137         } else {
6138                 pw = getpwnam(name);
6139                 if (pw == NULL)
6140                         goto lose;
6141                 home = pw->pw_dir;
6142         }
6143         if (!home || !*home)
6144                 goto lose;
6145         *p = c;
6146         strtodest(home, SQSYNTAX, quotes);
6147         return p;
6148  lose:
6149         *p = c;
6150         return startp;
6151 }
6152
6153 /*
6154  * Execute a command inside back quotes.  If it's a builtin command, we
6155  * want to save its output in a block obtained from malloc.  Otherwise
6156  * we fork off a subprocess and get the output of the command via a pipe.
6157  * Should be called with interrupts off.
6158  */
6159 struct backcmd {                /* result of evalbackcmd */
6160         int fd;                 /* file descriptor to read from */
6161         int nleft;              /* number of chars in buffer */
6162         char *buf;              /* buffer */
6163         struct job *jp;         /* job structure for command */
6164 };
6165
6166 /* These forward decls are needed to use "eval" code for backticks handling: */
6167 /* flags in argument to evaltree */
6168 #define EV_EXIT    01           /* exit after evaluating tree */
6169 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6170 static int evaltree(union node *, int);
6171
6172 /* An evaltree() which is known to never return.
6173  * Used to use an alias:
6174  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6175  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6176  */
6177 static ALWAYS_INLINE NORETURN void
6178 evaltreenr(union node *n, int flags)
6179 {
6180         evaltree(n, flags);
6181         bb_unreachable(abort());
6182         /* NOTREACHED */
6183 }
6184
6185 static void FAST_FUNC
6186 evalbackcmd(union node *n, struct backcmd *result)
6187 {
6188         int pip[2];
6189         struct job *jp;
6190
6191         result->fd = -1;
6192         result->buf = NULL;
6193         result->nleft = 0;
6194         result->jp = NULL;
6195         if (n == NULL) {
6196                 goto out;
6197         }
6198
6199         if (pipe(pip) < 0)
6200                 ash_msg_and_raise_error("pipe call failed");
6201         jp = makejob(/*n,*/ 1);
6202         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6203                 /* child */
6204                 FORCE_INT_ON;
6205                 close(pip[0]);
6206                 if (pip[1] != 1) {
6207                         /*close(1);*/
6208                         dup2_or_raise(pip[1], 1);
6209                         close(pip[1]);
6210                 }
6211 /* TODO: eflag clearing makes the following not abort:
6212  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6213  * which is what bash does (unless it is in POSIX mode).
6214  * dash deleted "eflag = 0" line in the commit
6215  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6216  *  [EVAL] Don't clear eflag in evalbackcmd
6217  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6218  */
6219                 eflag = 0;
6220                 ifsfree();
6221                 evaltreenr(n, EV_EXIT);
6222                 /* NOTREACHED */
6223         }
6224         /* parent */
6225         close(pip[1]);
6226         result->fd = pip[0];
6227         result->jp = jp;
6228
6229  out:
6230         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6231                 result->fd, result->buf, result->nleft, result->jp));
6232 }
6233
6234 /*
6235  * Expand stuff in backwards quotes.
6236  */
6237 static void
6238 expbackq(union node *cmd, int flag)
6239 {
6240         struct backcmd in;
6241         int i;
6242         char buf[128];
6243         char *p;
6244         char *dest;
6245         int startloc;
6246         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6247         struct stackmark smark;
6248
6249         INT_OFF;
6250         startloc = expdest - (char *)stackblock();
6251         pushstackmark(&smark, startloc);
6252         evalbackcmd(cmd, &in);
6253         popstackmark(&smark);
6254
6255         p = in.buf;
6256         i = in.nleft;
6257         if (i == 0)
6258                 goto read;
6259         for (;;) {
6260                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6261  read:
6262                 if (in.fd < 0)
6263                         break;
6264                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6265                 TRACE(("expbackq: read returns %d\n", i));
6266                 if (i <= 0)
6267                         break;
6268                 p = buf;
6269         }
6270
6271         free(in.buf);
6272         if (in.fd >= 0) {
6273                 close(in.fd);
6274                 back_exitstatus = waitforjob(in.jp);
6275         }
6276         INT_ON;
6277
6278         /* Eat all trailing newlines */
6279         dest = expdest;
6280         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6281                 STUNPUTC(dest);
6282         expdest = dest;
6283
6284         if (!(flag & EXP_QUOTED))
6285                 recordregion(startloc, dest - (char *)stackblock(), 0);
6286         TRACE(("evalbackq: size:%d:'%.*s'\n",
6287                 (int)((dest - (char *)stackblock()) - startloc),
6288                 (int)((dest - (char *)stackblock()) - startloc),
6289                 stackblock() + startloc));
6290 }
6291
6292 #if ENABLE_FEATURE_SH_MATH
6293 /*
6294  * Expand arithmetic expression.  Backup to start of expression,
6295  * evaluate, place result in (backed up) result, adjust string position.
6296  */
6297 static void
6298 expari(int flag)
6299 {
6300         char *p, *start;
6301         int begoff;
6302         int len;
6303
6304         /* ifsfree(); */
6305
6306         /*
6307          * This routine is slightly over-complicated for
6308          * efficiency.  Next we scan backwards looking for the
6309          * start of arithmetic.
6310          */
6311         start = stackblock();
6312         p = expdest - 1;
6313         *p = '\0';
6314         p--;
6315         while (1) {
6316                 int esc;
6317
6318                 while ((unsigned char)*p != CTLARI) {
6319                         p--;
6320 #if DEBUG
6321                         if (p < start) {
6322                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6323                         }
6324 #endif
6325                 }
6326
6327                 esc = esclen(start, p);
6328                 if (!(esc % 2)) {
6329                         break;
6330                 }
6331
6332                 p -= esc + 1;
6333         }
6334
6335         begoff = p - start;
6336
6337         removerecordregions(begoff);
6338
6339         expdest = p;
6340
6341         if (flag & QUOTES_ESC)
6342                 rmescapes(p + 1, 0);
6343
6344         len = cvtnum(ash_arith(p + 1));
6345
6346         if (!(flag & EXP_QUOTED))
6347                 recordregion(begoff, begoff + len, 0);
6348 }
6349 #endif
6350
6351 /* argstr needs it */
6352 static char *evalvar(char *p, int flags);
6353
6354 /*
6355  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6356  * characters to allow for further processing.  Otherwise treat
6357  * $@ like $* since no splitting will be performed.
6358  */
6359 static void
6360 argstr(char *p, int flags)
6361 {
6362         static const char spclchars[] ALIGN1 = {
6363                 '=',
6364                 ':',
6365                 CTLQUOTEMARK,
6366                 CTLENDVAR,
6367                 CTLESC,
6368                 CTLVAR,
6369                 CTLBACKQ,
6370 #if ENABLE_FEATURE_SH_MATH
6371                 CTLENDARI,
6372 #endif
6373                 '\0'
6374         };
6375         const char *reject = spclchars;
6376         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6377         int inquotes;
6378         size_t length;
6379         int startloc;
6380
6381         if (!(flags & EXP_VARTILDE)) {
6382                 reject += 2;
6383         } else if (flags & EXP_VARTILDE2) {
6384                 reject++;
6385         }
6386         inquotes = 0;
6387         length = 0;
6388         if (flags & EXP_TILDE) {
6389                 char *q;
6390
6391                 flags &= ~EXP_TILDE;
6392  tilde:
6393                 q = p;
6394                 if (*q == '~')
6395                         p = exptilde(p, q, flags);
6396         }
6397  start:
6398         startloc = expdest - (char *)stackblock();
6399         for (;;) {
6400                 unsigned char c;
6401
6402                 length += strcspn(p + length, reject);
6403                 c = p[length];
6404                 if (c) {
6405                         if (!(c & 0x80)
6406                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6407                         ) {
6408                                 /* c == '=' || c == ':' || c == CTLENDARI */
6409                                 length++;
6410                         }
6411                 }
6412                 if (length > 0) {
6413                         int newloc;
6414                         expdest = stack_nputstr(p, length, expdest);
6415                         newloc = expdest - (char *)stackblock();
6416                         if (breakall && !inquotes && newloc > startloc) {
6417                                 recordregion(startloc, newloc, 0);
6418                         }
6419                         startloc = newloc;
6420                 }
6421                 p += length + 1;
6422                 length = 0;
6423
6424                 switch (c) {
6425                 case '\0':
6426                         goto breakloop;
6427                 case '=':
6428                         if (flags & EXP_VARTILDE2) {
6429                                 p--;
6430                                 continue;
6431                         }
6432                         flags |= EXP_VARTILDE2;
6433                         reject++;
6434                         /* fall through */
6435                 case ':':
6436                         /*
6437                          * sort of a hack - expand tildes in variable
6438                          * assignments (after the first '=' and after ':'s).
6439                          */
6440                         if (*--p == '~') {
6441                                 goto tilde;
6442                         }
6443                         continue;
6444                 }
6445
6446                 switch (c) {
6447                 case CTLENDVAR: /* ??? */
6448                         goto breakloop;
6449                 case CTLQUOTEMARK:
6450                         inquotes ^= EXP_QUOTED;
6451                         /* "$@" syntax adherence hack */
6452                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6453                                 p = evalvar(p + 1, flags | inquotes) + 1;
6454                                 goto start;
6455                         }
6456  addquote:
6457                         if (flags & QUOTES_ESC) {
6458                                 p--;
6459                                 length++;
6460                                 startloc++;
6461                         }
6462                         break;
6463                 case CTLESC:
6464                         startloc++;
6465                         length++;
6466
6467                         /*
6468                          * Quoted parameter expansion pattern: remove quote
6469                          * unless inside inner quotes or we have a literal
6470                          * backslash.
6471                          */
6472                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6473                             EXP_QPAT && *p != '\\')
6474                                 break;
6475
6476                         goto addquote;
6477                 case CTLVAR:
6478                         TRACE(("argstr: evalvar('%s')\n", p));
6479                         p = evalvar(p, flags | inquotes);
6480                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6481                         goto start;
6482                 case CTLBACKQ:
6483                         expbackq(argbackq->n, flags | inquotes);
6484                         argbackq = argbackq->next;
6485                         goto start;
6486 #if ENABLE_FEATURE_SH_MATH
6487                 case CTLENDARI:
6488                         p--;
6489                         expari(flags | inquotes);
6490                         goto start;
6491 #endif
6492                 }
6493         }
6494  breakloop: ;
6495 }
6496
6497 static char *
6498 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6499                 char *pattern, int quotes, int zero)
6500 {
6501         char *loc, *loc2;
6502         char c;
6503
6504         loc = startp;
6505         loc2 = rmesc;
6506         do {
6507                 int match;
6508                 const char *s = loc2;
6509
6510                 c = *loc2;
6511                 if (zero) {
6512                         *loc2 = '\0';
6513                         s = rmesc;
6514                 }
6515                 match = pmatch(pattern, s);
6516
6517                 *loc2 = c;
6518                 if (match)
6519                         return loc;
6520                 if (quotes && (unsigned char)*loc == CTLESC)
6521                         loc++;
6522                 loc++;
6523                 loc2++;
6524         } while (c);
6525         return NULL;
6526 }
6527
6528 static char *
6529 scanright(char *startp, char *rmesc, char *rmescend,
6530                 char *pattern, int quotes, int match_at_start)
6531 {
6532 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6533         int try2optimize = match_at_start;
6534 #endif
6535         int esc = 0;
6536         char *loc;
6537         char *loc2;
6538
6539         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6540          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6541          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6542          * Logic:
6543          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6544          * and on each iteration they go back two/one char until they reach the beginning.
6545          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6546          */
6547         /* TODO: document in what other circumstances we are called. */
6548
6549         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6550                 int match;
6551                 char c = *loc2;
6552                 const char *s = loc2;
6553                 if (match_at_start) {
6554                         *loc2 = '\0';
6555                         s = rmesc;
6556                 }
6557                 match = pmatch(pattern, s);
6558                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6559                 *loc2 = c;
6560                 if (match)
6561                         return loc;
6562 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6563                 if (try2optimize) {
6564                         /* Maybe we can optimize this:
6565                          * if pattern ends with unescaped *, we can avoid checking
6566                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6567                          * it won't match truncated "raw_value_of_" strings too.
6568                          */
6569                         unsigned plen = strlen(pattern);
6570                         /* Does it end with "*"? */
6571                         if (plen != 0 && pattern[--plen] == '*') {
6572                                 /* "xxxx*" is not escaped */
6573                                 /* "xxx\*" is escaped */
6574                                 /* "xx\\*" is not escaped */
6575                                 /* "x\\\*" is escaped */
6576                                 int slashes = 0;
6577                                 while (plen != 0 && pattern[--plen] == '\\')
6578                                         slashes++;
6579                                 if (!(slashes & 1))
6580                                         break; /* ends with unescaped "*" */
6581                         }
6582                         try2optimize = 0;
6583                 }
6584 #endif
6585                 loc--;
6586                 if (quotes) {
6587                         if (--esc < 0) {
6588                                 esc = esclen(startp, loc);
6589                         }
6590                         if (esc % 2) {
6591                                 esc--;
6592                                 loc--;
6593                         }
6594                 }
6595         }
6596         return NULL;
6597 }
6598
6599 static void varunset(const char *, const char *, const char *, int) NORETURN;
6600 static void
6601 varunset(const char *end, const char *var, const char *umsg, int varflags)
6602 {
6603         const char *msg;
6604         const char *tail;
6605
6606         tail = nullstr;
6607         msg = "parameter not set";
6608         if (umsg) {
6609                 if ((unsigned char)*end == CTLENDVAR) {
6610                         if (varflags & VSNUL)
6611                                 tail = " or null";
6612                 } else {
6613                         msg = umsg;
6614                 }
6615         }
6616         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6617 }
6618
6619 static const char *
6620 subevalvar(char *p, char *varname, int strloc, int subtype,
6621                 int startloc, int varflags, int flag)
6622 {
6623         struct nodelist *saveargbackq = argbackq;
6624         int quotes = flag & QUOTES_ESC;
6625         char *startp;
6626         char *loc;
6627         char *rmesc, *rmescend;
6628         char *str;
6629         int amount, resetloc;
6630         IF_BASH_PATTERN_SUBST(int workloc;)
6631         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6632         int zero;
6633         char *(*scan)(char*, char*, char*, char*, int, int);
6634
6635         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6636         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6637
6638         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6639                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6640         );
6641         STPUTC('\0', expdest);
6642         argbackq = saveargbackq;
6643         startp = (char *)stackblock() + startloc;
6644
6645         switch (subtype) {
6646         case VSASSIGN:
6647                 setvar0(varname, startp);
6648                 amount = startp - expdest;
6649                 STADJUST(amount, expdest);
6650                 return startp;
6651
6652         case VSQUESTION:
6653                 varunset(p, varname, startp, varflags);
6654                 /* NOTREACHED */
6655
6656 #if BASH_SUBSTR
6657         case VSSUBSTR: {
6658                 int pos, len, orig_len;
6659                 char *colon;
6660
6661                 loc = str = stackblock() + strloc;
6662
6663 # if !ENABLE_FEATURE_SH_MATH
6664 #  define ash_arith number
6665 # endif
6666                 /* Read POS in ${var:POS:LEN} */
6667                 colon = strchr(loc, ':');
6668                 if (colon) *colon = '\0';
6669                 pos = ash_arith(loc);
6670                 if (colon) *colon = ':';
6671
6672                 /* Read LEN in ${var:POS:LEN} */
6673                 len = str - startp - 1;
6674                 /* *loc != '\0', guaranteed by parser */
6675                 if (quotes) {
6676                         char *ptr;
6677
6678                         /* Adjust the length by the number of escapes */
6679                         for (ptr = startp; ptr < (str - 1); ptr++) {
6680                                 if ((unsigned char)*ptr == CTLESC) {
6681                                         len--;
6682                                         ptr++;
6683                                 }
6684                         }
6685                 }
6686                 orig_len = len;
6687                 if (*loc++ == ':') {
6688                         /* ${var::LEN} */
6689                         len = ash_arith(loc);
6690                 } else {
6691                         /* Skip POS in ${var:POS:LEN} */
6692                         len = orig_len;
6693                         while (*loc && *loc != ':') {
6694                                 loc++;
6695                         }
6696                         if (*loc++ == ':') {
6697                                 len = ash_arith(loc);
6698                         }
6699                 }
6700 #  undef ash_arith
6701
6702                 if (pos < 0) {
6703                         /* ${VAR:$((-n)):l} starts n chars from the end */
6704                         pos = orig_len + pos;
6705                 }
6706                 if ((unsigned)pos >= orig_len) {
6707                         /* apart from obvious ${VAR:999999:l},
6708                          * covers ${VAR:$((-9999999)):l} - result is ""
6709                          * (bash compat)
6710                          */
6711                         pos = 0;
6712                         len = 0;
6713                 }
6714                 if (len < 0) {
6715                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6716                         len = (orig_len - pos) + len;
6717                 }
6718                 if ((unsigned)len > (orig_len - pos))
6719                         len = orig_len - pos;
6720
6721                 for (str = startp; pos; str++, pos--) {
6722                         if (quotes && (unsigned char)*str == CTLESC)
6723                                 str++;
6724                 }
6725                 for (loc = startp; len; len--) {
6726                         if (quotes && (unsigned char)*str == CTLESC)
6727                                 *loc++ = *str++;
6728                         *loc++ = *str++;
6729                 }
6730                 *loc = '\0';
6731                 amount = loc - expdest;
6732                 STADJUST(amount, expdest);
6733                 return loc;
6734         }
6735 #endif /* BASH_SUBSTR */
6736         }
6737
6738         resetloc = expdest - (char *)stackblock();
6739
6740 #if BASH_PATTERN_SUBST
6741         /* We'll comeback here if we grow the stack while handling
6742          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6743          * stack will need rebasing, and we'll need to remove our work
6744          * areas each time
6745          */
6746  restart:
6747 #endif
6748
6749         amount = expdest - ((char *)stackblock() + resetloc);
6750         STADJUST(-amount, expdest);
6751         startp = (char *)stackblock() + startloc;
6752
6753         rmesc = startp;
6754         rmescend = (char *)stackblock() + strloc;
6755         if (quotes) {
6756                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6757                 if (rmesc != startp) {
6758                         rmescend = expdest;
6759                         startp = (char *)stackblock() + startloc;
6760                 }
6761         }
6762         rmescend--;
6763         str = (char *)stackblock() + strloc;
6764         /*
6765          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6766          * The result is a_\_z_c (not a\_\_z_c)!
6767          *
6768          * The search pattern and replace string treat backslashes differently!
6769          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6770          * and string.  It's only used on the first call.
6771          */
6772         preglob(str, IF_BASH_PATTERN_SUBST(
6773                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6774                         RMESCAPE_SLASH : ) 0);
6775
6776 #if BASH_PATTERN_SUBST
6777         workloc = expdest - (char *)stackblock();
6778         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6779                 int len;
6780                 char *idx, *end;
6781
6782                 if (!repl) {
6783                         repl = strchr(str, CTLESC);
6784                         if (repl)
6785                                 *repl++ = '\0';
6786                         else
6787                                 repl = nullstr;
6788                 }
6789                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6790
6791                 /* If there's no pattern to match, return the expansion unmolested */
6792                 if (str[0] == '\0')
6793                         return NULL;
6794
6795                 len = 0;
6796                 idx = startp;
6797                 end = str - 1;
6798                 while (idx < end) {
6799  try_to_match:
6800                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6801                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6802                         if (!loc) {
6803                                 /* No match, advance */
6804                                 char *restart_detect = stackblock();
6805  skip_matching:
6806                                 STPUTC(*idx, expdest);
6807                                 if (quotes && (unsigned char)*idx == CTLESC) {
6808                                         idx++;
6809                                         len++;
6810                                         STPUTC(*idx, expdest);
6811                                 }
6812                                 if (stackblock() != restart_detect)
6813                                         goto restart;
6814                                 idx++;
6815                                 len++;
6816                                 rmesc++;
6817                                 /* continue; - prone to quadratic behavior, smarter code: */
6818                                 if (idx >= end)
6819                                         break;
6820                                 if (str[0] == '*') {
6821                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6822                                          * it would never match "ong_string" etc, no point in trying.
6823                                          */
6824                                         goto skip_matching;
6825                                 }
6826                                 goto try_to_match;
6827                         }
6828
6829                         if (subtype == VSREPLACEALL) {
6830                                 while (idx < loc) {
6831                                         if (quotes && (unsigned char)*idx == CTLESC)
6832                                                 idx++;
6833                                         idx++;
6834                                         rmesc++;
6835                                 }
6836                         } else {
6837                                 idx = loc;
6838                         }
6839
6840                         //bb_error_msg("repl:'%s'", repl);
6841                         for (loc = (char*)repl; *loc; loc++) {
6842                                 char *restart_detect = stackblock();
6843                                 if (quotes && *loc == '\\') {
6844                                         STPUTC(CTLESC, expdest);
6845                                         len++;
6846                                 }
6847                                 STPUTC(*loc, expdest);
6848                                 if (stackblock() != restart_detect)
6849                                         goto restart;
6850                                 len++;
6851                         }
6852
6853                         if (subtype == VSREPLACE) {
6854                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6855                                 while (*idx) {
6856                                         char *restart_detect = stackblock();
6857                                         STPUTC(*idx, expdest);
6858                                         if (stackblock() != restart_detect)
6859                                                 goto restart;
6860                                         len++;
6861                                         idx++;
6862                                 }
6863                                 break;
6864                         }
6865                 }
6866
6867                 /* We've put the replaced text into a buffer at workloc, now
6868                  * move it to the right place and adjust the stack.
6869                  */
6870                 STPUTC('\0', expdest);
6871                 startp = (char *)stackblock() + startloc;
6872                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6873                 //bb_error_msg("startp:'%s'", startp);
6874                 amount = expdest - (startp + len);
6875                 STADJUST(-amount, expdest);
6876                 return startp;
6877         }
6878 #endif /* BASH_PATTERN_SUBST */
6879
6880         subtype -= VSTRIMRIGHT;
6881 #if DEBUG
6882         if (subtype < 0 || subtype > 7)
6883                 abort();
6884 #endif
6885         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6886         zero = subtype >> 1;
6887         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6888         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6889
6890         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6891         if (loc) {
6892                 if (zero) {
6893                         memmove(startp, loc, str - loc);
6894                         loc = startp + (str - loc) - 1;
6895                 }
6896                 *loc = '\0';
6897                 amount = loc - expdest;
6898                 STADJUST(amount, expdest);
6899         }
6900         return loc;
6901 }
6902
6903 /*
6904  * Add the value of a specialized variable to the stack string.
6905  * name parameter (examples):
6906  * ash -c 'echo $1'      name:'1='
6907  * ash -c 'echo $qwe'    name:'qwe='
6908  * ash -c 'echo $$'      name:'$='
6909  * ash -c 'echo ${$}'    name:'$='
6910  * ash -c 'echo ${$##q}' name:'$=q'
6911  * ash -c 'echo ${#$}'   name:'$='
6912  * note: examples with bad shell syntax:
6913  * ash -c 'echo ${#$1}'  name:'$=1'
6914  * ash -c 'echo ${#1#}'  name:'1=#'
6915  */
6916 static NOINLINE ssize_t
6917 varvalue(char *name, int varflags, int flags, int *quotedp)
6918 {
6919         const char *p;
6920         int num;
6921         int i;
6922         ssize_t len = 0;
6923         int sep;
6924         int quoted = *quotedp;
6925         int subtype = varflags & VSTYPE;
6926         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6927         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6928         int syntax;
6929
6930         sep = (flags & EXP_FULL) << CHAR_BIT;
6931         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6932
6933         switch (*name) {
6934         case '$':
6935                 num = rootpid;
6936                 goto numvar;
6937         case '?':
6938                 num = exitstatus;
6939                 goto numvar;
6940         case '#':
6941                 num = shellparam.nparam;
6942                 goto numvar;
6943         case '!':
6944                 num = backgndpid;
6945                 if (num == 0)
6946                         return -1;
6947  numvar:
6948                 len = cvtnum(num);
6949                 goto check_1char_name;
6950         case '-':
6951                 expdest = makestrspace(NOPTS, expdest);
6952                 for (i = NOPTS - 1; i >= 0; i--) {
6953                         if (optlist[i]) {
6954                                 USTPUTC(optletters(i), expdest);
6955                                 len++;
6956                         }
6957                 }
6958  check_1char_name:
6959 #if 0
6960                 /* handles cases similar to ${#$1} */
6961                 if (name[2] != '\0')
6962                         raise_error_syntax("bad substitution");
6963 #endif
6964                 break;
6965         case '@':
6966                 if (quoted && sep)
6967                         goto param;
6968                 /* fall through */
6969         case '*': {
6970                 char **ap;
6971                 char sepc;
6972
6973                 if (quoted)
6974                         sep = 0;
6975                 sep |= ifsset() ? ifsval()[0] : ' ';
6976  param:
6977                 sepc = sep;
6978                 *quotedp = !sepc;
6979                 ap = shellparam.p;
6980                 if (!ap)
6981                         return -1;
6982                 while ((p = *ap++) != NULL) {
6983                         len += strtodest(p, syntax, quotes);
6984
6985                         if (*ap && sep) {
6986                                 len++;
6987                                 memtodest(&sepc, 1, syntax, quotes);
6988                         }
6989                 }
6990                 break;
6991         } /* case '*' */
6992         case '0':
6993         case '1':
6994         case '2':
6995         case '3':
6996         case '4':
6997         case '5':
6998         case '6':
6999         case '7':
7000         case '8':
7001         case '9':
7002                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7003                 if (num < 0 || num > shellparam.nparam)
7004                         return -1;
7005                 p = num ? shellparam.p[num - 1] : arg0;
7006                 goto value;
7007         default:
7008                 /* NB: name has form "VAR=..." */
7009                 p = lookupvar(name);
7010  value:
7011                 if (!p)
7012                         return -1;
7013
7014                 len = strtodest(p, syntax, quotes);
7015 #if ENABLE_UNICODE_SUPPORT
7016                 if (subtype == VSLENGTH && len > 0) {
7017                         reinit_unicode_for_ash();
7018                         if (unicode_status == UNICODE_ON) {
7019                                 STADJUST(-len, expdest);
7020                                 discard = 0;
7021                                 len = unicode_strlen(p);
7022                         }
7023                 }
7024 #endif
7025                 break;
7026         }
7027
7028         if (discard)
7029                 STADJUST(-len, expdest);
7030         return len;
7031 }
7032
7033 /*
7034  * Expand a variable, and return a pointer to the next character in the
7035  * input string.
7036  */
7037 static char *
7038 evalvar(char *p, int flag)
7039 {
7040         char varflags;
7041         char subtype;
7042         int quoted;
7043         char easy;
7044         char *var;
7045         int patloc;
7046         int startloc;
7047         ssize_t varlen;
7048
7049         varflags = (unsigned char) *p++;
7050         subtype = varflags & VSTYPE;
7051
7052         if (!subtype)
7053                 raise_error_syntax("bad substitution");
7054
7055         quoted = flag & EXP_QUOTED;
7056         var = p;
7057         easy = (!quoted || (*var == '@' && shellparam.nparam));
7058         startloc = expdest - (char *)stackblock();
7059         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7060
7061  again:
7062         varlen = varvalue(var, varflags, flag, &quoted);
7063         if (varflags & VSNUL)
7064                 varlen--;
7065
7066         if (subtype == VSPLUS) {
7067                 varlen = -1 - varlen;
7068                 goto vsplus;
7069         }
7070
7071         if (subtype == VSMINUS) {
7072  vsplus:
7073                 if (varlen < 0) {
7074                         argstr(
7075                                 p,
7076                                 flag | EXP_TILDE | EXP_WORD
7077                         );
7078                         goto end;
7079                 }
7080                 goto record;
7081         }
7082
7083         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7084                 if (varlen >= 0)
7085                         goto record;
7086
7087                 subevalvar(p, var, 0, subtype, startloc, varflags,
7088                            flag & ~QUOTES_ESC);
7089                 varflags &= ~VSNUL;
7090                 /*
7091                  * Remove any recorded regions beyond
7092                  * start of variable
7093                  */
7094                 removerecordregions(startloc);
7095                 goto again;
7096         }
7097
7098         if (varlen < 0 && uflag)
7099                 varunset(p, var, 0, 0);
7100
7101         if (subtype == VSLENGTH) {
7102                 cvtnum(varlen > 0 ? varlen : 0);
7103                 goto record;
7104         }
7105
7106         if (subtype == VSNORMAL) {
7107  record:
7108                 if (!easy)
7109                         goto end;
7110                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7111                 goto end;
7112         }
7113
7114 #if DEBUG
7115         switch (subtype) {
7116         case VSTRIMLEFT:
7117         case VSTRIMLEFTMAX:
7118         case VSTRIMRIGHT:
7119         case VSTRIMRIGHTMAX:
7120 #if BASH_SUBSTR
7121         case VSSUBSTR:
7122 #endif
7123 #if BASH_PATTERN_SUBST
7124         case VSREPLACE:
7125         case VSREPLACEALL:
7126 #endif
7127                 break;
7128         default:
7129                 abort();
7130         }
7131 #endif
7132
7133         if (varlen >= 0) {
7134                 /*
7135                  * Terminate the string and start recording the pattern
7136                  * right after it
7137                  */
7138                 STPUTC('\0', expdest);
7139                 patloc = expdest - (char *)stackblock();
7140                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7141                                 startloc, varflags, flag)) {
7142                         int amount = expdest - (
7143                                 (char *)stackblock() + patloc - 1
7144                         );
7145                         STADJUST(-amount, expdest);
7146                 }
7147                 /* Remove any recorded regions beyond start of variable */
7148                 removerecordregions(startloc);
7149                 goto record;
7150         }
7151
7152  end:
7153         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7154                 int nesting = 1;
7155                 for (;;) {
7156                         unsigned char c = *p++;
7157                         if (c == CTLESC)
7158                                 p++;
7159                         else if (c == CTLBACKQ) {
7160                                 if (varlen >= 0)
7161                                         argbackq = argbackq->next;
7162                         } else if (c == CTLVAR) {
7163                                 if ((*p++ & VSTYPE) != VSNORMAL)
7164                                         nesting++;
7165                         } else if (c == CTLENDVAR) {
7166                                 if (--nesting == 0)
7167                                         break;
7168                         }
7169                 }
7170         }
7171         return p;
7172 }
7173
7174 /*
7175  * Add a file name to the list.
7176  */
7177 static void
7178 addfname(const char *name)
7179 {
7180         struct strlist *sp;
7181
7182         sp = stzalloc(sizeof(*sp));
7183         sp->text = sstrdup(name);
7184         *exparg.lastp = sp;
7185         exparg.lastp = &sp->next;
7186 }
7187
7188 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7189 static int
7190 hasmeta(const char *p)
7191 {
7192         static const char chars[] ALIGN1 = {
7193                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7194         };
7195
7196         for (;;) {
7197                 p = strpbrk(p, chars);
7198                 if (!p)
7199                         break;
7200                 switch ((unsigned char) *p) {
7201                 case CTLQUOTEMARK:
7202                         for (;;) {
7203                                 p++;
7204                                 if (*p == CTLQUOTEMARK)
7205                                         break;
7206                                 if (*p == CTLESC)
7207                                         p++;
7208                                 if (*p == '\0') /* huh? */
7209                                         return 0;
7210                         }
7211                         break;
7212                 case '\\':
7213                 case CTLESC:
7214                         p++;
7215                         if (*p == '\0')
7216                                 return 0;
7217                         break;
7218                 case '[':
7219                         if (!strchr(p + 1, ']')) {
7220                                 /* It's not a properly closed [] pattern,
7221                                  * but other metas may follow. Continue checking.
7222                                  * my[file* _is_ globbed by bash
7223                                  * and matches filenames like "my[file1".
7224                                  */
7225                                 break;
7226                         }
7227                         /* fallthrough */
7228                 default:
7229                 /* case '*': */
7230                 /* case '?': */
7231                         return 1;
7232                 }
7233                 p++;
7234         }
7235
7236         return 0;
7237 }
7238
7239 /* If we want to use glob() from libc... */
7240 #if !ENABLE_ASH_INTERNAL_GLOB
7241
7242 /* Add the result of glob() to the list */
7243 static void
7244 addglob(const glob_t *pglob)
7245 {
7246         char **p = pglob->gl_pathv;
7247
7248         do {
7249                 addfname(*p);
7250         } while (*++p);
7251 }
7252 static void
7253 expandmeta(struct strlist *str /*, int flag*/)
7254 {
7255         /* TODO - EXP_REDIR */
7256
7257         while (str) {
7258                 char *p;
7259                 glob_t pglob;
7260                 int i;
7261
7262                 if (fflag)
7263                         goto nometa;
7264
7265                 if (!hasmeta(str->text))
7266                         goto nometa;
7267
7268                 INT_OFF;
7269                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7270 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7271 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7272 //
7273 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7274 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7275 // Which means you need to unescape the string, right? Not so fast:
7276 // if there _is_ a file named "file\?" (with backslash), it is returned
7277 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7278 // You DON'T KNOW by looking at the result whether you need to unescape it.
7279 //
7280 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7281 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7282 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7283 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7284 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7285 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7286                 i = glob(p, 0, NULL, &pglob);
7287                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7288                 if (p != str->text)
7289                         free(p);
7290                 switch (i) {
7291                 case 0:
7292 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7293                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7294                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7295                                 goto nometa2;
7296 #endif
7297                         addglob(&pglob);
7298                         globfree(&pglob);
7299                         INT_ON;
7300                         break;
7301                 case GLOB_NOMATCH:
7302  //nometa2:
7303                         globfree(&pglob);
7304                         INT_ON;
7305  nometa:
7306                         *exparg.lastp = str;
7307                         rmescapes(str->text, 0);
7308                         exparg.lastp = &str->next;
7309                         break;
7310                 default:        /* GLOB_NOSPACE */
7311                         globfree(&pglob);
7312                         INT_ON;
7313                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7314                 }
7315                 str = str->next;
7316         }
7317 }
7318
7319 #else
7320 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7321
7322 /*
7323  * Do metacharacter (i.e. *, ?, [...]) expansion.
7324  */
7325 static void
7326 expmeta(char *expdir, char *enddir, char *name)
7327 {
7328         char *p;
7329         const char *cp;
7330         char *start;
7331         char *endname;
7332         int metaflag;
7333         struct stat statb;
7334         DIR *dirp;
7335         struct dirent *dp;
7336         int atend;
7337         int matchdot;
7338         int esc;
7339
7340         metaflag = 0;
7341         start = name;
7342         for (p = name; esc = 0, *p; p += esc + 1) {
7343                 if (*p == '*' || *p == '?')
7344                         metaflag = 1;
7345                 else if (*p == '[') {
7346                         char *q = p + 1;
7347                         if (*q == '!')
7348                                 q++;
7349                         for (;;) {
7350                                 if (*q == '\\')
7351                                         q++;
7352                                 if (*q == '/' || *q == '\0')
7353                                         break;
7354                                 if (*++q == ']') {
7355                                         metaflag = 1;
7356                                         break;
7357                                 }
7358                         }
7359                 } else {
7360                         if (*p == '\\')
7361                                 esc++;
7362                         if (p[esc] == '/') {
7363                                 if (metaflag)
7364                                         break;
7365                                 start = p + esc + 1;
7366                         }
7367                 }
7368         }
7369         if (metaflag == 0) {    /* we've reached the end of the file name */
7370                 if (enddir != expdir)
7371                         metaflag++;
7372                 p = name;
7373                 do {
7374                         if (*p == '\\')
7375                                 p++;
7376                         *enddir++ = *p;
7377                 } while (*p++);
7378                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7379                         addfname(expdir);
7380                 return;
7381         }
7382         endname = p;
7383         if (name < start) {
7384                 p = name;
7385                 do {
7386                         if (*p == '\\')
7387                                 p++;
7388                         *enddir++ = *p++;
7389                 } while (p < start);
7390         }
7391         if (enddir == expdir) {
7392                 cp = ".";
7393         } else if (enddir == expdir + 1 && *expdir == '/') {
7394                 cp = "/";
7395         } else {
7396                 cp = expdir;
7397                 enddir[-1] = '\0';
7398         }
7399         dirp = opendir(cp);
7400         if (dirp == NULL)
7401                 return;
7402         if (enddir != expdir)
7403                 enddir[-1] = '/';
7404         if (*endname == 0) {
7405                 atend = 1;
7406         } else {
7407                 atend = 0;
7408                 *endname = '\0';
7409                 endname += esc + 1;
7410         }
7411         matchdot = 0;
7412         p = start;
7413         if (*p == '\\')
7414                 p++;
7415         if (*p == '.')
7416                 matchdot++;
7417         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7418                 if (dp->d_name[0] == '.' && !matchdot)
7419                         continue;
7420                 if (pmatch(start, dp->d_name)) {
7421                         if (atend) {
7422                                 strcpy(enddir, dp->d_name);
7423                                 addfname(expdir);
7424                         } else {
7425                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7426                                         continue;
7427                                 p[-1] = '/';
7428                                 expmeta(expdir, p, endname);
7429                         }
7430                 }
7431         }
7432         closedir(dirp);
7433         if (!atend)
7434                 endname[-esc - 1] = esc ? '\\' : '/';
7435 }
7436
7437 static struct strlist *
7438 msort(struct strlist *list, int len)
7439 {
7440         struct strlist *p, *q = NULL;
7441         struct strlist **lpp;
7442         int half;
7443         int n;
7444
7445         if (len <= 1)
7446                 return list;
7447         half = len >> 1;
7448         p = list;
7449         for (n = half; --n >= 0;) {
7450                 q = p;
7451                 p = p->next;
7452         }
7453         q->next = NULL;                 /* terminate first half of list */
7454         q = msort(list, half);          /* sort first half of list */
7455         p = msort(p, len - half);               /* sort second half */
7456         lpp = &list;
7457         for (;;) {
7458 #if ENABLE_LOCALE_SUPPORT
7459                 if (strcoll(p->text, q->text) < 0)
7460 #else
7461                 if (strcmp(p->text, q->text) < 0)
7462 #endif
7463                                                 {
7464                         *lpp = p;
7465                         lpp = &p->next;
7466                         p = *lpp;
7467                         if (p == NULL) {
7468                                 *lpp = q;
7469                                 break;
7470                         }
7471                 } else {
7472                         *lpp = q;
7473                         lpp = &q->next;
7474                         q = *lpp;
7475                         if (q == NULL) {
7476                                 *lpp = p;
7477                                 break;
7478                         }
7479                 }
7480         }
7481         return list;
7482 }
7483
7484 /*
7485  * Sort the results of file name expansion.  It calculates the number of
7486  * strings to sort and then calls msort (short for merge sort) to do the
7487  * work.
7488  */
7489 static struct strlist *
7490 expsort(struct strlist *str)
7491 {
7492         int len;
7493         struct strlist *sp;
7494
7495         len = 0;
7496         for (sp = str; sp; sp = sp->next)
7497                 len++;
7498         return msort(str, len);
7499 }
7500
7501 static void
7502 expandmeta(struct strlist *str /*, int flag*/)
7503 {
7504         /* TODO - EXP_REDIR */
7505
7506         while (str) {
7507                 char *expdir;
7508                 struct strlist **savelastp;
7509                 struct strlist *sp;
7510                 char *p;
7511
7512                 if (fflag)
7513                         goto nometa;
7514                 if (!hasmeta(str->text))
7515                         goto nometa;
7516                 savelastp = exparg.lastp;
7517
7518                 INT_OFF;
7519                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7520                 {
7521                         int i = strlen(str->text);
7522 //BUGGY estimation of how long expanded name can be
7523                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7524                 }
7525                 expmeta(expdir, expdir, p);
7526                 free(expdir);
7527                 if (p != str->text)
7528                         free(p);
7529                 INT_ON;
7530                 if (exparg.lastp == savelastp) {
7531                         /*
7532                          * no matches
7533                          */
7534  nometa:
7535                         *exparg.lastp = str;
7536                         rmescapes(str->text, 0);
7537                         exparg.lastp = &str->next;
7538                 } else {
7539                         *exparg.lastp = NULL;
7540                         *savelastp = sp = expsort(*savelastp);
7541                         while (sp->next != NULL)
7542                                 sp = sp->next;
7543                         exparg.lastp = &sp->next;
7544                 }
7545                 str = str->next;
7546         }
7547 }
7548 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7549
7550 /*
7551  * Perform variable substitution and command substitution on an argument,
7552  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7553  * perform splitting and file name expansion.  When arglist is NULL, perform
7554  * here document expansion.
7555  */
7556 static void
7557 expandarg(union node *arg, struct arglist *arglist, int flag)
7558 {
7559         struct strlist *sp;
7560         char *p;
7561
7562         argbackq = arg->narg.backquote;
7563         STARTSTACKSTR(expdest);
7564         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7565         argstr(arg->narg.text, flag);
7566         p = _STPUTC('\0', expdest);
7567         expdest = p - 1;
7568         if (arglist == NULL) {
7569                 /* here document expanded */
7570                 goto out;
7571         }
7572         p = grabstackstr(p);
7573         TRACE(("expandarg: p:'%s'\n", p));
7574         exparg.lastp = &exparg.list;
7575         /*
7576          * TODO - EXP_REDIR
7577          */
7578         if (flag & EXP_FULL) {
7579                 ifsbreakup(p, &exparg);
7580                 *exparg.lastp = NULL;
7581                 exparg.lastp = &exparg.list;
7582                 expandmeta(exparg.list /*, flag*/);
7583         } else {
7584                 sp = stzalloc(sizeof(*sp));
7585                 sp->text = p;
7586                 *exparg.lastp = sp;
7587                 exparg.lastp = &sp->next;
7588         }
7589         *exparg.lastp = NULL;
7590         if (exparg.list) {
7591                 *arglist->lastp = exparg.list;
7592                 arglist->lastp = exparg.lastp;
7593         }
7594
7595  out:
7596         ifsfree();
7597 }
7598
7599 /*
7600  * Expand shell variables and backquotes inside a here document.
7601  */
7602 static void
7603 expandhere(union node *arg, int fd)
7604 {
7605         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7606         full_write(fd, stackblock(), expdest - (char *)stackblock());
7607 }
7608
7609 /*
7610  * Returns true if the pattern matches the string.
7611  */
7612 static int
7613 patmatch(char *pattern, const char *string)
7614 {
7615         char *p = preglob(pattern, 0);
7616         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7617         return pmatch(p, string);
7618 }
7619
7620 /*
7621  * See if a pattern matches in a case statement.
7622  */
7623 static int
7624 casematch(union node *pattern, char *val)
7625 {
7626         struct stackmark smark;
7627         int result;
7628
7629         setstackmark(&smark);
7630         argbackq = pattern->narg.backquote;
7631         STARTSTACKSTR(expdest);
7632         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7633         STACKSTRNUL(expdest);
7634         ifsfree();
7635         result = patmatch(stackblock(), val);
7636         popstackmark(&smark);
7637         return result;
7638 }
7639
7640
7641 /* ============ find_command */
7642
7643 struct builtincmd {
7644         const char *name;
7645         int (*builtin)(int, char **) FAST_FUNC;
7646         /* unsigned flags; */
7647 };
7648 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7649 /* "regular" builtins always take precedence over commands,
7650  * regardless of PATH=....%builtin... position */
7651 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7652 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7653
7654 struct cmdentry {
7655         smallint cmdtype;       /* CMDxxx */
7656         union param {
7657                 int index;
7658                 /* index >= 0 for commands without path (slashes) */
7659                 /* (TODO: what exactly does the value mean? PATH position?) */
7660                 /* index == -1 for commands with slashes */
7661                 /* index == (-2 - applet_no) for NOFORK applets */
7662                 const struct builtincmd *cmd;
7663                 struct funcnode *func;
7664         } u;
7665 };
7666 /* values of cmdtype */
7667 #define CMDUNKNOWN      -1      /* no entry in table for command */
7668 #define CMDNORMAL       0       /* command is an executable program */
7669 #define CMDFUNCTION     1       /* command is a shell function */
7670 #define CMDBUILTIN      2       /* command is a shell builtin */
7671
7672 /* action to find_command() */
7673 #define DO_ERR          0x01    /* prints errors */
7674 #define DO_ABS          0x02    /* checks absolute paths */
7675 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7676 #define DO_ALTPATH      0x08    /* using alternate path */
7677 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7678
7679 static void find_command(char *, struct cmdentry *, int, const char *);
7680
7681
7682 /* ============ Hashing commands */
7683
7684 /*
7685  * When commands are first encountered, they are entered in a hash table.
7686  * This ensures that a full path search will not have to be done for them
7687  * on each invocation.
7688  *
7689  * We should investigate converting to a linear search, even though that
7690  * would make the command name "hash" a misnomer.
7691  */
7692
7693 struct tblentry {
7694         struct tblentry *next;  /* next entry in hash chain */
7695         union param param;      /* definition of builtin function */
7696         smallint cmdtype;       /* CMDxxx */
7697         char rehash;            /* if set, cd done since entry created */
7698         char cmdname[1];        /* name of command */
7699 };
7700
7701 static struct tblentry **cmdtable;
7702 #define INIT_G_cmdtable() do { \
7703         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7704 } while (0)
7705
7706 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7707
7708
7709 static void
7710 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7711 {
7712 #if ENABLE_FEATURE_SH_STANDALONE
7713         if (applet_no >= 0) {
7714                 if (APPLET_IS_NOEXEC(applet_no)) {
7715                         clearenv();
7716                         while (*envp)
7717                                 putenv(*envp++);
7718                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7719                         run_applet_no_and_exit(applet_no, cmd, argv);
7720                 }
7721                 /* re-exec ourselves with the new arguments */
7722                 execve(bb_busybox_exec_path, argv, envp);
7723                 /* If they called chroot or otherwise made the binary no longer
7724                  * executable, fall through */
7725         }
7726 #endif
7727
7728  repeat:
7729 #ifdef SYSV
7730         do {
7731                 execve(cmd, argv, envp);
7732         } while (errno == EINTR);
7733 #else
7734         execve(cmd, argv, envp);
7735 #endif
7736         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7737                 /* Run "cmd" as a shell script:
7738                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7739                  * "If the execve() function fails with ENOEXEC, the shell
7740                  * shall execute a command equivalent to having a shell invoked
7741                  * with the command name as its first operand,
7742                  * with any remaining arguments passed to the new shell"
7743                  *
7744                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7745                  * just call ourselves.
7746                  *
7747                  * Note that bash reads ~80 chars of the file, and if it sees
7748                  * a zero byte before it sees newline, it doesn't try to
7749                  * interpret it, but fails with "cannot execute binary file"
7750                  * message and exit code 126. For one, this prevents attempts
7751                  * to interpret foreign ELF binaries as shell scripts.
7752                  */
7753                 argv[0] = (char*) cmd;
7754                 cmd = bb_busybox_exec_path;
7755                 /* NB: this is only possible because all callers of shellexec()
7756                  * ensure that the argv[-1] slot exists!
7757                  */
7758                 argv--;
7759                 argv[0] = (char*) "ash";
7760                 goto repeat;
7761         }
7762 }
7763
7764 /*
7765  * Exec a program.  Never returns.  If you change this routine, you may
7766  * have to change the find_command routine as well.
7767  * argv[-1] must exist and be writable! See tryexec() for why.
7768  */
7769 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7770 static void shellexec(char *prog, char **argv, const char *path, int idx)
7771 {
7772         char *cmdname;
7773         int e;
7774         char **envp;
7775         int exerrno;
7776         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7777
7778         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7779         if (strchr(prog, '/') != NULL
7780 #if ENABLE_FEATURE_SH_STANDALONE
7781          || (applet_no = find_applet_by_name(prog)) >= 0
7782 #endif
7783         ) {
7784                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7785                 if (applet_no >= 0) {
7786                         /* We tried execing ourself, but it didn't work.
7787                          * Maybe /proc/self/exe doesn't exist?
7788                          * Try $PATH search.
7789                          */
7790                         goto try_PATH;
7791                 }
7792                 e = errno;
7793         } else {
7794  try_PATH:
7795                 e = ENOENT;
7796                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7797                         if (--idx < 0 && pathopt == NULL) {
7798                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7799                                 if (errno != ENOENT && errno != ENOTDIR)
7800                                         e = errno;
7801                         }
7802                         stunalloc(cmdname);
7803                 }
7804         }
7805
7806         /* Map to POSIX errors */
7807         switch (e) {
7808         case EACCES:
7809                 exerrno = 126;
7810                 break;
7811         case ENOENT:
7812                 exerrno = 127;
7813                 break;
7814         default:
7815                 exerrno = 2;
7816                 break;
7817         }
7818         exitstatus = exerrno;
7819         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7820                 prog, e, suppress_int));
7821         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7822         /* NOTREACHED */
7823 }
7824
7825 static void
7826 printentry(struct tblentry *cmdp)
7827 {
7828         int idx;
7829         const char *path;
7830         char *name;
7831
7832         idx = cmdp->param.index;
7833         path = pathval();
7834         do {
7835                 name = path_advance(&path, cmdp->cmdname);
7836                 stunalloc(name);
7837         } while (--idx >= 0);
7838         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7839 }
7840
7841 /*
7842  * Clear out command entries.  The argument specifies the first entry in
7843  * PATH which has changed.
7844  */
7845 static void
7846 clearcmdentry(int firstchange)
7847 {
7848         struct tblentry **tblp;
7849         struct tblentry **pp;
7850         struct tblentry *cmdp;
7851
7852         INT_OFF;
7853         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7854                 pp = tblp;
7855                 while ((cmdp = *pp) != NULL) {
7856                         if ((cmdp->cmdtype == CMDNORMAL &&
7857                              cmdp->param.index >= firstchange)
7858                          || (cmdp->cmdtype == CMDBUILTIN &&
7859                              builtinloc >= firstchange)
7860                         ) {
7861                                 *pp = cmdp->next;
7862                                 free(cmdp);
7863                         } else {
7864                                 pp = &cmdp->next;
7865                         }
7866                 }
7867         }
7868         INT_ON;
7869 }
7870
7871 /*
7872  * Locate a command in the command hash table.  If "add" is nonzero,
7873  * add the command to the table if it is not already present.  The
7874  * variable "lastcmdentry" is set to point to the address of the link
7875  * pointing to the entry, so that delete_cmd_entry can delete the
7876  * entry.
7877  *
7878  * Interrupts must be off if called with add != 0.
7879  */
7880 static struct tblentry **lastcmdentry;
7881
7882 static struct tblentry *
7883 cmdlookup(const char *name, int add)
7884 {
7885         unsigned int hashval;
7886         const char *p;
7887         struct tblentry *cmdp;
7888         struct tblentry **pp;
7889
7890         p = name;
7891         hashval = (unsigned char)*p << 4;
7892         while (*p)
7893                 hashval += (unsigned char)*p++;
7894         hashval &= 0x7FFF;
7895         pp = &cmdtable[hashval % CMDTABLESIZE];
7896         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7897                 if (strcmp(cmdp->cmdname, name) == 0)
7898                         break;
7899                 pp = &cmdp->next;
7900         }
7901         if (add && cmdp == NULL) {
7902                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7903                                 + strlen(name)
7904                                 /* + 1 - already done because
7905                                  * tblentry::cmdname is char[1] */);
7906                 /*cmdp->next = NULL; - ckzalloc did it */
7907                 cmdp->cmdtype = CMDUNKNOWN;
7908                 strcpy(cmdp->cmdname, name);
7909         }
7910         lastcmdentry = pp;
7911         return cmdp;
7912 }
7913
7914 /*
7915  * Delete the command entry returned on the last lookup.
7916  */
7917 static void
7918 delete_cmd_entry(void)
7919 {
7920         struct tblentry *cmdp;
7921
7922         INT_OFF;
7923         cmdp = *lastcmdentry;
7924         *lastcmdentry = cmdp->next;
7925         if (cmdp->cmdtype == CMDFUNCTION)
7926                 freefunc(cmdp->param.func);
7927         free(cmdp);
7928         INT_ON;
7929 }
7930
7931 /*
7932  * Add a new command entry, replacing any existing command entry for
7933  * the same name - except special builtins.
7934  */
7935 static void
7936 addcmdentry(char *name, struct cmdentry *entry)
7937 {
7938         struct tblentry *cmdp;
7939
7940         cmdp = cmdlookup(name, 1);
7941         if (cmdp->cmdtype == CMDFUNCTION) {
7942                 freefunc(cmdp->param.func);
7943         }
7944         cmdp->cmdtype = entry->cmdtype;
7945         cmdp->param = entry->u;
7946         cmdp->rehash = 0;
7947 }
7948
7949 static int FAST_FUNC
7950 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7951 {
7952         struct tblentry **pp;
7953         struct tblentry *cmdp;
7954         int c;
7955         struct cmdentry entry;
7956         char *name;
7957
7958         if (nextopt("r") != '\0') {
7959                 clearcmdentry(0);
7960                 return 0;
7961         }
7962
7963         if (*argptr == NULL) {
7964                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7965                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7966                                 if (cmdp->cmdtype == CMDNORMAL)
7967                                         printentry(cmdp);
7968                         }
7969                 }
7970                 return 0;
7971         }
7972
7973         c = 0;
7974         while ((name = *argptr) != NULL) {
7975                 cmdp = cmdlookup(name, 0);
7976                 if (cmdp != NULL
7977                  && (cmdp->cmdtype == CMDNORMAL
7978                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7979                 ) {
7980                         delete_cmd_entry();
7981                 }
7982                 find_command(name, &entry, DO_ERR, pathval());
7983                 if (entry.cmdtype == CMDUNKNOWN)
7984                         c = 1;
7985                 argptr++;
7986         }
7987         return c;
7988 }
7989
7990 /*
7991  * Called when a cd is done.  Marks all commands so the next time they
7992  * are executed they will be rehashed.
7993  */
7994 static void
7995 hashcd(void)
7996 {
7997         struct tblentry **pp;
7998         struct tblentry *cmdp;
7999
8000         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8001                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8002                         if (cmdp->cmdtype == CMDNORMAL
8003                          || (cmdp->cmdtype == CMDBUILTIN
8004                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8005                              && builtinloc > 0)
8006                         ) {
8007                                 cmdp->rehash = 1;
8008                         }
8009                 }
8010         }
8011 }
8012
8013 /*
8014  * Fix command hash table when PATH changed.
8015  * Called before PATH is changed.  The argument is the new value of PATH;
8016  * pathval() still returns the old value at this point.
8017  * Called with interrupts off.
8018  */
8019 static void FAST_FUNC
8020 changepath(const char *new)
8021 {
8022         const char *old;
8023         int firstchange;
8024         int idx;
8025         int idx_bltin;
8026
8027         old = pathval();
8028         firstchange = 9999;     /* assume no change */
8029         idx = 0;
8030         idx_bltin = -1;
8031         for (;;) {
8032                 if (*old != *new) {
8033                         firstchange = idx;
8034                         if ((*old == '\0' && *new == ':')
8035                          || (*old == ':' && *new == '\0')
8036                         ) {
8037                                 firstchange++;
8038                         }
8039                         old = new;      /* ignore subsequent differences */
8040                 }
8041                 if (*new == '\0')
8042                         break;
8043                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8044                         idx_bltin = idx;
8045                 if (*new == ':')
8046                         idx++;
8047                 new++;
8048                 old++;
8049         }
8050         if (builtinloc < 0 && idx_bltin >= 0)
8051                 builtinloc = idx_bltin;             /* zap builtins */
8052         if (builtinloc >= 0 && idx_bltin < 0)
8053                 firstchange = 0;
8054         clearcmdentry(firstchange);
8055         builtinloc = idx_bltin;
8056 }
8057 enum {
8058         TEOF,
8059         TNL,
8060         TREDIR,
8061         TWORD,
8062         TSEMI,
8063         TBACKGND,
8064         TAND,
8065         TOR,
8066         TPIPE,
8067         TLP,
8068         TRP,
8069         TENDCASE,
8070         TENDBQUOTE,
8071         TNOT,
8072         TCASE,
8073         TDO,
8074         TDONE,
8075         TELIF,
8076         TELSE,
8077         TESAC,
8078         TFI,
8079         TFOR,
8080 #if BASH_FUNCTION
8081         TFUNCTION,
8082 #endif
8083         TIF,
8084         TIN,
8085         TTHEN,
8086         TUNTIL,
8087         TWHILE,
8088         TBEGIN,
8089         TEND
8090 };
8091 typedef smallint token_id_t;
8092
8093 /* Nth bit indicates if token marks the end of a list */
8094 enum {
8095         tokendlist = 0
8096         /*  0 */ | (1u << TEOF)
8097         /*  1 */ | (0u << TNL)
8098         /*  2 */ | (0u << TREDIR)
8099         /*  3 */ | (0u << TWORD)
8100         /*  4 */ | (0u << TSEMI)
8101         /*  5 */ | (0u << TBACKGND)
8102         /*  6 */ | (0u << TAND)
8103         /*  7 */ | (0u << TOR)
8104         /*  8 */ | (0u << TPIPE)
8105         /*  9 */ | (0u << TLP)
8106         /* 10 */ | (1u << TRP)
8107         /* 11 */ | (1u << TENDCASE)
8108         /* 12 */ | (1u << TENDBQUOTE)
8109         /* 13 */ | (0u << TNOT)
8110         /* 14 */ | (0u << TCASE)
8111         /* 15 */ | (1u << TDO)
8112         /* 16 */ | (1u << TDONE)
8113         /* 17 */ | (1u << TELIF)
8114         /* 18 */ | (1u << TELSE)
8115         /* 19 */ | (1u << TESAC)
8116         /* 20 */ | (1u << TFI)
8117         /* 21 */ | (0u << TFOR)
8118 #if BASH_FUNCTION
8119         /* 22 */ | (0u << TFUNCTION)
8120 #endif
8121         /* 23 */ | (0u << TIF)
8122         /* 24 */ | (0u << TIN)
8123         /* 25 */ | (1u << TTHEN)
8124         /* 26 */ | (0u << TUNTIL)
8125         /* 27 */ | (0u << TWHILE)
8126         /* 28 */ | (0u << TBEGIN)
8127         /* 29 */ | (1u << TEND)
8128         , /* thus far 29 bits used */
8129 };
8130
8131 static const char *const tokname_array[] = {
8132         "end of file",
8133         "newline",
8134         "redirection",
8135         "word",
8136         ";",
8137         "&",
8138         "&&",
8139         "||",
8140         "|",
8141         "(",
8142         ")",
8143         ";;",
8144         "`",
8145 #define KWDOFFSET 13
8146         /* the following are keywords */
8147         "!",
8148         "case",
8149         "do",
8150         "done",
8151         "elif",
8152         "else",
8153         "esac",
8154         "fi",
8155         "for",
8156 #if BASH_FUNCTION
8157         "function",
8158 #endif
8159         "if",
8160         "in",
8161         "then",
8162         "until",
8163         "while",
8164         "{",
8165         "}",
8166 };
8167
8168 /* Wrapper around strcmp for qsort/bsearch/... */
8169 static int
8170 pstrcmp(const void *a, const void *b)
8171 {
8172         return strcmp((char*)a, *(char**)b);
8173 }
8174
8175 static const char *const *
8176 findkwd(const char *s)
8177 {
8178         return bsearch(s, tokname_array + KWDOFFSET,
8179                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8180                         sizeof(tokname_array[0]), pstrcmp);
8181 }
8182
8183 /*
8184  * Locate and print what a word is...
8185  */
8186 static int
8187 describe_command(char *command, const char *path, int describe_command_verbose)
8188 {
8189         struct cmdentry entry;
8190 #if ENABLE_ASH_ALIAS
8191         const struct alias *ap;
8192 #endif
8193
8194         path = path ? path : pathval();
8195
8196         if (describe_command_verbose) {
8197                 out1str(command);
8198         }
8199
8200         /* First look at the keywords */
8201         if (findkwd(command)) {
8202                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8203                 goto out;
8204         }
8205
8206 #if ENABLE_ASH_ALIAS
8207         /* Then look at the aliases */
8208         ap = lookupalias(command, 0);
8209         if (ap != NULL) {
8210                 if (!describe_command_verbose) {
8211                         out1str("alias ");
8212                         printalias(ap);
8213                         return 0;
8214                 }
8215                 out1fmt(" is an alias for %s", ap->val);
8216                 goto out;
8217         }
8218 #endif
8219         /* Brute force */
8220         find_command(command, &entry, DO_ABS, path);
8221
8222         switch (entry.cmdtype) {
8223         case CMDNORMAL: {
8224                 int j = entry.u.index;
8225                 char *p;
8226                 if (j < 0) {
8227                         p = command;
8228                 } else {
8229                         do {
8230                                 p = path_advance(&path, command);
8231                                 stunalloc(p);
8232                         } while (--j >= 0);
8233                 }
8234                 if (describe_command_verbose) {
8235                         out1fmt(" is %s", p);
8236                 } else {
8237                         out1str(p);
8238                 }
8239                 break;
8240         }
8241
8242         case CMDFUNCTION:
8243                 if (describe_command_verbose) {
8244                         out1str(" is a shell function");
8245                 } else {
8246                         out1str(command);
8247                 }
8248                 break;
8249
8250         case CMDBUILTIN:
8251                 if (describe_command_verbose) {
8252                         out1fmt(" is a %sshell builtin",
8253                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8254                                         "special " : nullstr
8255                         );
8256                 } else {
8257                         out1str(command);
8258                 }
8259                 break;
8260
8261         default:
8262                 if (describe_command_verbose) {
8263                         out1str(": not found\n");
8264                 }
8265                 return 127;
8266         }
8267  out:
8268         out1str("\n");
8269         return 0;
8270 }
8271
8272 static int FAST_FUNC
8273 typecmd(int argc UNUSED_PARAM, char **argv)
8274 {
8275         int i = 1;
8276         int err = 0;
8277         int verbose = 1;
8278
8279         /* type -p ... ? (we don't bother checking for 'p') */
8280         if (argv[1] && argv[1][0] == '-') {
8281                 i++;
8282                 verbose = 0;
8283         }
8284         while (argv[i]) {
8285                 err |= describe_command(argv[i++], NULL, verbose);
8286         }
8287         return err;
8288 }
8289
8290 #if ENABLE_ASH_CMDCMD
8291 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8292 static char **
8293 parse_command_args(char **argv, const char **path)
8294 {
8295         char *cp, c;
8296
8297         for (;;) {
8298                 cp = *++argv;
8299                 if (!cp)
8300                         return NULL;
8301                 if (*cp++ != '-')
8302                         break;
8303                 c = *cp++;
8304                 if (!c)
8305                         break;
8306                 if (c == '-' && !*cp) {
8307                         if (!*++argv)
8308                                 return NULL;
8309                         break;
8310                 }
8311                 do {
8312                         switch (c) {
8313                         case 'p':
8314                                 *path = bb_default_path;
8315                                 break;
8316                         default:
8317                                 /* run 'typecmd' for other options */
8318                                 return NULL;
8319                         }
8320                         c = *cp++;
8321                 } while (c);
8322         }
8323         return argv;
8324 }
8325
8326 static int FAST_FUNC
8327 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8328 {
8329         char *cmd;
8330         int c;
8331         enum {
8332                 VERIFY_BRIEF = 1,
8333                 VERIFY_VERBOSE = 2,
8334         } verify = 0;
8335         const char *path = NULL;
8336
8337         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8338          * never reaches this function.
8339          */
8340
8341         while ((c = nextopt("pvV")) != '\0')
8342                 if (c == 'V')
8343                         verify |= VERIFY_VERBOSE;
8344                 else if (c == 'v')
8345                         /*verify |= VERIFY_BRIEF*/;
8346 #if DEBUG
8347                 else if (c != 'p')
8348                         abort();
8349 #endif
8350                 else
8351                         path = bb_default_path;
8352
8353         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8354         cmd = *argptr;
8355         if (/*verify && */ cmd)
8356                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8357
8358         return 0;
8359 }
8360 #endif
8361
8362
8363 /*static int funcblocksize;     // size of structures in function */
8364 /*static int funcstringsize;    // size of strings in node */
8365 static void *funcblock;         /* block to allocate function from */
8366 static char *funcstring_end;    /* end of block to allocate strings from */
8367
8368 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8369         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8370         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8371         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8372         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8373         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8374         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8375         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8376         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8377         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8378         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8379         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8380         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8381         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8382         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8383         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8384         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8385         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8386 #if BASH_REDIR_OUTPUT
8387         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8388 #endif
8389         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8390         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8391         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8392         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8393         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8394         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8395         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8396         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8397         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8398 };
8399
8400 static int calcsize(int funcblocksize, union node *n);
8401
8402 static int
8403 sizenodelist(int funcblocksize, struct nodelist *lp)
8404 {
8405         while (lp) {
8406                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8407                 funcblocksize = calcsize(funcblocksize, lp->n);
8408                 lp = lp->next;
8409         }
8410         return funcblocksize;
8411 }
8412
8413 static int
8414 calcsize(int funcblocksize, union node *n)
8415 {
8416         if (n == NULL)
8417                 return funcblocksize;
8418         funcblocksize += nodesize[n->type];
8419         switch (n->type) {
8420         case NCMD:
8421                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8422                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8423                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8424                 break;
8425         case NPIPE:
8426                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8427                 break;
8428         case NREDIR:
8429         case NBACKGND:
8430         case NSUBSHELL:
8431                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8432                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8433                 break;
8434         case NAND:
8435         case NOR:
8436         case NSEMI:
8437         case NWHILE:
8438         case NUNTIL:
8439                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8440                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8441                 break;
8442         case NIF:
8443                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8444                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8445                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8446                 break;
8447         case NFOR:
8448                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8449                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8450                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8451                 break;
8452         case NCASE:
8453                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8454                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8455                 break;
8456         case NCLIST:
8457                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8458                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8459                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8460                 break;
8461         case NDEFUN:
8462         case NARG:
8463                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8464                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8465                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8466                 break;
8467         case NTO:
8468 #if BASH_REDIR_OUTPUT
8469         case NTO2:
8470 #endif
8471         case NCLOBBER:
8472         case NFROM:
8473         case NFROMTO:
8474         case NAPPEND:
8475                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8476                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8477                 break;
8478         case NTOFD:
8479         case NFROMFD:
8480                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8481                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8482         break;
8483         case NHERE:
8484         case NXHERE:
8485                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8486                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8487                 break;
8488         case NNOT:
8489                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8490                 break;
8491         };
8492         return funcblocksize;
8493 }
8494
8495 static char *
8496 nodeckstrdup(char *s)
8497 {
8498         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8499         return strcpy(funcstring_end, s);
8500 }
8501
8502 static union node *copynode(union node *);
8503
8504 static struct nodelist *
8505 copynodelist(struct nodelist *lp)
8506 {
8507         struct nodelist *start;
8508         struct nodelist **lpp;
8509
8510         lpp = &start;
8511         while (lp) {
8512                 *lpp = funcblock;
8513                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8514                 (*lpp)->n = copynode(lp->n);
8515                 lp = lp->next;
8516                 lpp = &(*lpp)->next;
8517         }
8518         *lpp = NULL;
8519         return start;
8520 }
8521
8522 static union node *
8523 copynode(union node *n)
8524 {
8525         union node *new;
8526
8527         if (n == NULL)
8528                 return NULL;
8529         new = funcblock;
8530         funcblock = (char *) funcblock + nodesize[n->type];
8531
8532         switch (n->type) {
8533         case NCMD:
8534                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8535                 new->ncmd.args = copynode(n->ncmd.args);
8536                 new->ncmd.assign = copynode(n->ncmd.assign);
8537                 break;
8538         case NPIPE:
8539                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8540                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8541                 break;
8542         case NREDIR:
8543         case NBACKGND:
8544         case NSUBSHELL:
8545                 new->nredir.redirect = copynode(n->nredir.redirect);
8546                 new->nredir.n = copynode(n->nredir.n);
8547                 break;
8548         case NAND:
8549         case NOR:
8550         case NSEMI:
8551         case NWHILE:
8552         case NUNTIL:
8553                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8554                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8555                 break;
8556         case NIF:
8557                 new->nif.elsepart = copynode(n->nif.elsepart);
8558                 new->nif.ifpart = copynode(n->nif.ifpart);
8559                 new->nif.test = copynode(n->nif.test);
8560                 break;
8561         case NFOR:
8562                 new->nfor.var = nodeckstrdup(n->nfor.var);
8563                 new->nfor.body = copynode(n->nfor.body);
8564                 new->nfor.args = copynode(n->nfor.args);
8565                 break;
8566         case NCASE:
8567                 new->ncase.cases = copynode(n->ncase.cases);
8568                 new->ncase.expr = copynode(n->ncase.expr);
8569                 break;
8570         case NCLIST:
8571                 new->nclist.body = copynode(n->nclist.body);
8572                 new->nclist.pattern = copynode(n->nclist.pattern);
8573                 new->nclist.next = copynode(n->nclist.next);
8574                 break;
8575         case NDEFUN:
8576         case NARG:
8577                 new->narg.backquote = copynodelist(n->narg.backquote);
8578                 new->narg.text = nodeckstrdup(n->narg.text);
8579                 new->narg.next = copynode(n->narg.next);
8580                 break;
8581         case NTO:
8582 #if BASH_REDIR_OUTPUT
8583         case NTO2:
8584 #endif
8585         case NCLOBBER:
8586         case NFROM:
8587         case NFROMTO:
8588         case NAPPEND:
8589                 new->nfile.fname = copynode(n->nfile.fname);
8590                 new->nfile.fd = n->nfile.fd;
8591                 new->nfile.next = copynode(n->nfile.next);
8592                 break;
8593         case NTOFD:
8594         case NFROMFD:
8595                 new->ndup.vname = copynode(n->ndup.vname);
8596                 new->ndup.dupfd = n->ndup.dupfd;
8597                 new->ndup.fd = n->ndup.fd;
8598                 new->ndup.next = copynode(n->ndup.next);
8599                 break;
8600         case NHERE:
8601         case NXHERE:
8602                 new->nhere.doc = copynode(n->nhere.doc);
8603                 new->nhere.fd = n->nhere.fd;
8604                 new->nhere.next = copynode(n->nhere.next);
8605                 break;
8606         case NNOT:
8607                 new->nnot.com = copynode(n->nnot.com);
8608                 break;
8609         };
8610         new->type = n->type;
8611         return new;
8612 }
8613
8614 /*
8615  * Make a copy of a parse tree.
8616  */
8617 static struct funcnode *
8618 copyfunc(union node *n)
8619 {
8620         struct funcnode *f;
8621         size_t blocksize;
8622
8623         /*funcstringsize = 0;*/
8624         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8625         f = ckzalloc(blocksize /* + funcstringsize */);
8626         funcblock = (char *) f + offsetof(struct funcnode, n);
8627         funcstring_end = (char *) f + blocksize;
8628         copynode(n);
8629         /* f->count = 0; - ckzalloc did it */
8630         return f;
8631 }
8632
8633 /*
8634  * Define a shell function.
8635  */
8636 static void
8637 defun(union node *func)
8638 {
8639         struct cmdentry entry;
8640
8641         INT_OFF;
8642         entry.cmdtype = CMDFUNCTION;
8643         entry.u.func = copyfunc(func);
8644         addcmdentry(func->narg.text, &entry);
8645         INT_ON;
8646 }
8647
8648 /* Reasons for skipping commands (see comment on breakcmd routine) */
8649 #define SKIPBREAK      (1 << 0)
8650 #define SKIPCONT       (1 << 1)
8651 #define SKIPFUNC       (1 << 2)
8652 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8653 static int skipcount;           /* number of levels to skip */
8654 static int funcnest;            /* depth of function calls */
8655 static int loopnest;            /* current loop nesting level */
8656
8657 /* Forward decl way out to parsing code - dotrap needs it */
8658 static int evalstring(char *s, int flags);
8659
8660 /* Called to execute a trap.
8661  * Single callsite - at the end of evaltree().
8662  * If we return non-zero, evaltree raises EXEXIT exception.
8663  *
8664  * Perhaps we should avoid entering new trap handlers
8665  * while we are executing a trap handler. [is it a TODO?]
8666  */
8667 static void
8668 dotrap(void)
8669 {
8670         uint8_t *g;
8671         int sig;
8672         uint8_t last_status;
8673
8674         if (!pending_sig)
8675                 return;
8676
8677         last_status = exitstatus;
8678         pending_sig = 0;
8679         barrier();
8680
8681         TRACE(("dotrap entered\n"));
8682         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8683                 char *p;
8684
8685                 if (!*g)
8686                         continue;
8687
8688                 if (evalskip) {
8689                         pending_sig = sig;
8690                         break;
8691                 }
8692
8693                 p = trap[sig];
8694                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8695                  * don't upset it by resetting gotsig[SIGINT-1] */
8696                 if (sig == SIGINT && !p)
8697                         continue;
8698
8699                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8700                 *g = 0;
8701                 if (!p)
8702                         continue;
8703                 evalstring(p, 0);
8704         }
8705         exitstatus = last_status;
8706         TRACE(("dotrap returns\n"));
8707 }
8708
8709 /* forward declarations - evaluation is fairly recursive business... */
8710 static int evalloop(union node *, int);
8711 static int evalfor(union node *, int);
8712 static int evalcase(union node *, int);
8713 static int evalsubshell(union node *, int);
8714 static void expredir(union node *);
8715 static int evalpipe(union node *, int);
8716 static int evalcommand(union node *, int);
8717 static int evalbltin(const struct builtincmd *, int, char **, int);
8718 static void prehash(union node *);
8719
8720 /*
8721  * Evaluate a parse tree.  The value is left in the global variable
8722  * exitstatus.
8723  */
8724 static int
8725 evaltree(union node *n, int flags)
8726 {
8727         int checkexit = 0;
8728         int (*evalfn)(union node *, int);
8729         int status = 0;
8730
8731         if (n == NULL) {
8732                 TRACE(("evaltree(NULL) called\n"));
8733                 goto out;
8734         }
8735         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8736
8737         dotrap();
8738
8739         switch (n->type) {
8740         default:
8741 #if DEBUG
8742                 out1fmt("Node type = %d\n", n->type);
8743                 fflush_all();
8744                 break;
8745 #endif
8746         case NNOT:
8747                 status = !evaltree(n->nnot.com, EV_TESTED);
8748                 goto setstatus;
8749         case NREDIR:
8750                 expredir(n->nredir.redirect);
8751                 pushredir(n->nredir.redirect);
8752                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8753                 if (!status) {
8754                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8755                 }
8756                 if (n->nredir.redirect)
8757                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8758                 goto setstatus;
8759         case NCMD:
8760                 evalfn = evalcommand;
8761  checkexit:
8762                 if (eflag && !(flags & EV_TESTED))
8763                         checkexit = ~0;
8764                 goto calleval;
8765         case NFOR:
8766                 evalfn = evalfor;
8767                 goto calleval;
8768         case NWHILE:
8769         case NUNTIL:
8770                 evalfn = evalloop;
8771                 goto calleval;
8772         case NSUBSHELL:
8773         case NBACKGND:
8774                 evalfn = evalsubshell;
8775                 goto checkexit;
8776         case NPIPE:
8777                 evalfn = evalpipe;
8778                 goto checkexit;
8779         case NCASE:
8780                 evalfn = evalcase;
8781                 goto calleval;
8782         case NAND:
8783         case NOR:
8784         case NSEMI: {
8785
8786 #if NAND + 1 != NOR
8787 #error NAND + 1 != NOR
8788 #endif
8789 #if NOR + 1 != NSEMI
8790 #error NOR + 1 != NSEMI
8791 #endif
8792                 unsigned is_or = n->type - NAND;
8793                 status = evaltree(
8794                         n->nbinary.ch1,
8795                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8796                 );
8797                 if ((!status) == is_or || evalskip)
8798                         break;
8799                 n = n->nbinary.ch2;
8800  evaln:
8801                 evalfn = evaltree;
8802  calleval:
8803                 status = evalfn(n, flags);
8804                 goto setstatus;
8805         }
8806         case NIF:
8807                 status = evaltree(n->nif.test, EV_TESTED);
8808                 if (evalskip)
8809                         break;
8810                 if (!status) {
8811                         n = n->nif.ifpart;
8812                         goto evaln;
8813                 }
8814                 if (n->nif.elsepart) {
8815                         n = n->nif.elsepart;
8816                         goto evaln;
8817                 }
8818                 status = 0;
8819                 goto setstatus;
8820         case NDEFUN:
8821                 defun(n);
8822                 /* Not necessary. To test it:
8823                  * "false; f() { qwerty; }; echo $?" should print 0.
8824                  */
8825                 /* status = 0; */
8826  setstatus:
8827                 exitstatus = status;
8828                 break;
8829         }
8830  out:
8831         /* Order of checks below is important:
8832          * signal handlers trigger before exit caused by "set -e".
8833          */
8834         dotrap();
8835
8836         if (checkexit & status)
8837                 raise_exception(EXEXIT);
8838         if (flags & EV_EXIT)
8839                 raise_exception(EXEXIT);
8840
8841         TRACE(("leaving evaltree (no interrupts)\n"));
8842         return exitstatus;
8843 }
8844
8845 static int
8846 skiploop(void)
8847 {
8848         int skip = evalskip;
8849
8850         switch (skip) {
8851         case 0:
8852                 break;
8853         case SKIPBREAK:
8854         case SKIPCONT:
8855                 if (--skipcount <= 0) {
8856                         evalskip = 0;
8857                         break;
8858                 }
8859                 skip = SKIPBREAK;
8860                 break;
8861         }
8862         return skip;
8863 }
8864
8865 static int
8866 evalloop(union node *n, int flags)
8867 {
8868         int skip;
8869         int status;
8870
8871         loopnest++;
8872         status = 0;
8873         flags &= EV_TESTED;
8874         do {
8875                 int i;
8876
8877                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8878                 skip = skiploop();
8879                 if (skip == SKIPFUNC)
8880                         status = i;
8881                 if (skip)
8882                         continue;
8883                 if (n->type != NWHILE)
8884                         i = !i;
8885                 if (i != 0)
8886                         break;
8887                 status = evaltree(n->nbinary.ch2, flags);
8888                 skip = skiploop();
8889         } while (!(skip & ~SKIPCONT));
8890         loopnest--;
8891
8892         return status;
8893 }
8894
8895 static int
8896 evalfor(union node *n, int flags)
8897 {
8898         struct arglist arglist;
8899         union node *argp;
8900         struct strlist *sp;
8901         struct stackmark smark;
8902         int status = 0;
8903
8904         setstackmark(&smark);
8905         arglist.list = NULL;
8906         arglist.lastp = &arglist.list;
8907         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8908                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8909         }
8910         *arglist.lastp = NULL;
8911
8912         loopnest++;
8913         flags &= EV_TESTED;
8914         for (sp = arglist.list; sp; sp = sp->next) {
8915                 setvar0(n->nfor.var, sp->text);
8916                 status = evaltree(n->nfor.body, flags);
8917                 if (skiploop() & ~SKIPCONT)
8918                         break;
8919         }
8920         loopnest--;
8921         popstackmark(&smark);
8922
8923         return status;
8924 }
8925
8926 static int
8927 evalcase(union node *n, int flags)
8928 {
8929         union node *cp;
8930         union node *patp;
8931         struct arglist arglist;
8932         struct stackmark smark;
8933         int status = 0;
8934
8935         setstackmark(&smark);
8936         arglist.list = NULL;
8937         arglist.lastp = &arglist.list;
8938         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8939         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8940                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8941                         if (casematch(patp, arglist.list->text)) {
8942                                 /* Ensure body is non-empty as otherwise
8943                                  * EV_EXIT may prevent us from setting the
8944                                  * exit status.
8945                                  */
8946                                 if (evalskip == 0 && cp->nclist.body) {
8947                                         status = evaltree(cp->nclist.body, flags);
8948                                 }
8949                                 goto out;
8950                         }
8951                 }
8952         }
8953  out:
8954         popstackmark(&smark);
8955
8956         return status;
8957 }
8958
8959 /*
8960  * Kick off a subshell to evaluate a tree.
8961  */
8962 static int
8963 evalsubshell(union node *n, int flags)
8964 {
8965         struct job *jp;
8966         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8967         int status;
8968
8969         expredir(n->nredir.redirect);
8970         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8971                 goto nofork;
8972         INT_OFF;
8973         if (backgnd == FORK_FG)
8974                 get_tty_state();
8975         jp = makejob(/*n,*/ 1);
8976         if (forkshell(jp, n, backgnd) == 0) {
8977                 /* child */
8978                 INT_ON;
8979                 flags |= EV_EXIT;
8980                 if (backgnd)
8981                         flags &= ~EV_TESTED;
8982  nofork:
8983                 redirect(n->nredir.redirect, 0);
8984                 evaltreenr(n->nredir.n, flags);
8985                 /* never returns */
8986         }
8987         /* parent */
8988         status = 0;
8989         if (backgnd == FORK_FG)
8990                 status = waitforjob(jp);
8991         INT_ON;
8992         return status;
8993 }
8994
8995 /*
8996  * Compute the names of the files in a redirection list.
8997  */
8998 static void fixredir(union node *, const char *, int);
8999 static void
9000 expredir(union node *n)
9001 {
9002         union node *redir;
9003
9004         for (redir = n; redir; redir = redir->nfile.next) {
9005                 struct arglist fn;
9006
9007                 fn.list = NULL;
9008                 fn.lastp = &fn.list;
9009                 switch (redir->type) {
9010                 case NFROMTO:
9011                 case NFROM:
9012                 case NTO:
9013 #if BASH_REDIR_OUTPUT
9014                 case NTO2:
9015 #endif
9016                 case NCLOBBER:
9017                 case NAPPEND:
9018                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9019                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9020 #if BASH_REDIR_OUTPUT
9021  store_expfname:
9022 #endif
9023 #if 0
9024 // By the design of stack allocator, the loop of this kind:
9025 //      while true; do while true; do break; done </dev/null; done
9026 // will look like a memory leak: ash plans to free expfname's
9027 // of "/dev/null" as soon as it finishes running the loop
9028 // (in this case, never).
9029 // This "fix" is wrong:
9030                         if (redir->nfile.expfname)
9031                                 stunalloc(redir->nfile.expfname);
9032 // It results in corrupted state of stacked allocations.
9033 #endif
9034                         redir->nfile.expfname = fn.list->text;
9035                         break;
9036                 case NFROMFD:
9037                 case NTOFD: /* >& */
9038                         if (redir->ndup.vname) {
9039                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9040                                 if (fn.list == NULL)
9041                                         ash_msg_and_raise_error("redir error");
9042 #if BASH_REDIR_OUTPUT
9043 //FIXME: we used expandarg with different args!
9044                                 if (!isdigit_str9(fn.list->text)) {
9045                                         /* >&file, not >&fd */
9046                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9047                                                 ash_msg_and_raise_error("redir error");
9048                                         redir->type = NTO2;
9049                                         goto store_expfname;
9050                                 }
9051 #endif
9052                                 fixredir(redir, fn.list->text, 1);
9053                         }
9054                         break;
9055                 }
9056         }
9057 }
9058
9059 /*
9060  * Evaluate a pipeline.  All the processes in the pipeline are children
9061  * of the process creating the pipeline.  (This differs from some versions
9062  * of the shell, which make the last process in a pipeline the parent
9063  * of all the rest.)
9064  */
9065 static int
9066 evalpipe(union node *n, int flags)
9067 {
9068         struct job *jp;
9069         struct nodelist *lp;
9070         int pipelen;
9071         int prevfd;
9072         int pip[2];
9073         int status = 0;
9074
9075         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9076         pipelen = 0;
9077         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9078                 pipelen++;
9079         flags |= EV_EXIT;
9080         INT_OFF;
9081         if (n->npipe.pipe_backgnd == 0)
9082                 get_tty_state();
9083         jp = makejob(/*n,*/ pipelen);
9084         prevfd = -1;
9085         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9086                 prehash(lp->n);
9087                 pip[1] = -1;
9088                 if (lp->next) {
9089                         if (pipe(pip) < 0) {
9090                                 close(prevfd);
9091                                 ash_msg_and_raise_error("pipe call failed");
9092                         }
9093                 }
9094                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9095                         /* child */
9096                         INT_ON;
9097                         if (pip[1] >= 0) {
9098                                 close(pip[0]);
9099                         }
9100                         if (prevfd > 0) {
9101                                 dup2(prevfd, 0);
9102                                 close(prevfd);
9103                         }
9104                         if (pip[1] > 1) {
9105                                 dup2(pip[1], 1);
9106                                 close(pip[1]);
9107                         }
9108                         evaltreenr(lp->n, flags);
9109                         /* never returns */
9110                 }
9111                 /* parent */
9112                 if (prevfd >= 0)
9113                         close(prevfd);
9114                 prevfd = pip[0];
9115                 /* Don't want to trigger debugging */
9116                 if (pip[1] != -1)
9117                         close(pip[1]);
9118         }
9119         if (n->npipe.pipe_backgnd == 0) {
9120                 status = waitforjob(jp);
9121                 TRACE(("evalpipe:  job done exit status %d\n", status));
9122         }
9123         INT_ON;
9124
9125         return status;
9126 }
9127
9128 /*
9129  * Controls whether the shell is interactive or not.
9130  */
9131 static void
9132 setinteractive(int on)
9133 {
9134         static smallint is_interactive;
9135
9136         if (++on == is_interactive)
9137                 return;
9138         is_interactive = on;
9139         setsignal(SIGINT);
9140         setsignal(SIGQUIT);
9141         setsignal(SIGTERM);
9142 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9143         if (is_interactive > 1) {
9144                 /* Looks like they want an interactive shell */
9145                 static smallint did_banner;
9146
9147                 if (!did_banner) {
9148                         /* note: ash and hush share this string */
9149                         out1fmt("\n\n%s %s\n"
9150                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9151                                 "\n",
9152                                 bb_banner,
9153                                 "built-in shell (ash)"
9154                         );
9155                         did_banner = 1;
9156                 }
9157         }
9158 #endif
9159 }
9160
9161 static void
9162 optschanged(void)
9163 {
9164 #if DEBUG
9165         opentrace();
9166 #endif
9167         setinteractive(iflag);
9168         setjobctl(mflag);
9169 #if ENABLE_FEATURE_EDITING_VI
9170         if (viflag)
9171                 line_input_state->flags |= VI_MODE;
9172         else
9173                 line_input_state->flags &= ~VI_MODE;
9174 #else
9175         viflag = 0; /* forcibly keep the option off */
9176 #endif
9177 }
9178
9179 struct localvar_list {
9180         struct localvar_list *next;
9181         struct localvar *lv;
9182 };
9183
9184 static struct localvar_list *localvar_stack;
9185
9186 /*
9187  * Called after a function returns.
9188  * Interrupts must be off.
9189  */
9190 static void
9191 poplocalvars(int keep)
9192 {
9193         struct localvar_list *ll;
9194         struct localvar *lvp, *next;
9195         struct var *vp;
9196
9197         INT_OFF;
9198         ll = localvar_stack;
9199         localvar_stack = ll->next;
9200
9201         next = ll->lv;
9202         free(ll);
9203
9204         while ((lvp = next) != NULL) {
9205                 next = lvp->next;
9206                 vp = lvp->vp;
9207                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9208                 if (keep) {
9209                         int bits = VSTRFIXED;
9210
9211                         if (lvp->flags != VUNSET) {
9212                                 if (vp->var_text == lvp->text)
9213                                         bits |= VTEXTFIXED;
9214                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9215                                         free((char*)lvp->text);
9216                         }
9217
9218                         vp->flags &= ~bits;
9219                         vp->flags |= (lvp->flags & bits);
9220
9221                         if ((vp->flags &
9222                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9223                                 unsetvar(vp->var_text);
9224                 } else if (vp == NULL) {        /* $- saved */
9225                         memcpy(optlist, lvp->text, sizeof(optlist));
9226                         free((char*)lvp->text);
9227                         optschanged();
9228                 } else if (lvp->flags == VUNSET) {
9229                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9230                         unsetvar(vp->var_text);
9231                 } else {
9232                         if (vp->var_func)
9233                                 vp->var_func(var_end(lvp->text));
9234                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9235                                 free((char*)vp->var_text);
9236                         vp->flags = lvp->flags;
9237                         vp->var_text = lvp->text;
9238                 }
9239                 free(lvp);
9240         }
9241         INT_ON;
9242 }
9243
9244 /*
9245  * Create a new localvar environment.
9246  */
9247 static struct localvar_list *
9248 pushlocalvars(void)
9249 {
9250         struct localvar_list *ll;
9251
9252         INT_OFF;
9253         ll = ckzalloc(sizeof(*ll));
9254         /*ll->lv = NULL; - zalloc did it */
9255         ll->next = localvar_stack;
9256         localvar_stack = ll;
9257         INT_ON;
9258
9259         return ll->next;
9260 }
9261
9262 static void
9263 unwindlocalvars(struct localvar_list *stop)
9264 {
9265         while (localvar_stack != stop)
9266                 poplocalvars(0);
9267 }
9268
9269 static int
9270 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9271 {
9272         volatile struct shparam saveparam;
9273         struct jmploc *volatile savehandler;
9274         struct jmploc jmploc;
9275         int e;
9276
9277         saveparam = shellparam;
9278         savehandler = exception_handler;
9279         e = setjmp(jmploc.loc);
9280         if (e) {
9281                 goto funcdone;
9282         }
9283         INT_OFF;
9284         exception_handler = &jmploc;
9285         shellparam.malloced = 0;
9286         func->count++;
9287         funcnest++;
9288         INT_ON;
9289         shellparam.nparam = argc - 1;
9290         shellparam.p = argv + 1;
9291 #if ENABLE_ASH_GETOPTS
9292         shellparam.optind = 1;
9293         shellparam.optoff = -1;
9294 #endif
9295         pushlocalvars();
9296         evaltree(func->n.narg.next, flags & EV_TESTED);
9297         poplocalvars(0);
9298  funcdone:
9299         INT_OFF;
9300         funcnest--;
9301         freefunc(func);
9302         freeparam(&shellparam);
9303         shellparam = saveparam;
9304         exception_handler = savehandler;
9305         INT_ON;
9306         evalskip &= ~SKIPFUNC;
9307         return e;
9308 }
9309
9310 /*
9311  * Make a variable a local variable.  When a variable is made local, it's
9312  * value and flags are saved in a localvar structure.  The saved values
9313  * will be restored when the shell function returns.  We handle the name
9314  * "-" as a special case: it makes changes to "set +-options" local
9315  * (options will be restored on return from the function).
9316  */
9317 static void
9318 mklocal(char *name)
9319 {
9320         struct localvar *lvp;
9321         struct var **vpp;
9322         struct var *vp;
9323         char *eq = strchr(name, '=');
9324
9325         INT_OFF;
9326         /* Cater for duplicate "local". Examples:
9327          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9328          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9329          */
9330         lvp = localvar_stack->lv;
9331         while (lvp) {
9332                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9333                         if (eq)
9334                                 setvareq(name, 0);
9335                         /* else:
9336                          * it's a duplicate "local VAR" declaration, do nothing
9337                          */
9338                         goto ret;
9339                 }
9340                 lvp = lvp->next;
9341         }
9342
9343         lvp = ckzalloc(sizeof(*lvp));
9344         if (LONE_DASH(name)) {
9345                 char *p;
9346                 p = ckmalloc(sizeof(optlist));
9347                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9348                 vp = NULL;
9349         } else {
9350                 vpp = hashvar(name);
9351                 vp = *findvar(vpp, name);
9352                 if (vp == NULL) {
9353                         /* variable did not exist yet */
9354                         if (eq)
9355                                 vp = setvareq(name, VSTRFIXED);
9356                         else
9357                                 vp = setvar(name, NULL, VSTRFIXED);
9358                         lvp->flags = VUNSET;
9359                 } else {
9360                         lvp->text = vp->var_text;
9361                         lvp->flags = vp->flags;
9362                         /* make sure neither "struct var" nor string gets freed
9363                          * during (un)setting:
9364                          */
9365                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9366                         if (eq)
9367                                 setvareq(name, 0);
9368                         else
9369                                 /* "local VAR" unsets VAR: */
9370                                 setvar0(name, NULL);
9371                 }
9372         }
9373         lvp->vp = vp;
9374         lvp->next = localvar_stack->lv;
9375         localvar_stack->lv = lvp;
9376  ret:
9377         INT_ON;
9378 }
9379
9380 /*
9381  * The "local" command.
9382  */
9383 static int FAST_FUNC
9384 localcmd(int argc UNUSED_PARAM, char **argv)
9385 {
9386         char *name;
9387
9388         if (!localvar_stack)
9389                 ash_msg_and_raise_error("not in a function");
9390
9391         argv = argptr;
9392         while ((name = *argv++) != NULL) {
9393                 mklocal(name);
9394         }
9395         return 0;
9396 }
9397
9398 static int FAST_FUNC
9399 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9400 {
9401         return 1;
9402 }
9403
9404 static int FAST_FUNC
9405 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9406 {
9407         return 0;
9408 }
9409
9410 static int FAST_FUNC
9411 execcmd(int argc UNUSED_PARAM, char **argv)
9412 {
9413         optionarg = NULL;
9414         while (nextopt("a:") != '\0')
9415                 /* nextopt() sets optionarg to "-a ARGV0" */;
9416
9417         argv = argptr;
9418         if (argv[0]) {
9419                 char *prog;
9420
9421                 iflag = 0;              /* exit on error */
9422                 mflag = 0;
9423                 optschanged();
9424                 /* We should set up signals for "exec CMD"
9425                  * the same way as for "CMD" without "exec".
9426                  * But optschanged->setinteractive->setsignal
9427                  * still thought we are a root shell. Therefore, for example,
9428                  * SIGQUIT is still set to IGN. Fix it:
9429                  */
9430                 shlvl++;
9431                 setsignal(SIGQUIT);
9432                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9433                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9434                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9435
9436                 prog = argv[0];
9437                 if (optionarg)
9438                         argv[0] = optionarg;
9439                 shellexec(prog, argv, pathval(), 0);
9440                 /* NOTREACHED */
9441         }
9442         return 0;
9443 }
9444
9445 /*
9446  * The return command.
9447  */
9448 static int FAST_FUNC
9449 returncmd(int argc UNUSED_PARAM, char **argv)
9450 {
9451         /*
9452          * If called outside a function, do what ksh does;
9453          * skip the rest of the file.
9454          */
9455         evalskip = SKIPFUNC;
9456         return argv[1] ? number(argv[1]) : exitstatus;
9457 }
9458
9459 /* Forward declarations for builtintab[] */
9460 static int breakcmd(int, char **) FAST_FUNC;
9461 static int dotcmd(int, char **) FAST_FUNC;
9462 static int evalcmd(int, char **, int) FAST_FUNC;
9463 static int exitcmd(int, char **) FAST_FUNC;
9464 static int exportcmd(int, char **) FAST_FUNC;
9465 #if ENABLE_ASH_GETOPTS
9466 static int getoptscmd(int, char **) FAST_FUNC;
9467 #endif
9468 #if ENABLE_ASH_HELP
9469 static int helpcmd(int, char **) FAST_FUNC;
9470 #endif
9471 #if MAX_HISTORY
9472 static int historycmd(int, char **) FAST_FUNC;
9473 #endif
9474 #if ENABLE_FEATURE_SH_MATH
9475 static int letcmd(int, char **) FAST_FUNC;
9476 #endif
9477 static int readcmd(int, char **) FAST_FUNC;
9478 static int setcmd(int, char **) FAST_FUNC;
9479 static int shiftcmd(int, char **) FAST_FUNC;
9480 static int timescmd(int, char **) FAST_FUNC;
9481 static int trapcmd(int, char **) FAST_FUNC;
9482 static int umaskcmd(int, char **) FAST_FUNC;
9483 static int unsetcmd(int, char **) FAST_FUNC;
9484 static int ulimitcmd(int, char **) FAST_FUNC;
9485
9486 #define BUILTIN_NOSPEC          "0"
9487 #define BUILTIN_SPECIAL         "1"
9488 #define BUILTIN_REGULAR         "2"
9489 #define BUILTIN_SPEC_REG        "3"
9490 #define BUILTIN_ASSIGN          "4"
9491 #define BUILTIN_SPEC_ASSG       "5"
9492 #define BUILTIN_REG_ASSG        "6"
9493 #define BUILTIN_SPEC_REG_ASSG   "7"
9494
9495 /* Stubs for calling non-FAST_FUNC's */
9496 #if ENABLE_ASH_ECHO
9497 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9498 #endif
9499 #if ENABLE_ASH_PRINTF
9500 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9501 #endif
9502 #if ENABLE_ASH_TEST || BASH_TEST2
9503 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9504 #endif
9505
9506 /* Keep these in proper order since it is searched via bsearch() */
9507 static const struct builtincmd builtintab[] = {
9508         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9509         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9510 #if ENABLE_ASH_TEST
9511         { BUILTIN_REGULAR       "["       , testcmd    },
9512 #endif
9513 #if BASH_TEST2
9514         { BUILTIN_REGULAR       "[["      , testcmd    },
9515 #endif
9516 #if ENABLE_ASH_ALIAS
9517         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9518 #endif
9519 #if JOBS
9520         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9521 #endif
9522         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9523         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9524         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9525 #if ENABLE_ASH_CMDCMD
9526         { BUILTIN_REGULAR       "command" , commandcmd },
9527 #endif
9528         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9529 #if ENABLE_ASH_ECHO
9530         { BUILTIN_REGULAR       "echo"    , echocmd    },
9531 #endif
9532         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9533         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9534         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9535         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9536         { BUILTIN_REGULAR       "false"   , falsecmd   },
9537 #if JOBS
9538         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9539 #endif
9540 #if ENABLE_ASH_GETOPTS
9541         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9542 #endif
9543         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9544 #if ENABLE_ASH_HELP
9545         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9546 #endif
9547 #if MAX_HISTORY
9548         { BUILTIN_NOSPEC        "history" , historycmd },
9549 #endif
9550 #if JOBS
9551         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9552         { BUILTIN_REGULAR       "kill"    , killcmd    },
9553 #endif
9554 #if ENABLE_FEATURE_SH_MATH
9555         { BUILTIN_NOSPEC        "let"     , letcmd     },
9556 #endif
9557         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9558 #if ENABLE_ASH_PRINTF
9559         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9560 #endif
9561         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9562         { BUILTIN_REGULAR       "read"    , readcmd    },
9563         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9564         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9565         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9566         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9567 #if BASH_SOURCE
9568         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9569 #endif
9570 #if ENABLE_ASH_TEST
9571         { BUILTIN_REGULAR       "test"    , testcmd    },
9572 #endif
9573         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9574         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9575         { BUILTIN_REGULAR       "true"    , truecmd    },
9576         { BUILTIN_NOSPEC        "type"    , typecmd    },
9577         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9578         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9579 #if ENABLE_ASH_ALIAS
9580         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9581 #endif
9582         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9583         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9584 };
9585
9586 /* Should match the above table! */
9587 #define COMMANDCMD (builtintab + \
9588         /* . : */       2 + \
9589         /* [ */         1 * ENABLE_ASH_TEST + \
9590         /* [[ */        1 * BASH_TEST2 + \
9591         /* alias */     1 * ENABLE_ASH_ALIAS + \
9592         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9593         /* break cd cddir  */   3)
9594 #define EVALCMD (COMMANDCMD + \
9595         /* command */   1 * ENABLE_ASH_CMDCMD + \
9596         /* continue */  1 + \
9597         /* echo */      1 * ENABLE_ASH_ECHO + \
9598         0)
9599 #define EXECCMD (EVALCMD + \
9600         /* eval */      1)
9601
9602 /*
9603  * Search the table of builtin commands.
9604  */
9605 static int
9606 pstrcmp1(const void *a, const void *b)
9607 {
9608         return strcmp((char*)a, *(char**)b + 1);
9609 }
9610 static struct builtincmd *
9611 find_builtin(const char *name)
9612 {
9613         struct builtincmd *bp;
9614
9615         bp = bsearch(
9616                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9617                 pstrcmp1
9618         );
9619         return bp;
9620 }
9621
9622 /*
9623  * Execute a simple command.
9624  */
9625 static int
9626 isassignment(const char *p)
9627 {
9628         const char *q = endofname(p);
9629         if (p == q)
9630                 return 0;
9631         return *q == '=';
9632 }
9633 static int FAST_FUNC
9634 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9635 {
9636         /* Preserve exitstatus of a previous possible redirection
9637          * as POSIX mandates */
9638         return back_exitstatus;
9639 }
9640 static int
9641 evalcommand(union node *cmd, int flags)
9642 {
9643         static const struct builtincmd null_bltin = {
9644                 "\0\0", bltincmd /* why three NULs? */
9645         };
9646         struct localvar_list *localvar_stop;
9647         struct redirtab *redir_stop;
9648         struct stackmark smark;
9649         union node *argp;
9650         struct arglist arglist;
9651         struct arglist varlist;
9652         char **argv;
9653         int argc;
9654         const struct strlist *sp;
9655         struct cmdentry cmdentry;
9656         struct job *jp;
9657         char *lastarg;
9658         const char *path;
9659         int spclbltin;
9660         int status;
9661         char **nargv;
9662         smallint cmd_is_exec;
9663
9664         /* First expand the arguments. */
9665         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9666         setstackmark(&smark);
9667         localvar_stop = pushlocalvars();
9668         back_exitstatus = 0;
9669
9670         cmdentry.cmdtype = CMDBUILTIN;
9671         cmdentry.u.cmd = &null_bltin;
9672         varlist.lastp = &varlist.list;
9673         *varlist.lastp = NULL;
9674         arglist.lastp = &arglist.list;
9675         *arglist.lastp = NULL;
9676
9677         argc = 0;
9678         if (cmd->ncmd.args) {
9679                 struct builtincmd *bcmd;
9680                 smallint pseudovarflag;
9681
9682                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9683                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9684
9685                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9686                         struct strlist **spp;
9687
9688                         spp = arglist.lastp;
9689                         if (pseudovarflag && isassignment(argp->narg.text))
9690                                 expandarg(argp, &arglist, EXP_VARTILDE);
9691                         else
9692                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9693
9694                         for (sp = *spp; sp; sp = sp->next)
9695                                 argc++;
9696                 }
9697         }
9698
9699         /* Reserve one extra spot at the front for shellexec. */
9700         nargv = stalloc(sizeof(char *) * (argc + 2));
9701         argv = ++nargv;
9702         for (sp = arglist.list; sp; sp = sp->next) {
9703                 TRACE(("evalcommand arg: %s\n", sp->text));
9704                 *nargv++ = sp->text;
9705         }
9706         *nargv = NULL;
9707
9708         lastarg = NULL;
9709         if (iflag && funcnest == 0 && argc > 0)
9710                 lastarg = nargv[-1];
9711
9712         expredir(cmd->ncmd.redirect);
9713         redir_stop = pushredir(cmd->ncmd.redirect);
9714         preverrout_fd = 2;
9715         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9716
9717         path = vpath.var_text;
9718         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9719                 struct strlist **spp;
9720                 char *p;
9721
9722                 spp = varlist.lastp;
9723                 expandarg(argp, &varlist, EXP_VARTILDE);
9724
9725                 mklocal((*spp)->text);
9726
9727                 /*
9728                  * Modify the command lookup path, if a PATH= assignment
9729                  * is present
9730                  */
9731                 p = (*spp)->text;
9732                 if (varcmp(p, path) == 0)
9733                         path = p;
9734         }
9735
9736         /* Print the command if xflag is set. */
9737         if (xflag) {
9738                 const char *pfx = "";
9739
9740                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9741
9742                 sp = varlist.list;
9743                 while (sp) {
9744                         char *varval = sp->text;
9745                         char *eq = strchrnul(varval, '=');
9746                         if (*eq)
9747                                 eq++;
9748                         fdprintf(preverrout_fd, "%s%.*s%s",
9749                                 pfx,
9750                                 (int)(eq - varval), varval,
9751                                 maybe_single_quote(eq)
9752                         );
9753                         sp = sp->next;
9754                         pfx = " ";
9755                 }
9756
9757                 sp = arglist.list;
9758                 while (sp) {
9759                         fdprintf(preverrout_fd, "%s%s",
9760                                 pfx,
9761                                 /* always quote if matches reserved word: */
9762                                 findkwd(sp->text)
9763                                 ? single_quote(sp->text)
9764                                 : maybe_single_quote(sp->text)
9765                         );
9766                         sp = sp->next;
9767                         pfx = " ";
9768                 }
9769                 safe_write(preverrout_fd, "\n", 1);
9770         }
9771
9772         cmd_is_exec = 0;
9773         spclbltin = -1;
9774
9775         /* Now locate the command. */
9776         if (argc) {
9777                 int cmd_flag = DO_ERR;
9778 #if ENABLE_ASH_CMDCMD
9779                 const char *oldpath = path + 5;
9780 #endif
9781                 path += 5;
9782                 for (;;) {
9783                         find_command(argv[0], &cmdentry, cmd_flag, path);
9784                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9785                                 flush_stdout_stderr();
9786                                 status = 127;
9787                                 goto bail;
9788                         }
9789
9790                         /* implement bltin and command here */
9791                         if (cmdentry.cmdtype != CMDBUILTIN)
9792                                 break;
9793                         if (spclbltin < 0)
9794                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9795                         if (cmdentry.u.cmd == EXECCMD)
9796                                 cmd_is_exec = 1;
9797 #if ENABLE_ASH_CMDCMD
9798                         if (cmdentry.u.cmd == COMMANDCMD) {
9799                                 path = oldpath;
9800                                 nargv = parse_command_args(argv, &path);
9801                                 if (!nargv)
9802                                         break;
9803                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9804                                  * nargv => "PROG". path is updated if -p.
9805                                  */
9806                                 argc -= nargv - argv;
9807                                 argv = nargv;
9808                                 cmd_flag |= DO_NOFUNC;
9809                         } else
9810 #endif
9811                                 break;
9812                 }
9813         }
9814
9815         if (status) {
9816  bail:
9817                 exitstatus = status;
9818
9819                 /* We have a redirection error. */
9820                 if (spclbltin > 0)
9821                         raise_exception(EXERROR);
9822
9823                 goto out;
9824         }
9825
9826         /* Execute the command. */
9827         switch (cmdentry.cmdtype) {
9828         default: {
9829
9830 #if ENABLE_FEATURE_SH_NOFORK
9831 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9832  *     around run_nofork_applet() call.
9833  * (2) Should this check also be done in forkshell()?
9834  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9835  */
9836                 /* find_command() encodes applet_no as (-2 - applet_no) */
9837                 int applet_no = (- cmdentry.u.index - 2);
9838                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9839                         listsetvar(varlist.list, VEXPORT|VSTACK);
9840                         /* run <applet>_main() */
9841                         status = run_nofork_applet(applet_no, argv);
9842                         break;
9843                 }
9844 #endif
9845                 /* Can we avoid forking off? For example, very last command
9846                  * in a script or a subshell does not need forking,
9847                  * we can just exec it.
9848                  */
9849                 if (!(flags & EV_EXIT) || may_have_traps) {
9850                         /* No, forking off a child is necessary */
9851                         INT_OFF;
9852                         get_tty_state();
9853                         jp = makejob(/*cmd,*/ 1);
9854                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9855                                 /* parent */
9856                                 status = waitforjob(jp);
9857                                 INT_ON;
9858                                 TRACE(("forked child exited with %d\n", status));
9859                                 break;
9860                         }
9861                         /* child */
9862                         FORCE_INT_ON;
9863                         /* fall through to exec'ing external program */
9864                 }
9865                 listsetvar(varlist.list, VEXPORT|VSTACK);
9866                 shellexec(argv[0], argv, path, cmdentry.u.index);
9867                 /* NOTREACHED */
9868         } /* default */
9869         case CMDBUILTIN:
9870                 if (spclbltin > 0 || argc == 0) {
9871                         poplocalvars(1);
9872                         if (cmd_is_exec && argc > 1)
9873                                 listsetvar(varlist.list, VEXPORT);
9874                 }
9875
9876                 /* Tight loop with builtins only:
9877                  * "while kill -0 $child; do true; done"
9878                  * will never exit even if $child died, unless we do this
9879                  * to reap the zombie and make kill detect that it's gone: */
9880                 dowait(DOWAIT_NONBLOCK, NULL);
9881
9882                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9883                         if (exception_type == EXERROR && spclbltin <= 0) {
9884                                 FORCE_INT_ON;
9885                                 goto readstatus;
9886                         }
9887  raise:
9888                         longjmp(exception_handler->loc, 1);
9889                 }
9890                 goto readstatus;
9891
9892         case CMDFUNCTION:
9893                 poplocalvars(1);
9894                 /* See above for the rationale */
9895                 dowait(DOWAIT_NONBLOCK, NULL);
9896                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9897                         goto raise;
9898  readstatus:
9899                 status = exitstatus;
9900                 break;
9901         } /* switch */
9902
9903  out:
9904         if (cmd->ncmd.redirect)
9905                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9906         unwindredir(redir_stop);
9907         unwindlocalvars(localvar_stop);
9908         if (lastarg) {
9909                 /* dsl: I think this is intended to be used to support
9910                  * '_' in 'vi' command mode during line editing...
9911                  * However I implemented that within libedit itself.
9912                  */
9913                 setvar0("_", lastarg);
9914         }
9915         popstackmark(&smark);
9916
9917         return status;
9918 }
9919
9920 static int
9921 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9922 {
9923         char *volatile savecmdname;
9924         struct jmploc *volatile savehandler;
9925         struct jmploc jmploc;
9926         int status;
9927         int i;
9928
9929         savecmdname = commandname;
9930         savehandler = exception_handler;
9931         i = setjmp(jmploc.loc);
9932         if (i)
9933                 goto cmddone;
9934         exception_handler = &jmploc;
9935         commandname = argv[0];
9936         argptr = argv + 1;
9937         optptr = NULL;                  /* initialize nextopt */
9938         if (cmd == EVALCMD)
9939                 status = evalcmd(argc, argv, flags);
9940         else
9941                 status = (*cmd->builtin)(argc, argv);
9942         flush_stdout_stderr();
9943         status |= ferror(stdout);
9944         exitstatus = status;
9945  cmddone:
9946         clearerr(stdout);
9947         commandname = savecmdname;
9948         exception_handler = savehandler;
9949
9950         return i;
9951 }
9952
9953 static int
9954 goodname(const char *p)
9955 {
9956         return endofname(p)[0] == '\0';
9957 }
9958
9959
9960 /*
9961  * Search for a command.  This is called before we fork so that the
9962  * location of the command will be available in the parent as well as
9963  * the child.  The check for "goodname" is an overly conservative
9964  * check that the name will not be subject to expansion.
9965  */
9966 static void
9967 prehash(union node *n)
9968 {
9969         struct cmdentry entry;
9970
9971         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9972                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9973 }
9974
9975
9976 /* ============ Builtin commands
9977  *
9978  * Builtin commands whose functions are closely tied to evaluation
9979  * are implemented here.
9980  */
9981
9982 /*
9983  * Handle break and continue commands.  Break, continue, and return are
9984  * all handled by setting the evalskip flag.  The evaluation routines
9985  * above all check this flag, and if it is set they start skipping
9986  * commands rather than executing them.  The variable skipcount is
9987  * the number of loops to break/continue, or the number of function
9988  * levels to return.  (The latter is always 1.)  It should probably
9989  * be an error to break out of more loops than exist, but it isn't
9990  * in the standard shell so we don't make it one here.
9991  */
9992 static int FAST_FUNC
9993 breakcmd(int argc UNUSED_PARAM, char **argv)
9994 {
9995         int n = argv[1] ? number(argv[1]) : 1;
9996
9997         if (n <= 0)
9998                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9999         if (n > loopnest)
10000                 n = loopnest;
10001         if (n > 0) {
10002                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10003                 skipcount = n;
10004         }
10005         return 0;
10006 }
10007
10008
10009 /*
10010  * This implements the input routines used by the parser.
10011  */
10012
10013 enum {
10014         INPUT_PUSH_FILE = 1,
10015         INPUT_NOFILE_OK = 2,
10016 };
10017
10018 static smallint checkkwd;
10019 /* values of checkkwd variable */
10020 #define CHKALIAS        0x1
10021 #define CHKKWD          0x2
10022 #define CHKNL           0x4
10023 #define CHKEOFMARK      0x8
10024
10025 /*
10026  * Push a string back onto the input at this current parsefile level.
10027  * We handle aliases this way.
10028  */
10029 #if !ENABLE_ASH_ALIAS
10030 #define pushstring(s, ap) pushstring(s)
10031 #endif
10032 static void
10033 pushstring(char *s, struct alias *ap)
10034 {
10035         struct strpush *sp;
10036         int len;
10037
10038         len = strlen(s);
10039         INT_OFF;
10040         if (g_parsefile->strpush) {
10041                 sp = ckzalloc(sizeof(*sp));
10042                 sp->prev = g_parsefile->strpush;
10043         } else {
10044                 sp = &(g_parsefile->basestrpush);
10045         }
10046         g_parsefile->strpush = sp;
10047         sp->prev_string = g_parsefile->next_to_pgetc;
10048         sp->prev_left_in_line = g_parsefile->left_in_line;
10049         sp->unget = g_parsefile->unget;
10050         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10051 #if ENABLE_ASH_ALIAS
10052         sp->ap = ap;
10053         if (ap) {
10054                 ap->flag |= ALIASINUSE;
10055                 sp->string = s;
10056         }
10057 #endif
10058         g_parsefile->next_to_pgetc = s;
10059         g_parsefile->left_in_line = len;
10060         g_parsefile->unget = 0;
10061         INT_ON;
10062 }
10063
10064 static void
10065 popstring(void)
10066 {
10067         struct strpush *sp = g_parsefile->strpush;
10068
10069         INT_OFF;
10070 #if ENABLE_ASH_ALIAS
10071         if (sp->ap) {
10072                 if (g_parsefile->next_to_pgetc[-1] == ' '
10073                  || g_parsefile->next_to_pgetc[-1] == '\t'
10074                 ) {
10075                         checkkwd |= CHKALIAS;
10076                 }
10077                 if (sp->string != sp->ap->val) {
10078                         free(sp->string);
10079                 }
10080                 sp->ap->flag &= ~ALIASINUSE;
10081                 if (sp->ap->flag & ALIASDEAD) {
10082                         unalias(sp->ap->name);
10083                 }
10084         }
10085 #endif
10086         g_parsefile->next_to_pgetc = sp->prev_string;
10087         g_parsefile->left_in_line = sp->prev_left_in_line;
10088         g_parsefile->unget = sp->unget;
10089         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10090         g_parsefile->strpush = sp->prev;
10091         if (sp != &(g_parsefile->basestrpush))
10092                 free(sp);
10093         INT_ON;
10094 }
10095
10096 static int
10097 preadfd(void)
10098 {
10099         int nr;
10100         char *buf = g_parsefile->buf;
10101
10102         g_parsefile->next_to_pgetc = buf;
10103 #if ENABLE_FEATURE_EDITING
10104  retry:
10105         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10106                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10107         else {
10108                 int timeout = -1;
10109 # if ENABLE_ASH_IDLE_TIMEOUT
10110                 if (iflag) {
10111                         const char *tmout_var = lookupvar("TMOUT");
10112                         if (tmout_var) {
10113                                 timeout = atoi(tmout_var) * 1000;
10114                                 if (timeout <= 0)
10115                                         timeout = -1;
10116                         }
10117                 }
10118 # endif
10119 # if ENABLE_FEATURE_TAB_COMPLETION
10120                 line_input_state->path_lookup = pathval();
10121 # endif
10122                 reinit_unicode_for_ash();
10123                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10124                 if (nr == 0) {
10125                         /* ^C pressed, "convert" to SIGINT */
10126                         write(STDOUT_FILENO, "^C", 2);
10127                         if (trap[SIGINT]) {
10128                                 buf[0] = '\n';
10129                                 buf[1] = '\0';
10130                                 raise(SIGINT);
10131                                 return 1;
10132                         }
10133                         exitstatus = 128 + SIGINT;
10134                         bb_putchar('\n');
10135                         goto retry;
10136                 }
10137                 if (nr < 0) {
10138                         if (errno == 0) {
10139                                 /* Ctrl+D pressed */
10140                                 nr = 0;
10141                         }
10142 # if ENABLE_ASH_IDLE_TIMEOUT
10143                         else if (errno == EAGAIN && timeout > 0) {
10144                                 puts("\007timed out waiting for input: auto-logout");
10145                                 exitshell();
10146                         }
10147 # endif
10148                 }
10149         }
10150 #else
10151         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10152 #endif
10153
10154 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10155         if (nr < 0) {
10156                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10157                         int flags = fcntl(0, F_GETFL);
10158                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10159                                 flags &= ~O_NONBLOCK;
10160                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10161                                         out2str("sh: turning off NDELAY mode\n");
10162                                         goto retry;
10163                                 }
10164                         }
10165                 }
10166         }
10167 #endif
10168         return nr;
10169 }
10170
10171 /*
10172  * Refill the input buffer and return the next input character:
10173  *
10174  * 1) If a string was pushed back on the input, pop it;
10175  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10176  *    or we are reading from a string so we can't refill the buffer,
10177  *    return EOF.
10178  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10179  * 4) Process input up to the next newline, deleting nul characters.
10180  */
10181 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10182 #define pgetc_debug(...) ((void)0)
10183 static int pgetc(void);
10184 static int
10185 preadbuffer(void)
10186 {
10187         char *q;
10188         int more;
10189
10190         if (g_parsefile->strpush) {
10191 #if ENABLE_ASH_ALIAS
10192                 if (g_parsefile->left_in_line == -1
10193                  && g_parsefile->strpush->ap
10194                  && g_parsefile->next_to_pgetc[-1] != ' '
10195                  && g_parsefile->next_to_pgetc[-1] != '\t'
10196                 ) {
10197                         pgetc_debug("preadbuffer PEOA");
10198                         return PEOA;
10199                 }
10200 #endif
10201                 popstring();
10202                 return pgetc();
10203         }
10204         /* on both branches above g_parsefile->left_in_line < 0.
10205          * "pgetc" needs refilling.
10206          */
10207
10208         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10209          * pungetc() may increment it a few times.
10210          * Assuming it won't increment it to less than -90.
10211          */
10212         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10213                 pgetc_debug("preadbuffer PEOF1");
10214                 /* even in failure keep left_in_line and next_to_pgetc
10215                  * in lock step, for correct multi-layer pungetc.
10216                  * left_in_line was decremented before preadbuffer(),
10217                  * must inc next_to_pgetc: */
10218                 g_parsefile->next_to_pgetc++;
10219                 return PEOF;
10220         }
10221
10222         more = g_parsefile->left_in_buffer;
10223         if (more <= 0) {
10224                 flush_stdout_stderr();
10225  again:
10226                 more = preadfd();
10227                 if (more <= 0) {
10228                         /* don't try reading again */
10229                         g_parsefile->left_in_line = -99;
10230                         pgetc_debug("preadbuffer PEOF2");
10231                         g_parsefile->next_to_pgetc++;
10232                         return PEOF;
10233                 }
10234         }
10235
10236         /* Find out where's the end of line.
10237          * Set g_parsefile->left_in_line
10238          * and g_parsefile->left_in_buffer acordingly.
10239          * NUL chars are deleted.
10240          */
10241         q = g_parsefile->next_to_pgetc;
10242         for (;;) {
10243                 char c;
10244
10245                 more--;
10246
10247                 c = *q;
10248                 if (c == '\0') {
10249                         memmove(q, q + 1, more);
10250                 } else {
10251                         q++;
10252                         if (c == '\n') {
10253                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10254                                 break;
10255                         }
10256                 }
10257
10258                 if (more <= 0) {
10259                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10260                         if (g_parsefile->left_in_line < 0)
10261                                 goto again;
10262                         break;
10263                 }
10264         }
10265         g_parsefile->left_in_buffer = more;
10266
10267         if (vflag) {
10268                 char save = *q;
10269                 *q = '\0';
10270                 out2str(g_parsefile->next_to_pgetc);
10271                 *q = save;
10272         }
10273
10274         pgetc_debug("preadbuffer at %d:%p'%s'",
10275                         g_parsefile->left_in_line,
10276                         g_parsefile->next_to_pgetc,
10277                         g_parsefile->next_to_pgetc);
10278         return (unsigned char)*g_parsefile->next_to_pgetc++;
10279 }
10280
10281 static void
10282 nlprompt(void)
10283 {
10284         g_parsefile->linno++;
10285         setprompt_if(doprompt, 2);
10286 }
10287 static void
10288 nlnoprompt(void)
10289 {
10290         g_parsefile->linno++;
10291         needprompt = doprompt;
10292 }
10293
10294 static int
10295 pgetc(void)
10296 {
10297         int c;
10298
10299         pgetc_debug("pgetc at %d:%p'%s'",
10300                         g_parsefile->left_in_line,
10301                         g_parsefile->next_to_pgetc,
10302                         g_parsefile->next_to_pgetc);
10303         if (g_parsefile->unget)
10304                 return g_parsefile->lastc[--g_parsefile->unget];
10305
10306         if (--g_parsefile->left_in_line >= 0)
10307                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10308         else
10309                 c = preadbuffer();
10310
10311         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10312         g_parsefile->lastc[0] = c;
10313
10314         return c;
10315 }
10316
10317 #if ENABLE_ASH_ALIAS
10318 static int
10319 pgetc_without_PEOA(void)
10320 {
10321         int c;
10322         do {
10323                 pgetc_debug("pgetc at %d:%p'%s'",
10324                                 g_parsefile->left_in_line,
10325                                 g_parsefile->next_to_pgetc,
10326                                 g_parsefile->next_to_pgetc);
10327                 c = pgetc();
10328         } while (c == PEOA);
10329         return c;
10330 }
10331 #else
10332 # define pgetc_without_PEOA() pgetc()
10333 #endif
10334
10335 /*
10336  * Undo a call to pgetc.  Only two characters may be pushed back.
10337  * PEOF may be pushed back.
10338  */
10339 static void
10340 pungetc(void)
10341 {
10342         g_parsefile->unget++;
10343 }
10344
10345 /* This one eats backslash+newline */
10346 static int
10347 pgetc_eatbnl(void)
10348 {
10349         int c;
10350
10351         while ((c = pgetc()) == '\\') {
10352                 if (pgetc() != '\n') {
10353                         pungetc();
10354                         break;
10355                 }
10356
10357                 nlprompt();
10358         }
10359
10360         return c;
10361 }
10362
10363 /*
10364  * To handle the "." command, a stack of input files is used.  Pushfile
10365  * adds a new entry to the stack and popfile restores the previous level.
10366  */
10367 static void
10368 pushfile(void)
10369 {
10370         struct parsefile *pf;
10371
10372         pf = ckzalloc(sizeof(*pf));
10373         pf->prev = g_parsefile;
10374         pf->pf_fd = -1;
10375         /*pf->strpush = NULL; - ckzalloc did it */
10376         /*pf->basestrpush.prev = NULL;*/
10377         /*pf->unget = 0;*/
10378         g_parsefile = pf;
10379 }
10380
10381 static void
10382 popfile(void)
10383 {
10384         struct parsefile *pf = g_parsefile;
10385
10386         if (pf == &basepf)
10387                 return;
10388
10389         INT_OFF;
10390         if (pf->pf_fd >= 0)
10391                 close(pf->pf_fd);
10392         free(pf->buf);
10393         while (pf->strpush)
10394                 popstring();
10395         g_parsefile = pf->prev;
10396         free(pf);
10397         INT_ON;
10398 }
10399
10400 /*
10401  * Return to top level.
10402  */
10403 static void
10404 popallfiles(void)
10405 {
10406         while (g_parsefile != &basepf)
10407                 popfile();
10408 }
10409
10410 /*
10411  * Close the file(s) that the shell is reading commands from.  Called
10412  * after a fork is done.
10413  */
10414 static void
10415 closescript(void)
10416 {
10417         popallfiles();
10418         if (g_parsefile->pf_fd > 0) {
10419                 close(g_parsefile->pf_fd);
10420                 g_parsefile->pf_fd = 0;
10421         }
10422 }
10423
10424 /*
10425  * Like setinputfile, but takes an open file descriptor.  Call this with
10426  * interrupts off.
10427  */
10428 static void
10429 setinputfd(int fd, int push)
10430 {
10431         if (push) {
10432                 pushfile();
10433                 g_parsefile->buf = NULL;
10434         }
10435         g_parsefile->pf_fd = fd;
10436         if (g_parsefile->buf == NULL)
10437                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10438         g_parsefile->left_in_buffer = 0;
10439         g_parsefile->left_in_line = 0;
10440         g_parsefile->linno = 1;
10441 }
10442
10443 /*
10444  * Set the input to take input from a file.  If push is set, push the
10445  * old input onto the stack first.
10446  */
10447 static int
10448 setinputfile(const char *fname, int flags)
10449 {
10450         int fd;
10451
10452         INT_OFF;
10453         fd = open(fname, O_RDONLY);
10454         if (fd < 0) {
10455                 if (flags & INPUT_NOFILE_OK)
10456                         goto out;
10457                 exitstatus = 127;
10458                 ash_msg_and_raise_error("can't open '%s'", fname);
10459         }
10460         if (fd < 10)
10461                 fd = savefd(fd);
10462         else
10463                 close_on_exec_on(fd);
10464         setinputfd(fd, flags & INPUT_PUSH_FILE);
10465  out:
10466         INT_ON;
10467         return fd;
10468 }
10469
10470 /*
10471  * Like setinputfile, but takes input from a string.
10472  */
10473 static void
10474 setinputstring(char *string)
10475 {
10476         INT_OFF;
10477         pushfile();
10478         g_parsefile->next_to_pgetc = string;
10479         g_parsefile->left_in_line = strlen(string);
10480         g_parsefile->buf = NULL;
10481         g_parsefile->linno = 1;
10482         INT_ON;
10483 }
10484
10485
10486 /*
10487  * Routines to check for mail.
10488  */
10489
10490 #if ENABLE_ASH_MAIL
10491
10492 /* Hash of mtimes of mailboxes */
10493 static unsigned mailtime_hash;
10494 /* Set if MAIL or MAILPATH is changed. */
10495 static smallint mail_var_path_changed;
10496
10497 /*
10498  * Print appropriate message(s) if mail has arrived.
10499  * If mail_var_path_changed is set,
10500  * then the value of MAIL has mail_var_path_changed,
10501  * so we just update the values.
10502  */
10503 static void
10504 chkmail(void)
10505 {
10506         const char *mpath;
10507         char *p;
10508         char *q;
10509         unsigned new_hash;
10510         struct stackmark smark;
10511         struct stat statb;
10512
10513         setstackmark(&smark);
10514         mpath = mpathset() ? mpathval() : mailval();
10515         new_hash = 0;
10516         for (;;) {
10517                 p = path_advance(&mpath, nullstr);
10518                 if (p == NULL)
10519                         break;
10520                 if (*p == '\0')
10521                         continue;
10522                 for (q = p; *q; q++)
10523                         continue;
10524 #if DEBUG
10525                 if (q[-1] != '/')
10526                         abort();
10527 #endif
10528                 q[-1] = '\0';                   /* delete trailing '/' */
10529                 if (stat(p, &statb) < 0) {
10530                         continue;
10531                 }
10532                 /* Very simplistic "hash": just a sum of all mtimes */
10533                 new_hash += (unsigned)statb.st_mtime;
10534         }
10535         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10536                 if (mailtime_hash != 0)
10537                         out2str("you have mail\n");
10538                 mailtime_hash = new_hash;
10539         }
10540         mail_var_path_changed = 0;
10541         popstackmark(&smark);
10542 }
10543
10544 static void FAST_FUNC
10545 changemail(const char *val UNUSED_PARAM)
10546 {
10547         mail_var_path_changed = 1;
10548 }
10549
10550 #endif /* ASH_MAIL */
10551
10552
10553 /* ============ ??? */
10554
10555 /*
10556  * Set the shell parameters.
10557  */
10558 static void
10559 setparam(char **argv)
10560 {
10561         char **newparam;
10562         char **ap;
10563         int nparam;
10564
10565         for (nparam = 0; argv[nparam]; nparam++)
10566                 continue;
10567         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10568         while (*argv) {
10569                 *ap++ = ckstrdup(*argv++);
10570         }
10571         *ap = NULL;
10572         freeparam(&shellparam);
10573         shellparam.malloced = 1;
10574         shellparam.nparam = nparam;
10575         shellparam.p = newparam;
10576 #if ENABLE_ASH_GETOPTS
10577         shellparam.optind = 1;
10578         shellparam.optoff = -1;
10579 #endif
10580 }
10581
10582 /*
10583  * Process shell options.  The global variable argptr contains a pointer
10584  * to the argument list; we advance it past the options.
10585  *
10586  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10587  * For a non-interactive shell, an error condition encountered
10588  * by a special built-in ... shall cause the shell to write a diagnostic message
10589  * to standard error and exit as shown in the following table:
10590  * Error                                           Special Built-In
10591  * ...
10592  * Utility syntax error (option or operand error)  Shall exit
10593  * ...
10594  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10595  * we see that bash does not do that (set "finishes" with error code 1 instead,
10596  * and shell continues), and people rely on this behavior!
10597  * Testcase:
10598  * set -o barfoo 2>/dev/null
10599  * echo $?
10600  *
10601  * Oh well. Let's mimic that.
10602  */
10603 static int
10604 plus_minus_o(char *name, int val)
10605 {
10606         int i;
10607
10608         if (name) {
10609                 for (i = 0; i < NOPTS; i++) {
10610                         if (strcmp(name, optnames(i)) == 0) {
10611                                 optlist[i] = val;
10612                                 return 0;
10613                         }
10614                 }
10615                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10616                 return 1;
10617         }
10618         for (i = 0; i < NOPTS; i++) {
10619                 if (val) {
10620                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10621                 } else {
10622                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10623                 }
10624         }
10625         return 0;
10626 }
10627 static void
10628 setoption(int flag, int val)
10629 {
10630         int i;
10631
10632         for (i = 0; i < NOPTS; i++) {
10633                 if (optletters(i) == flag) {
10634                         optlist[i] = val;
10635                         return;
10636                 }
10637         }
10638         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10639         /* NOTREACHED */
10640 }
10641 static int
10642 options(int cmdline)
10643 {
10644         char *p;
10645         int val;
10646         int c;
10647
10648         if (cmdline)
10649                 minusc = NULL;
10650         while ((p = *argptr) != NULL) {
10651                 c = *p++;
10652                 if (c != '-' && c != '+')
10653                         break;
10654                 argptr++;
10655                 val = 0; /* val = 0 if c == '+' */
10656                 if (c == '-') {
10657                         val = 1;
10658                         if (p[0] == '\0' || LONE_DASH(p)) {
10659                                 if (!cmdline) {
10660                                         /* "-" means turn off -x and -v */
10661                                         if (p[0] == '\0')
10662                                                 xflag = vflag = 0;
10663                                         /* "--" means reset params */
10664                                         else if (*argptr == NULL)
10665                                                 setparam(argptr);
10666                                 }
10667                                 break;    /* "-" or "--" terminates options */
10668                         }
10669                 }
10670                 /* first char was + or - */
10671                 while ((c = *p++) != '\0') {
10672                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10673                         if (c == 'c' && cmdline) {
10674                                 minusc = p;     /* command is after shell args */
10675                         } else if (c == 'o') {
10676                                 if (plus_minus_o(*argptr, val)) {
10677                                         /* it already printed err message */
10678                                         return 1; /* error */
10679                                 }
10680                                 if (*argptr)
10681                                         argptr++;
10682                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10683                                 isloginsh = 1;
10684                         /* bash does not accept +-login, we also won't */
10685                         } else if (cmdline && val && (c == '-')) { /* long options */
10686                                 if (strcmp(p, "login") == 0)
10687                                         isloginsh = 1;
10688                                 break;
10689                         } else {
10690                                 setoption(c, val);
10691                         }
10692                 }
10693         }
10694         return 0;
10695 }
10696
10697 /*
10698  * The shift builtin command.
10699  */
10700 static int FAST_FUNC
10701 shiftcmd(int argc UNUSED_PARAM, char **argv)
10702 {
10703         int n;
10704         char **ap1, **ap2;
10705
10706         n = 1;
10707         if (argv[1])
10708                 n = number(argv[1]);
10709         if (n > shellparam.nparam)
10710                 n = 0; /* bash compat, was = shellparam.nparam; */
10711         INT_OFF;
10712         shellparam.nparam -= n;
10713         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10714                 if (shellparam.malloced)
10715                         free(*ap1);
10716         }
10717         ap2 = shellparam.p;
10718         while ((*ap2++ = *ap1++) != NULL)
10719                 continue;
10720 #if ENABLE_ASH_GETOPTS
10721         shellparam.optind = 1;
10722         shellparam.optoff = -1;
10723 #endif
10724         INT_ON;
10725         return 0;
10726 }
10727
10728 /*
10729  * POSIX requires that 'set' (but not export or readonly) output the
10730  * variables in lexicographic order - by the locale's collating order (sigh).
10731  * Maybe we could keep them in an ordered balanced binary tree
10732  * instead of hashed lists.
10733  * For now just roll 'em through qsort for printing...
10734  */
10735 static int
10736 showvars(const char *sep_prefix, int on, int off)
10737 {
10738         const char *sep;
10739         char **ep, **epend;
10740
10741         ep = listvars(on, off, &epend);
10742         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10743
10744         sep = *sep_prefix ? " " : sep_prefix;
10745
10746         for (; ep < epend; ep++) {
10747                 const char *p;
10748                 const char *q;
10749
10750                 p = strchrnul(*ep, '=');
10751                 q = nullstr;
10752                 if (*p)
10753                         q = single_quote(++p);
10754                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10755         }
10756         return 0;
10757 }
10758
10759 /*
10760  * The set command builtin.
10761  */
10762 static int FAST_FUNC
10763 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10764 {
10765         int retval;
10766
10767         if (!argv[1])
10768                 return showvars(nullstr, 0, VUNSET);
10769
10770         INT_OFF;
10771         retval = options(/*cmdline:*/ 0);
10772         if (retval == 0) { /* if no parse error... */
10773                 optschanged();
10774                 if (*argptr != NULL) {
10775                         setparam(argptr);
10776                 }
10777         }
10778         INT_ON;
10779         return retval;
10780 }
10781
10782 #if ENABLE_ASH_RANDOM_SUPPORT
10783 static void FAST_FUNC
10784 change_random(const char *value)
10785 {
10786         uint32_t t;
10787
10788         if (value == NULL) {
10789                 /* "get", generate */
10790                 t = next_random(&random_gen);
10791                 /* set without recursion */
10792                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10793                 vrandom.flags &= ~VNOFUNC;
10794         } else {
10795                 /* set/reset */
10796                 t = strtoul(value, NULL, 10);
10797                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10798         }
10799 }
10800 #endif
10801
10802 #if ENABLE_ASH_GETOPTS
10803 static int
10804 getopts(char *optstr, char *optvar, char **optfirst)
10805 {
10806         char *p, *q;
10807         char c = '?';
10808         int done = 0;
10809         char sbuf[2];
10810         char **optnext;
10811         int ind = shellparam.optind;
10812         int off = shellparam.optoff;
10813
10814         sbuf[1] = '\0';
10815
10816         shellparam.optind = -1;
10817         optnext = optfirst + ind - 1;
10818
10819         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10820                 p = NULL;
10821         else
10822                 p = optnext[-1] + off;
10823         if (p == NULL || *p == '\0') {
10824                 /* Current word is done, advance */
10825                 p = *optnext;
10826                 if (p == NULL || *p != '-' || *++p == '\0') {
10827  atend:
10828                         p = NULL;
10829                         done = 1;
10830                         goto out;
10831                 }
10832                 optnext++;
10833                 if (LONE_DASH(p))        /* check for "--" */
10834                         goto atend;
10835         }
10836
10837         c = *p++;
10838         for (q = optstr; *q != c;) {
10839                 if (*q == '\0') {
10840                         if (optstr[0] == ':') {
10841                                 sbuf[0] = c;
10842                                 /*sbuf[1] = '\0'; - already is */
10843                                 setvar0("OPTARG", sbuf);
10844                         } else {
10845                                 fprintf(stderr, "Illegal option -%c\n", c);
10846                                 unsetvar("OPTARG");
10847                         }
10848                         c = '?';
10849                         goto out;
10850                 }
10851                 if (*++q == ':')
10852                         q++;
10853         }
10854
10855         if (*++q == ':') {
10856                 if (*p == '\0' && (p = *optnext) == NULL) {
10857                         if (optstr[0] == ':') {
10858                                 sbuf[0] = c;
10859                                 /*sbuf[1] = '\0'; - already is */
10860                                 setvar0("OPTARG", sbuf);
10861                                 c = ':';
10862                         } else {
10863                                 fprintf(stderr, "No arg for -%c option\n", c);
10864                                 unsetvar("OPTARG");
10865                                 c = '?';
10866                         }
10867                         goto out;
10868                 }
10869
10870                 if (p == *optnext)
10871                         optnext++;
10872                 setvar0("OPTARG", p);
10873                 p = NULL;
10874         } else
10875                 setvar0("OPTARG", nullstr);
10876  out:
10877         ind = optnext - optfirst + 1;
10878         setvar("OPTIND", itoa(ind), VNOFUNC);
10879         sbuf[0] = c;
10880         /*sbuf[1] = '\0'; - already is */
10881         setvar0(optvar, sbuf);
10882
10883         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10884         shellparam.optind = ind;
10885
10886         return done;
10887 }
10888
10889 /*
10890  * The getopts builtin.  Shellparam.optnext points to the next argument
10891  * to be processed.  Shellparam.optptr points to the next character to
10892  * be processed in the current argument.  If shellparam.optnext is NULL,
10893  * then it's the first time getopts has been called.
10894  */
10895 static int FAST_FUNC
10896 getoptscmd(int argc, char **argv)
10897 {
10898         char **optbase;
10899
10900         if (argc < 3)
10901                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10902         if (argc == 3) {
10903                 optbase = shellparam.p;
10904                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10905                         shellparam.optind = 1;
10906                         shellparam.optoff = -1;
10907                 }
10908         } else {
10909                 optbase = &argv[3];
10910                 if ((unsigned)shellparam.optind > argc - 2) {
10911                         shellparam.optind = 1;
10912                         shellparam.optoff = -1;
10913                 }
10914         }
10915
10916         return getopts(argv[1], argv[2], optbase);
10917 }
10918 #endif /* ASH_GETOPTS */
10919
10920
10921 /* ============ Shell parser */
10922
10923 struct heredoc {
10924         struct heredoc *next;   /* next here document in list */
10925         union node *here;       /* redirection node */
10926         char *eofmark;          /* string indicating end of input */
10927         smallint striptabs;     /* if set, strip leading tabs */
10928 };
10929
10930 static smallint tokpushback;           /* last token pushed back */
10931 static smallint quoteflag;             /* set if (part of) last token was quoted */
10932 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10933 static struct heredoc *heredoclist;    /* list of here documents to read */
10934 static char *wordtext;                 /* text of last word returned by readtoken */
10935 static struct nodelist *backquotelist;
10936 static union node *redirnode;
10937 static struct heredoc *heredoc;
10938
10939 static const char *
10940 tokname(char *buf, int tok)
10941 {
10942         if (tok < TSEMI)
10943                 return tokname_array[tok];
10944         sprintf(buf, "\"%s\"", tokname_array[tok]);
10945         return buf;
10946 }
10947
10948 /* raise_error_unexpected_syntax:
10949  * Called when an unexpected token is read during the parse.  The argument
10950  * is the token that is expected, or -1 if more than one type of token can
10951  * occur at this point.
10952  */
10953 static void raise_error_unexpected_syntax(int) NORETURN;
10954 static void
10955 raise_error_unexpected_syntax(int token)
10956 {
10957         char msg[64];
10958         char buf[16];
10959         int l;
10960
10961         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10962         if (token >= 0)
10963                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10964         raise_error_syntax(msg);
10965         /* NOTREACHED */
10966 }
10967
10968 /* parsing is heavily cross-recursive, need these forward decls */
10969 static union node *andor(void);
10970 static union node *pipeline(void);
10971 static union node *parse_command(void);
10972 static void parseheredoc(void);
10973 static int peektoken(void);
10974 static int readtoken(void);
10975
10976 static union node *
10977 list(int nlflag)
10978 {
10979         union node *n1, *n2, *n3;
10980         int tok;
10981
10982         n1 = NULL;
10983         for (;;) {
10984                 switch (peektoken()) {
10985                 case TNL:
10986                         if (!(nlflag & 1))
10987                                 break;
10988                         parseheredoc();
10989                         return n1;
10990
10991                 case TEOF:
10992                         if (!n1 && (nlflag & 1))
10993                                 n1 = NODE_EOF;
10994                         parseheredoc();
10995                         return n1;
10996                 }
10997
10998                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10999                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11000                         return n1;
11001                 nlflag |= 2;
11002
11003                 n2 = andor();
11004                 tok = readtoken();
11005                 if (tok == TBACKGND) {
11006                         if (n2->type == NPIPE) {
11007                                 n2->npipe.pipe_backgnd = 1;
11008                         } else {
11009                                 if (n2->type != NREDIR) {
11010                                         n3 = stzalloc(sizeof(struct nredir));
11011                                         n3->nredir.n = n2;
11012                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11013                                         n2 = n3;
11014                                 }
11015                                 n2->type = NBACKGND;
11016                         }
11017                 }
11018                 if (n1 == NULL) {
11019                         n1 = n2;
11020                 } else {
11021                         n3 = stzalloc(sizeof(struct nbinary));
11022                         n3->type = NSEMI;
11023                         n3->nbinary.ch1 = n1;
11024                         n3->nbinary.ch2 = n2;
11025                         n1 = n3;
11026                 }
11027                 switch (tok) {
11028                 case TNL:
11029                 case TEOF:
11030                         tokpushback = 1;
11031                         /* fall through */
11032                 case TBACKGND:
11033                 case TSEMI:
11034                         break;
11035                 default:
11036                         if ((nlflag & 1))
11037                                 raise_error_unexpected_syntax(-1);
11038                         tokpushback = 1;
11039                         return n1;
11040                 }
11041         }
11042 }
11043
11044 static union node *
11045 andor(void)
11046 {
11047         union node *n1, *n2, *n3;
11048         int t;
11049
11050         n1 = pipeline();
11051         for (;;) {
11052                 t = readtoken();
11053                 if (t == TAND) {
11054                         t = NAND;
11055                 } else if (t == TOR) {
11056                         t = NOR;
11057                 } else {
11058                         tokpushback = 1;
11059                         return n1;
11060                 }
11061                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11062                 n2 = pipeline();
11063                 n3 = stzalloc(sizeof(struct nbinary));
11064                 n3->type = t;
11065                 n3->nbinary.ch1 = n1;
11066                 n3->nbinary.ch2 = n2;
11067                 n1 = n3;
11068         }
11069 }
11070
11071 static union node *
11072 pipeline(void)
11073 {
11074         union node *n1, *n2, *pipenode;
11075         struct nodelist *lp, *prev;
11076         int negate;
11077
11078         negate = 0;
11079         TRACE(("pipeline: entered\n"));
11080         if (readtoken() == TNOT) {
11081                 negate = !negate;
11082                 checkkwd = CHKKWD | CHKALIAS;
11083         } else
11084                 tokpushback = 1;
11085         n1 = parse_command();
11086         if (readtoken() == TPIPE) {
11087                 pipenode = stzalloc(sizeof(struct npipe));
11088                 pipenode->type = NPIPE;
11089                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11090                 lp = stzalloc(sizeof(struct nodelist));
11091                 pipenode->npipe.cmdlist = lp;
11092                 lp->n = n1;
11093                 do {
11094                         prev = lp;
11095                         lp = stzalloc(sizeof(struct nodelist));
11096                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11097                         lp->n = parse_command();
11098                         prev->next = lp;
11099                 } while (readtoken() == TPIPE);
11100                 lp->next = NULL;
11101                 n1 = pipenode;
11102         }
11103         tokpushback = 1;
11104         if (negate) {
11105                 n2 = stzalloc(sizeof(struct nnot));
11106                 n2->type = NNOT;
11107                 n2->nnot.com = n1;
11108                 return n2;
11109         }
11110         return n1;
11111 }
11112
11113 static union node *
11114 makename(void)
11115 {
11116         union node *n;
11117
11118         n = stzalloc(sizeof(struct narg));
11119         n->type = NARG;
11120         /*n->narg.next = NULL; - stzalloc did it */
11121         n->narg.text = wordtext;
11122         n->narg.backquote = backquotelist;
11123         return n;
11124 }
11125
11126 static void
11127 fixredir(union node *n, const char *text, int err)
11128 {
11129         int fd;
11130
11131         TRACE(("Fix redir %s %d\n", text, err));
11132         if (!err)
11133                 n->ndup.vname = NULL;
11134
11135         fd = bb_strtou(text, NULL, 10);
11136         if (!errno && fd >= 0)
11137                 n->ndup.dupfd = fd;
11138         else if (LONE_DASH(text))
11139                 n->ndup.dupfd = -1;
11140         else {
11141                 if (err)
11142                         raise_error_syntax("bad fd number");
11143                 n->ndup.vname = makename();
11144         }
11145 }
11146
11147 static void
11148 parsefname(void)
11149 {
11150         union node *n = redirnode;
11151
11152         if (n->type == NHERE)
11153                 checkkwd = CHKEOFMARK;
11154         if (readtoken() != TWORD)
11155                 raise_error_unexpected_syntax(-1);
11156         if (n->type == NHERE) {
11157                 struct heredoc *here = heredoc;
11158                 struct heredoc *p;
11159
11160                 if (quoteflag == 0)
11161                         n->type = NXHERE;
11162                 TRACE(("Here document %d\n", n->type));
11163                 rmescapes(wordtext, 0);
11164                 here->eofmark = wordtext;
11165                 here->next = NULL;
11166                 if (heredoclist == NULL)
11167                         heredoclist = here;
11168                 else {
11169                         for (p = heredoclist; p->next; p = p->next)
11170                                 continue;
11171                         p->next = here;
11172                 }
11173         } else if (n->type == NTOFD || n->type == NFROMFD) {
11174                 fixredir(n, wordtext, 0);
11175         } else {
11176                 n->nfile.fname = makename();
11177         }
11178 }
11179
11180 static union node *
11181 simplecmd(void)
11182 {
11183         union node *args, **app;
11184         union node *n = NULL;
11185         union node *vars, **vpp;
11186         union node **rpp, *redir;
11187         int savecheckkwd;
11188 #if BASH_TEST2
11189         smallint double_brackets_flag = 0;
11190 #endif
11191         IF_BASH_FUNCTION(smallint function_flag = 0;)
11192
11193         args = NULL;
11194         app = &args;
11195         vars = NULL;
11196         vpp = &vars;
11197         redir = NULL;
11198         rpp = &redir;
11199
11200         savecheckkwd = CHKALIAS;
11201         for (;;) {
11202                 int t;
11203                 checkkwd = savecheckkwd;
11204                 t = readtoken();
11205                 switch (t) {
11206 #if BASH_FUNCTION
11207                 case TFUNCTION:
11208                         if (peektoken() != TWORD)
11209                                 raise_error_unexpected_syntax(TWORD);
11210                         function_flag = 1;
11211                         break;
11212 #endif
11213 #if BASH_TEST2
11214                 case TAND: /* "&&" */
11215                 case TOR: /* "||" */
11216                         if (!double_brackets_flag) {
11217                                 tokpushback = 1;
11218                                 goto out;
11219                         }
11220                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11221 #endif
11222                 case TWORD:
11223                         n = stzalloc(sizeof(struct narg));
11224                         n->type = NARG;
11225                         /*n->narg.next = NULL; - stzalloc did it */
11226                         n->narg.text = wordtext;
11227 #if BASH_TEST2
11228                         if (strcmp("[[", wordtext) == 0)
11229                                 double_brackets_flag = 1;
11230                         else if (strcmp("]]", wordtext) == 0)
11231                                 double_brackets_flag = 0;
11232 #endif
11233                         n->narg.backquote = backquotelist;
11234                         if (savecheckkwd && isassignment(wordtext)) {
11235                                 *vpp = n;
11236                                 vpp = &n->narg.next;
11237                         } else {
11238                                 *app = n;
11239                                 app = &n->narg.next;
11240                                 savecheckkwd = 0;
11241                         }
11242 #if BASH_FUNCTION
11243                         if (function_flag) {
11244                                 checkkwd = CHKNL | CHKKWD;
11245                                 switch (peektoken()) {
11246                                 case TBEGIN:
11247                                 case TIF:
11248                                 case TCASE:
11249                                 case TUNTIL:
11250                                 case TWHILE:
11251                                 case TFOR:
11252                                         goto do_func;
11253                                 case TLP:
11254                                         function_flag = 0;
11255                                         break;
11256                                 case TWORD:
11257                                         if (strcmp("[[", wordtext) == 0)
11258                                                 goto do_func;
11259                                         /* fall through */
11260                                 default:
11261                                         raise_error_unexpected_syntax(-1);
11262                                 }
11263                         }
11264 #endif
11265                         break;
11266                 case TREDIR:
11267                         *rpp = n = redirnode;
11268                         rpp = &n->nfile.next;
11269                         parsefname();   /* read name of redirection file */
11270                         break;
11271                 case TLP:
11272  IF_BASH_FUNCTION(do_func:)
11273                         if (args && app == &args->narg.next
11274                          && !vars && !redir
11275                         ) {
11276                                 struct builtincmd *bcmd;
11277                                 const char *name;
11278
11279                                 /* We have a function */
11280                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11281                                         raise_error_unexpected_syntax(TRP);
11282                                 name = n->narg.text;
11283                                 if (!goodname(name)
11284                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11285                                 ) {
11286                                         raise_error_syntax("bad function name");
11287                                 }
11288                                 n->type = NDEFUN;
11289                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11290                                 n->narg.next = parse_command();
11291                                 return n;
11292                         }
11293                         IF_BASH_FUNCTION(function_flag = 0;)
11294                         /* fall through */
11295                 default:
11296                         tokpushback = 1;
11297                         goto out;
11298                 }
11299         }
11300  out:
11301         *app = NULL;
11302         *vpp = NULL;
11303         *rpp = NULL;
11304         n = stzalloc(sizeof(struct ncmd));
11305         n->type = NCMD;
11306         n->ncmd.args = args;
11307         n->ncmd.assign = vars;
11308         n->ncmd.redirect = redir;
11309         return n;
11310 }
11311
11312 static union node *
11313 parse_command(void)
11314 {
11315         union node *n1, *n2;
11316         union node *ap, **app;
11317         union node *cp, **cpp;
11318         union node *redir, **rpp;
11319         union node **rpp2;
11320         int t;
11321
11322         redir = NULL;
11323         rpp2 = &redir;
11324
11325         switch (readtoken()) {
11326         default:
11327                 raise_error_unexpected_syntax(-1);
11328                 /* NOTREACHED */
11329         case TIF:
11330                 n1 = stzalloc(sizeof(struct nif));
11331                 n1->type = NIF;
11332                 n1->nif.test = list(0);
11333                 if (readtoken() != TTHEN)
11334                         raise_error_unexpected_syntax(TTHEN);
11335                 n1->nif.ifpart = list(0);
11336                 n2 = n1;
11337                 while (readtoken() == TELIF) {
11338                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11339                         n2 = n2->nif.elsepart;
11340                         n2->type = NIF;
11341                         n2->nif.test = list(0);
11342                         if (readtoken() != TTHEN)
11343                                 raise_error_unexpected_syntax(TTHEN);
11344                         n2->nif.ifpart = list(0);
11345                 }
11346                 if (lasttoken == TELSE)
11347                         n2->nif.elsepart = list(0);
11348                 else {
11349                         n2->nif.elsepart = NULL;
11350                         tokpushback = 1;
11351                 }
11352                 t = TFI;
11353                 break;
11354         case TWHILE:
11355         case TUNTIL: {
11356                 int got;
11357                 n1 = stzalloc(sizeof(struct nbinary));
11358                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11359                 n1->nbinary.ch1 = list(0);
11360                 got = readtoken();
11361                 if (got != TDO) {
11362                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11363                                         got == TWORD ? wordtext : ""));
11364                         raise_error_unexpected_syntax(TDO);
11365                 }
11366                 n1->nbinary.ch2 = list(0);
11367                 t = TDONE;
11368                 break;
11369         }
11370         case TFOR:
11371                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11372                         raise_error_syntax("bad for loop variable");
11373                 n1 = stzalloc(sizeof(struct nfor));
11374                 n1->type = NFOR;
11375                 n1->nfor.var = wordtext;
11376                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11377                 if (readtoken() == TIN) {
11378                         app = &ap;
11379                         while (readtoken() == TWORD) {
11380                                 n2 = stzalloc(sizeof(struct narg));
11381                                 n2->type = NARG;
11382                                 /*n2->narg.next = NULL; - stzalloc did it */
11383                                 n2->narg.text = wordtext;
11384                                 n2->narg.backquote = backquotelist;
11385                                 *app = n2;
11386                                 app = &n2->narg.next;
11387                         }
11388                         *app = NULL;
11389                         n1->nfor.args = ap;
11390                         if (lasttoken != TNL && lasttoken != TSEMI)
11391                                 raise_error_unexpected_syntax(-1);
11392                 } else {
11393                         n2 = stzalloc(sizeof(struct narg));
11394                         n2->type = NARG;
11395                         /*n2->narg.next = NULL; - stzalloc did it */
11396                         n2->narg.text = (char *)dolatstr;
11397                         /*n2->narg.backquote = NULL;*/
11398                         n1->nfor.args = n2;
11399                         /*
11400                          * Newline or semicolon here is optional (but note
11401                          * that the original Bourne shell only allowed NL).
11402                          */
11403                         if (lasttoken != TSEMI)
11404                                 tokpushback = 1;
11405                 }
11406                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11407                 if (readtoken() != TDO)
11408                         raise_error_unexpected_syntax(TDO);
11409                 n1->nfor.body = list(0);
11410                 t = TDONE;
11411                 break;
11412         case TCASE:
11413                 n1 = stzalloc(sizeof(struct ncase));
11414                 n1->type = NCASE;
11415                 if (readtoken() != TWORD)
11416                         raise_error_unexpected_syntax(TWORD);
11417                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11418                 n2->type = NARG;
11419                 /*n2->narg.next = NULL; - stzalloc did it */
11420                 n2->narg.text = wordtext;
11421                 n2->narg.backquote = backquotelist;
11422                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11423                 if (readtoken() != TIN)
11424                         raise_error_unexpected_syntax(TIN);
11425                 cpp = &n1->ncase.cases;
11426  next_case:
11427                 checkkwd = CHKNL | CHKKWD;
11428                 t = readtoken();
11429                 while (t != TESAC) {
11430                         if (lasttoken == TLP)
11431                                 readtoken();
11432                         *cpp = cp = stzalloc(sizeof(struct nclist));
11433                         cp->type = NCLIST;
11434                         app = &cp->nclist.pattern;
11435                         for (;;) {
11436                                 *app = ap = stzalloc(sizeof(struct narg));
11437                                 ap->type = NARG;
11438                                 /*ap->narg.next = NULL; - stzalloc did it */
11439                                 ap->narg.text = wordtext;
11440                                 ap->narg.backquote = backquotelist;
11441                                 if (readtoken() != TPIPE)
11442                                         break;
11443                                 app = &ap->narg.next;
11444                                 readtoken();
11445                         }
11446                         //ap->narg.next = NULL;
11447                         if (lasttoken != TRP)
11448                                 raise_error_unexpected_syntax(TRP);
11449                         cp->nclist.body = list(2);
11450
11451                         cpp = &cp->nclist.next;
11452
11453                         checkkwd = CHKNL | CHKKWD;
11454                         t = readtoken();
11455                         if (t != TESAC) {
11456                                 if (t != TENDCASE)
11457                                         raise_error_unexpected_syntax(TENDCASE);
11458                                 goto next_case;
11459                         }
11460                 }
11461                 *cpp = NULL;
11462                 goto redir;
11463         case TLP:
11464                 n1 = stzalloc(sizeof(struct nredir));
11465                 n1->type = NSUBSHELL;
11466                 n1->nredir.n = list(0);
11467                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11468                 t = TRP;
11469                 break;
11470         case TBEGIN:
11471                 n1 = list(0);
11472                 t = TEND;
11473                 break;
11474         IF_BASH_FUNCTION(case TFUNCTION:)
11475         case TWORD:
11476         case TREDIR:
11477                 tokpushback = 1;
11478                 return simplecmd();
11479         }
11480
11481         if (readtoken() != t)
11482                 raise_error_unexpected_syntax(t);
11483
11484  redir:
11485         /* Now check for redirection which may follow command */
11486         checkkwd = CHKKWD | CHKALIAS;
11487         rpp = rpp2;
11488         while (readtoken() == TREDIR) {
11489                 *rpp = n2 = redirnode;
11490                 rpp = &n2->nfile.next;
11491                 parsefname();
11492         }
11493         tokpushback = 1;
11494         *rpp = NULL;
11495         if (redir) {
11496                 if (n1->type != NSUBSHELL) {
11497                         n2 = stzalloc(sizeof(struct nredir));
11498                         n2->type = NREDIR;
11499                         n2->nredir.n = n1;
11500                         n1 = n2;
11501                 }
11502                 n1->nredir.redirect = redir;
11503         }
11504         return n1;
11505 }
11506
11507 #if BASH_DOLLAR_SQUOTE
11508 static int
11509 decode_dollar_squote(void)
11510 {
11511         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11512         int c, cnt;
11513         char *p;
11514         char buf[4];
11515
11516         c = pgetc();
11517         p = strchr(C_escapes, c);
11518         if (p) {
11519                 buf[0] = c;
11520                 p = buf;
11521                 cnt = 3;
11522                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11523                         do {
11524                                 c = pgetc();
11525                                 *++p = c;
11526                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11527                         pungetc();
11528                 } else if (c == 'x') { /* \xHH */
11529                         do {
11530                                 c = pgetc();
11531                                 *++p = c;
11532                         } while (isxdigit(c) && --cnt);
11533                         pungetc();
11534                         if (cnt == 3) { /* \x but next char is "bad" */
11535                                 c = 'x';
11536                                 goto unrecognized;
11537                         }
11538                 } else { /* simple seq like \\ or \t */
11539                         p++;
11540                 }
11541                 *p = '\0';
11542                 p = buf;
11543                 c = bb_process_escape_sequence((void*)&p);
11544         } else { /* unrecognized "\z": print both chars unless ' or " */
11545                 if (c != '\'' && c != '"') {
11546  unrecognized:
11547                         c |= 0x100; /* "please encode \, then me" */
11548                 }
11549         }
11550         return c;
11551 }
11552 #endif
11553
11554 /* Used by expandstr to get here-doc like behaviour. */
11555 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11556
11557 static ALWAYS_INLINE int
11558 realeofmark(const char *eofmark)
11559 {
11560         return eofmark && eofmark != FAKEEOFMARK;
11561 }
11562
11563 /*
11564  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11565  * is not NULL, read a here document.  In the latter case, eofmark is the
11566  * word which marks the end of the document and striptabs is true if
11567  * leading tabs should be stripped from the document.  The argument c
11568  * is the first character of the input token or document.
11569  *
11570  * Because C does not have internal subroutines, I have simulated them
11571  * using goto's to implement the subroutine linkage.  The following macros
11572  * will run code that appears at the end of readtoken1.
11573  */
11574 #define CHECKEND()      {goto checkend; checkend_return:;}
11575 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11576 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11577 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11578 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11579 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11580 static int
11581 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11582 {
11583         /* NB: syntax parameter fits into smallint */
11584         /* c parameter is an unsigned char or PEOF or PEOA */
11585         char *out;
11586         size_t len;
11587         struct nodelist *bqlist;
11588         smallint quotef;
11589         smallint dblquote;
11590         smallint oldstyle;
11591         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11592         smallint pssyntax;   /* we are expanding a prompt string */
11593         int varnest;         /* levels of variables expansion */
11594         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11595         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11596         int dqvarnest;       /* levels of variables expansion within double quotes */
11597
11598         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11599
11600         startlinno = g_parsefile->linno;
11601         bqlist = NULL;
11602         quotef = 0;
11603         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11604 #if ENABLE_ASH_EXPAND_PRMT
11605         pssyntax = (syntax == PSSYNTAX);
11606         if (pssyntax)
11607                 syntax = DQSYNTAX;
11608 #else
11609         pssyntax = 0; /* constant */
11610 #endif
11611         dblquote = (syntax == DQSYNTAX);
11612         varnest = 0;
11613         IF_FEATURE_SH_MATH(arinest = 0;)
11614         IF_FEATURE_SH_MATH(parenlevel = 0;)
11615         dqvarnest = 0;
11616
11617         STARTSTACKSTR(out);
11618  loop:
11619         /* For each line, until end of word */
11620         CHECKEND();     /* set c to PEOF if at end of here document */
11621         for (;;) {      /* until end of line or end of word */
11622                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11623                 switch (SIT(c, syntax)) {
11624                 case CNL:       /* '\n' */
11625                         if (syntax == BASESYNTAX)
11626                                 goto endword;   /* exit outer loop */
11627                         USTPUTC(c, out);
11628                         nlprompt();
11629                         c = pgetc();
11630                         goto loop;              /* continue outer loop */
11631                 case CWORD:
11632                         USTPUTC(c, out);
11633                         break;
11634                 case CCTL:
11635 #if BASH_DOLLAR_SQUOTE
11636                         if (c == '\\' && bash_dollar_squote) {
11637                                 c = decode_dollar_squote();
11638                                 if (c == '\0') {
11639                                         /* skip $'\000', $'\x00' (like bash) */
11640                                         break;
11641                                 }
11642                                 if (c & 0x100) {
11643                                         /* Unknown escape. Encode as '\z' */
11644                                         c = (unsigned char)c;
11645                                         if (eofmark == NULL || dblquote)
11646                                                 USTPUTC(CTLESC, out);
11647                                         USTPUTC('\\', out);
11648                                 }
11649                         }
11650 #endif
11651                         if (eofmark == NULL || dblquote)
11652                                 USTPUTC(CTLESC, out);
11653                         USTPUTC(c, out);
11654                         break;
11655                 case CBACK:     /* backslash */
11656                         c = pgetc_without_PEOA();
11657                         if (c == PEOF) {
11658                                 USTPUTC(CTLESC, out);
11659                                 USTPUTC('\\', out);
11660                                 pungetc();
11661                         } else if (c == '\n') {
11662                                 nlprompt();
11663                         } else {
11664                                 if (pssyntax && c == '$') {
11665                                         USTPUTC(CTLESC, out);
11666                                         USTPUTC('\\', out);
11667                                 }
11668                                 /* Backslash is retained if we are in "str" and next char isn't special */
11669                                 if (dblquote
11670                                  && c != '\\'
11671                                  && c != '`'
11672                                  && c != '$'
11673                                  && (c != '"' || eofmark != NULL)
11674                                 ) {
11675                                         USTPUTC('\\', out);
11676                                 }
11677                                 USTPUTC(CTLESC, out);
11678                                 USTPUTC(c, out);
11679                                 quotef = 1;
11680                         }
11681                         break;
11682                 case CSQUOTE:
11683                         syntax = SQSYNTAX;
11684  quotemark:
11685                         if (eofmark == NULL) {
11686                                 USTPUTC(CTLQUOTEMARK, out);
11687                         }
11688                         break;
11689                 case CDQUOTE:
11690                         syntax = DQSYNTAX;
11691                         dblquote = 1;
11692                         goto quotemark;
11693                 case CENDQUOTE:
11694                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11695                         if (eofmark != NULL && varnest == 0) {
11696                                 USTPUTC(c, out);
11697                         } else {
11698                                 if (dqvarnest == 0) {
11699                                         syntax = BASESYNTAX;
11700                                         dblquote = 0;
11701                                 }
11702                                 quotef = 1;
11703                                 goto quotemark;
11704                         }
11705                         break;
11706                 case CVAR:      /* '$' */
11707                         PARSESUB();             /* parse substitution */
11708                         break;
11709                 case CENDVAR:   /* '}' */
11710                         if (varnest > 0) {
11711                                 varnest--;
11712                                 if (dqvarnest > 0) {
11713                                         dqvarnest--;
11714                                 }
11715                                 c = CTLENDVAR;
11716                         }
11717                         USTPUTC(c, out);
11718                         break;
11719 #if ENABLE_FEATURE_SH_MATH
11720                 case CLP:       /* '(' in arithmetic */
11721                         parenlevel++;
11722                         USTPUTC(c, out);
11723                         break;
11724                 case CRP:       /* ')' in arithmetic */
11725                         if (parenlevel > 0) {
11726                                 parenlevel--;
11727                         } else {
11728                                 if (pgetc_eatbnl() == ')') {
11729                                         c = CTLENDARI;
11730                                         if (--arinest == 0) {
11731                                                 syntax = prevsyntax;
11732                                         }
11733                                 } else {
11734                                         /*
11735                                          * unbalanced parens
11736                                          * (don't 2nd guess - no error)
11737                                          */
11738                                         pungetc();
11739                                 }
11740                         }
11741                         USTPUTC(c, out);
11742                         break;
11743 #endif
11744                 case CBQUOTE:   /* '`' */
11745                         PARSEBACKQOLD();
11746                         break;
11747                 case CENDFILE:
11748                         goto endword;           /* exit outer loop */
11749                 case CIGN:
11750                         break;
11751                 default:
11752                         if (varnest == 0) {
11753 #if BASH_REDIR_OUTPUT
11754                                 if (c == '&') {
11755 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11756                                         if (pgetc() == '>')
11757                                                 c = 0x100 + '>'; /* flag &> */
11758                                         pungetc();
11759                                 }
11760 #endif
11761                                 goto endword;   /* exit outer loop */
11762                         }
11763                         IF_ASH_ALIAS(if (c != PEOA))
11764                                 USTPUTC(c, out);
11765                 }
11766                 c = pgetc();
11767         } /* for (;;) */
11768  endword:
11769
11770 #if ENABLE_FEATURE_SH_MATH
11771         if (syntax == ARISYNTAX)
11772                 raise_error_syntax("missing '))'");
11773 #endif
11774         if (syntax != BASESYNTAX && eofmark == NULL)
11775                 raise_error_syntax("unterminated quoted string");
11776         if (varnest != 0) {
11777                 startlinno = g_parsefile->linno;
11778                 /* { */
11779                 raise_error_syntax("missing '}'");
11780         }
11781         USTPUTC('\0', out);
11782         len = out - (char *)stackblock();
11783         out = stackblock();
11784         if (eofmark == NULL) {
11785                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11786                  && quotef == 0
11787                 ) {
11788                         if (isdigit_str9(out)) {
11789                                 PARSEREDIR(); /* passed as params: out, c */
11790                                 lasttoken = TREDIR;
11791                                 return lasttoken;
11792                         }
11793                         /* else: non-number X seen, interpret it
11794                          * as "NNNX>file" = "NNNX >file" */
11795                 }
11796                 pungetc();
11797         }
11798         quoteflag = quotef;
11799         backquotelist = bqlist;
11800         grabstackblock(len);
11801         wordtext = out;
11802         lasttoken = TWORD;
11803         return lasttoken;
11804 /* end of readtoken routine */
11805
11806 /*
11807  * Check to see whether we are at the end of the here document.  When this
11808  * is called, c is set to the first character of the next input line.  If
11809  * we are at the end of the here document, this routine sets the c to PEOF.
11810  */
11811 checkend: {
11812         if (realeofmark(eofmark)) {
11813                 int markloc;
11814                 char *p;
11815
11816 #if ENABLE_ASH_ALIAS
11817                 if (c == PEOA)
11818                         c = pgetc_without_PEOA();
11819 #endif
11820                 if (striptabs) {
11821                         while (c == '\t') {
11822                                 c = pgetc_without_PEOA();
11823                         }
11824                 }
11825
11826                 markloc = out - (char *)stackblock();
11827                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11828                         if (c != *p)
11829                                 goto more_heredoc;
11830
11831                         c = pgetc_without_PEOA();
11832                 }
11833
11834                 if (c == '\n' || c == PEOF) {
11835                         c = PEOF;
11836                         g_parsefile->linno++;
11837                         needprompt = doprompt;
11838                 } else {
11839                         int len_here;
11840
11841  more_heredoc:
11842                         p = (char *)stackblock() + markloc + 1;
11843                         len_here = out - p;
11844
11845                         if (len_here) {
11846                                 len_here -= (c >= PEOF);
11847                                 c = p[-1];
11848
11849                                 if (len_here) {
11850                                         char *str;
11851
11852                                         str = alloca(len_here + 1);
11853                                         *(char *)mempcpy(str, p, len_here) = '\0';
11854
11855                                         pushstring(str, NULL);
11856                                 }
11857                         }
11858                 }
11859
11860                 STADJUST((char *)stackblock() + markloc - out, out);
11861         }
11862         goto checkend_return;
11863 }
11864
11865 /*
11866  * Parse a redirection operator.  The variable "out" points to a string
11867  * specifying the fd to be redirected.  The variable "c" contains the
11868  * first character of the redirection operator.
11869  */
11870 parseredir: {
11871         /* out is already checked to be a valid number or "" */
11872         int fd = (*out == '\0' ? -1 : atoi(out));
11873         union node *np;
11874
11875         np = stzalloc(sizeof(struct nfile));
11876         if (c == '>') {
11877                 np->nfile.fd = 1;
11878                 c = pgetc();
11879                 if (c == '>')
11880                         np->type = NAPPEND;
11881                 else if (c == '|')
11882                         np->type = NCLOBBER;
11883                 else if (c == '&')
11884                         np->type = NTOFD;
11885                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11886                 else {
11887                         np->type = NTO;
11888                         pungetc();
11889                 }
11890         }
11891 #if BASH_REDIR_OUTPUT
11892         else if (c == 0x100 + '>') { /* this flags &> redirection */
11893                 np->nfile.fd = 1;
11894                 pgetc(); /* this is '>', no need to check */
11895                 np->type = NTO2;
11896         }
11897 #endif
11898         else { /* c == '<' */
11899                 /*np->nfile.fd = 0; - stzalloc did it */
11900                 c = pgetc();
11901                 switch (c) {
11902                 case '<':
11903                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11904                                 np = stzalloc(sizeof(struct nhere));
11905                                 /*np->nfile.fd = 0; - stzalloc did it */
11906                         }
11907                         np->type = NHERE;
11908                         heredoc = stzalloc(sizeof(struct heredoc));
11909                         heredoc->here = np;
11910                         c = pgetc();
11911                         if (c == '-') {
11912                                 heredoc->striptabs = 1;
11913                         } else {
11914                                 /*heredoc->striptabs = 0; - stzalloc did it */
11915                                 pungetc();
11916                         }
11917                         break;
11918
11919                 case '&':
11920                         np->type = NFROMFD;
11921                         break;
11922
11923                 case '>':
11924                         np->type = NFROMTO;
11925                         break;
11926
11927                 default:
11928                         np->type = NFROM;
11929                         pungetc();
11930                         break;
11931                 }
11932         }
11933         if (fd >= 0)
11934                 np->nfile.fd = fd;
11935         redirnode = np;
11936         goto parseredir_return;
11937 }
11938
11939 /*
11940  * Parse a substitution.  At this point, we have read the dollar sign
11941  * and nothing else.
11942  */
11943
11944 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11945  * (assuming ascii char codes, as the original implementation did) */
11946 #define is_special(c) \
11947         (((unsigned)(c) - 33 < 32) \
11948                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11949 parsesub: {
11950         unsigned char subtype;
11951         int typeloc;
11952
11953         c = pgetc_eatbnl();
11954         if ((checkkwd & CHKEOFMARK)
11955          || c > 255 /* PEOA or PEOF */
11956          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11957         ) {
11958 #if BASH_DOLLAR_SQUOTE
11959                 if (syntax != DQSYNTAX && c == '\'')
11960                         bash_dollar_squote = 1;
11961                 else
11962 #endif
11963                         USTPUTC('$', out);
11964                 pungetc();
11965         } else if (c == '(') {
11966                 /* $(command) or $((arith)) */
11967                 if (pgetc_eatbnl() == '(') {
11968 #if ENABLE_FEATURE_SH_MATH
11969                         PARSEARITH();
11970 #else
11971                         raise_error_syntax("support for $((arith)) is disabled");
11972 #endif
11973                 } else {
11974                         pungetc();
11975                         PARSEBACKQNEW();
11976                 }
11977         } else {
11978                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11979                 USTPUTC(CTLVAR, out);
11980                 typeloc = out - (char *)stackblock();
11981                 STADJUST(1, out);
11982                 subtype = VSNORMAL;
11983                 if (c == '{') {
11984                         c = pgetc_eatbnl();
11985                         subtype = 0;
11986                 }
11987  varname:
11988                 if (is_name(c)) {
11989                         /* $[{[#]]NAME[}] */
11990                         do {
11991                                 STPUTC(c, out);
11992                                 c = pgetc_eatbnl();
11993                         } while (is_in_name(c));
11994                 } else if (isdigit(c)) {
11995                         /* $[{[#]]NUM[}] */
11996                         do {
11997                                 STPUTC(c, out);
11998                                 c = pgetc_eatbnl();
11999                         } while (isdigit(c));
12000                 } else if (is_special(c)) {
12001                         /* $[{[#]]<specialchar>[}] */
12002                         int cc = c;
12003
12004                         c = pgetc_eatbnl();
12005                         if (!subtype && cc == '#') {
12006                                 subtype = VSLENGTH;
12007                                 if (c == '_' || isalnum(c))
12008                                         goto varname;
12009                                 cc = c;
12010                                 c = pgetc_eatbnl();
12011                                 if (cc == '}' || c != '}') {
12012                                         pungetc();
12013                                         subtype = 0;
12014                                         c = cc;
12015                                         cc = '#';
12016                                 }
12017                         }
12018                         USTPUTC(cc, out);
12019                 } else {
12020                         goto badsub;
12021                 }
12022                 if (c != '}' && subtype == VSLENGTH) {
12023                         /* ${#VAR didn't end with } */
12024                         goto badsub;
12025                 }
12026
12027                 if (subtype == 0) {
12028                         static const char types[] ALIGN1 = "}-+?=";
12029                         /* ${VAR...} but not $VAR or ${#VAR} */
12030                         /* c == first char after VAR */
12031                         switch (c) {
12032                         case ':':
12033                                 c = pgetc_eatbnl();
12034 #if BASH_SUBSTR
12035                                 /* This check is only needed to not misinterpret
12036                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12037                                  * constructs.
12038                                  */
12039                                 if (!strchr(types, c)) {
12040                                         subtype = VSSUBSTR;
12041                                         pungetc();
12042                                         break; /* "goto badsub" is bigger (!) */
12043                                 }
12044 #endif
12045                                 subtype = VSNUL;
12046                                 /*FALLTHROUGH*/
12047                         default: {
12048                                 const char *p = strchr(types, c);
12049                                 if (p == NULL)
12050                                         break;
12051                                 subtype |= p - types + VSNORMAL;
12052                                 break;
12053                         }
12054                         case '%':
12055                         case '#': {
12056                                 int cc = c;
12057                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12058                                 c = pgetc_eatbnl();
12059                                 if (c != cc)
12060                                         goto badsub;
12061                                 subtype++;
12062                                 break;
12063                         }
12064 #if BASH_PATTERN_SUBST
12065                         case '/':
12066                                 /* ${v/[/]pattern/repl} */
12067 //TODO: encode pattern and repl separately.
12068 // Currently ${v/$var_with_slash/repl} is horribly broken
12069                                 subtype = VSREPLACE;
12070                                 c = pgetc_eatbnl();
12071                                 if (c != '/')
12072                                         goto badsub;
12073                                 subtype++; /* VSREPLACEALL */
12074                                 break;
12075 #endif
12076                         }
12077                 } else {
12078  badsub:
12079                         pungetc();
12080                 }
12081                 ((unsigned char *)stackblock())[typeloc] = subtype;
12082                 if (subtype != VSNORMAL) {
12083                         varnest++;
12084                         if (dblquote)
12085                                 dqvarnest++;
12086                 }
12087                 STPUTC('=', out);
12088         }
12089         goto parsesub_return;
12090 }
12091
12092 /*
12093  * Called to parse command substitutions.  Newstyle is set if the command
12094  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12095  * list of commands (passed by reference), and savelen is the number of
12096  * characters on the top of the stack which must be preserved.
12097  */
12098 parsebackq: {
12099         struct nodelist **nlpp;
12100         union node *n;
12101         char *str;
12102         size_t savelen;
12103         smallint saveprompt = 0;
12104
12105         str = NULL;
12106         savelen = out - (char *)stackblock();
12107         if (savelen > 0) {
12108                 /*
12109                  * FIXME: this can allocate very large block on stack and SEGV.
12110                  * Example:
12111                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12112                  * allocates 100kb for every command subst. With about
12113                  * a hundred command substitutions stack overflows.
12114                  * With larger prepended string, SEGV happens sooner.
12115                  */
12116                 str = alloca(savelen);
12117                 memcpy(str, stackblock(), savelen);
12118         }
12119
12120         if (oldstyle) {
12121                 /* We must read until the closing backquote, giving special
12122                  * treatment to some slashes, and then push the string and
12123                  * reread it as input, interpreting it normally.
12124                  */
12125                 char *pout;
12126                 size_t psavelen;
12127                 char *pstr;
12128
12129                 STARTSTACKSTR(pout);
12130                 for (;;) {
12131                         int pc;
12132
12133                         setprompt_if(needprompt, 2);
12134                         pc = pgetc();
12135                         switch (pc) {
12136                         case '`':
12137                                 goto done;
12138
12139                         case '\\':
12140                                 pc = pgetc();
12141                                 if (pc == '\n') {
12142                                         nlprompt();
12143                                         /*
12144                                          * If eating a newline, avoid putting
12145                                          * the newline into the new character
12146                                          * stream (via the STPUTC after the
12147                                          * switch).
12148                                          */
12149                                         continue;
12150                                 }
12151                                 if (pc != '\\' && pc != '`' && pc != '$'
12152                                  && (!dblquote || pc != '"')
12153                                 ) {
12154                                         STPUTC('\\', pout);
12155                                 }
12156                                 if (pc <= 255 /* not PEOA or PEOF */) {
12157                                         break;
12158                                 }
12159                                 /* fall through */
12160
12161                         case PEOF:
12162                         IF_ASH_ALIAS(case PEOA:)
12163                                 startlinno = g_parsefile->linno;
12164                                 raise_error_syntax("EOF in backquote substitution");
12165
12166                         case '\n':
12167                                 nlnoprompt();
12168                                 break;
12169
12170                         default:
12171                                 break;
12172                         }
12173                         STPUTC(pc, pout);
12174                 }
12175  done:
12176                 STPUTC('\0', pout);
12177                 psavelen = pout - (char *)stackblock();
12178                 if (psavelen > 0) {
12179                         pstr = grabstackstr(pout);
12180                         setinputstring(pstr);
12181                 }
12182         }
12183         nlpp = &bqlist;
12184         while (*nlpp)
12185                 nlpp = &(*nlpp)->next;
12186         *nlpp = stzalloc(sizeof(**nlpp));
12187         /* (*nlpp)->next = NULL; - stzalloc did it */
12188
12189         if (oldstyle) {
12190                 saveprompt = doprompt;
12191                 doprompt = 0;
12192         }
12193
12194         n = list(2);
12195
12196         if (oldstyle)
12197                 doprompt = saveprompt;
12198         else if (readtoken() != TRP)
12199                 raise_error_unexpected_syntax(TRP);
12200
12201         (*nlpp)->n = n;
12202         if (oldstyle) {
12203                 /*
12204                  * Start reading from old file again, ignoring any pushed back
12205                  * tokens left from the backquote parsing
12206                  */
12207                 popfile();
12208                 tokpushback = 0;
12209         }
12210         while (stackblocksize() <= savelen)
12211                 growstackblock();
12212         STARTSTACKSTR(out);
12213         if (str) {
12214                 memcpy(out, str, savelen);
12215                 STADJUST(savelen, out);
12216         }
12217         USTPUTC(CTLBACKQ, out);
12218         if (oldstyle)
12219                 goto parsebackq_oldreturn;
12220         goto parsebackq_newreturn;
12221 }
12222
12223 #if ENABLE_FEATURE_SH_MATH
12224 /*
12225  * Parse an arithmetic expansion (indicate start of one and set state)
12226  */
12227 parsearith: {
12228         if (++arinest == 1) {
12229                 prevsyntax = syntax;
12230                 syntax = ARISYNTAX;
12231         }
12232         USTPUTC(CTLARI, out);
12233         goto parsearith_return;
12234 }
12235 #endif
12236 } /* end of readtoken */
12237
12238 /*
12239  * Read the next input token.
12240  * If the token is a word, we set backquotelist to the list of cmds in
12241  *      backquotes.  We set quoteflag to true if any part of the word was
12242  *      quoted.
12243  * If the token is TREDIR, then we set redirnode to a structure containing
12244  *      the redirection.
12245  * In all cases, the variable startlinno is set to the number of the line
12246  *      on which the token starts.
12247  *
12248  * [Change comment:  here documents and internal procedures]
12249  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12250  *  word parsing code into a separate routine.  In this case, readtoken
12251  *  doesn't need to have any internal procedures, but parseword does.
12252  *  We could also make parseoperator in essence the main routine, and
12253  *  have parseword (readtoken1?) handle both words and redirection.]
12254  */
12255 #define NEW_xxreadtoken
12256 #ifdef NEW_xxreadtoken
12257 /* singles must be first! */
12258 static const char xxreadtoken_chars[7] ALIGN1 = {
12259         '\n', '(', ')', /* singles */
12260         '&', '|', ';',  /* doubles */
12261         0
12262 };
12263
12264 #define xxreadtoken_singles 3
12265 #define xxreadtoken_doubles 3
12266
12267 static const char xxreadtoken_tokens[] ALIGN1 = {
12268         TNL, TLP, TRP,          /* only single occurrence allowed */
12269         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12270         TEOF,                   /* corresponds to trailing nul */
12271         TAND, TOR, TENDCASE     /* if double occurrence */
12272 };
12273
12274 static int
12275 xxreadtoken(void)
12276 {
12277         int c;
12278
12279         if (tokpushback) {
12280                 tokpushback = 0;
12281                 return lasttoken;
12282         }
12283         setprompt_if(needprompt, 2);
12284         startlinno = g_parsefile->linno;
12285         for (;;) {                      /* until token or start of word found */
12286                 c = pgetc();
12287                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12288                         continue;
12289
12290                 if (c == '#') {
12291                         while ((c = pgetc()) != '\n' && c != PEOF)
12292                                 continue;
12293                         pungetc();
12294                 } else if (c == '\\') {
12295                         if (pgetc() != '\n') {
12296                                 pungetc();
12297                                 break; /* return readtoken1(...) */
12298                         }
12299                         nlprompt();
12300                 } else {
12301                         const char *p;
12302
12303                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12304                         if (c != PEOF) {
12305                                 if (c == '\n') {
12306                                         nlnoprompt();
12307                                 }
12308
12309                                 p = strchr(xxreadtoken_chars, c);
12310                                 if (p == NULL)
12311                                         break; /* return readtoken1(...) */
12312
12313                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12314                                         int cc = pgetc();
12315                                         if (cc == c) {    /* double occurrence? */
12316                                                 p += xxreadtoken_doubles + 1;
12317                                         } else {
12318                                                 pungetc();
12319 #if BASH_REDIR_OUTPUT
12320                                                 if (c == '&' && cc == '>') /* &> */
12321                                                         break; /* return readtoken1(...) */
12322 #endif
12323                                         }
12324                                 }
12325                         }
12326                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12327                         return lasttoken;
12328                 }
12329         } /* for (;;) */
12330
12331         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12332 }
12333 #else /* old xxreadtoken */
12334 #define RETURN(token)   return lasttoken = token
12335 static int
12336 xxreadtoken(void)
12337 {
12338         int c;
12339
12340         if (tokpushback) {
12341                 tokpushback = 0;
12342                 return lasttoken;
12343         }
12344         setprompt_if(needprompt, 2);
12345         startlinno = g_parsefile->linno;
12346         for (;;) {      /* until token or start of word found */
12347                 c = pgetc();
12348                 switch (c) {
12349                 case ' ': case '\t':
12350                 IF_ASH_ALIAS(case PEOA:)
12351                         continue;
12352                 case '#':
12353                         while ((c = pgetc()) != '\n' && c != PEOF)
12354                                 continue;
12355                         pungetc();
12356                         continue;
12357                 case '\\':
12358                         if (pgetc() == '\n') {
12359                                 nlprompt();
12360                                 continue;
12361                         }
12362                         pungetc();
12363                         goto breakloop;
12364                 case '\n':
12365                         nlnoprompt();
12366                         RETURN(TNL);
12367                 case PEOF:
12368                         RETURN(TEOF);
12369                 case '&':
12370                         if (pgetc() == '&')
12371                                 RETURN(TAND);
12372                         pungetc();
12373                         RETURN(TBACKGND);
12374                 case '|':
12375                         if (pgetc() == '|')
12376                                 RETURN(TOR);
12377                         pungetc();
12378                         RETURN(TPIPE);
12379                 case ';':
12380                         if (pgetc() == ';')
12381                                 RETURN(TENDCASE);
12382                         pungetc();
12383                         RETURN(TSEMI);
12384                 case '(':
12385                         RETURN(TLP);
12386                 case ')':
12387                         RETURN(TRP);
12388                 default:
12389                         goto breakloop;
12390                 }
12391         }
12392  breakloop:
12393         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12394 #undef RETURN
12395 }
12396 #endif /* old xxreadtoken */
12397
12398 static int
12399 readtoken(void)
12400 {
12401         int t;
12402         int kwd = checkkwd;
12403 #if DEBUG
12404         smallint alreadyseen = tokpushback;
12405 #endif
12406
12407 #if ENABLE_ASH_ALIAS
12408  top:
12409 #endif
12410
12411         t = xxreadtoken();
12412
12413         /*
12414          * eat newlines
12415          */
12416         if (kwd & CHKNL) {
12417                 while (t == TNL) {
12418                         parseheredoc();
12419                         t = xxreadtoken();
12420                 }
12421         }
12422
12423         if (t != TWORD || quoteflag) {
12424                 goto out;
12425         }
12426
12427         /*
12428          * check for keywords
12429          */
12430         if (kwd & CHKKWD) {
12431                 const char *const *pp;
12432
12433                 pp = findkwd(wordtext);
12434                 if (pp) {
12435                         lasttoken = t = pp - tokname_array;
12436                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12437                         goto out;
12438                 }
12439         }
12440
12441         if (checkkwd & CHKALIAS) {
12442 #if ENABLE_ASH_ALIAS
12443                 struct alias *ap;
12444                 ap = lookupalias(wordtext, 1);
12445                 if (ap != NULL) {
12446                         if (*ap->val) {
12447                                 pushstring(ap->val, ap);
12448                         }
12449                         goto top;
12450                 }
12451 #endif
12452         }
12453  out:
12454         checkkwd = 0;
12455 #if DEBUG
12456         if (!alreadyseen)
12457                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12458         else
12459                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12460 #endif
12461         return t;
12462 }
12463
12464 static int
12465 peektoken(void)
12466 {
12467         int t;
12468
12469         t = readtoken();
12470         tokpushback = 1;
12471         return t;
12472 }
12473
12474 /*
12475  * Read and parse a command.  Returns NODE_EOF on end of file.
12476  * (NULL is a valid parse tree indicating a blank line.)
12477  */
12478 static union node *
12479 parsecmd(int interact)
12480 {
12481         tokpushback = 0;
12482         checkkwd = 0;
12483         heredoclist = 0;
12484         doprompt = interact;
12485         setprompt_if(doprompt, doprompt);
12486         needprompt = 0;
12487         return list(1);
12488 }
12489
12490 /*
12491  * Input any here documents.
12492  */
12493 static void
12494 parseheredoc(void)
12495 {
12496         struct heredoc *here;
12497         union node *n;
12498
12499         here = heredoclist;
12500         heredoclist = NULL;
12501
12502         while (here) {
12503                 setprompt_if(needprompt, 2);
12504                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12505                                 here->eofmark, here->striptabs);
12506                 n = stzalloc(sizeof(struct narg));
12507                 n->narg.type = NARG;
12508                 /*n->narg.next = NULL; - stzalloc did it */
12509                 n->narg.text = wordtext;
12510                 n->narg.backquote = backquotelist;
12511                 here->here->nhere.doc = n;
12512                 here = here->next;
12513         }
12514 }
12515
12516
12517 static const char *
12518 expandstr(const char *ps, int syntax_type)
12519 {
12520         union node n;
12521         int saveprompt;
12522
12523         /* XXX Fix (char *) cast. */
12524         setinputstring((char *)ps);
12525
12526         saveprompt = doprompt;
12527         doprompt = 0;
12528         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12529         doprompt = saveprompt;
12530
12531         popfile();
12532
12533         n.narg.type = NARG;
12534         n.narg.next = NULL;
12535         n.narg.text = wordtext;
12536         n.narg.backquote = backquotelist;
12537
12538         expandarg(&n, NULL, EXP_QUOTED);
12539         return stackblock();
12540 }
12541
12542 static inline int
12543 parser_eof(void)
12544 {
12545         return tokpushback && lasttoken == TEOF;
12546 }
12547
12548 /*
12549  * Execute a command or commands contained in a string.
12550  */
12551 static int
12552 evalstring(char *s, int flags)
12553 {
12554         struct jmploc *volatile savehandler;
12555         struct jmploc jmploc;
12556         int ex;
12557
12558         union node *n;
12559         struct stackmark smark;
12560         int status;
12561
12562         s = sstrdup(s);
12563         setinputstring(s);
12564         setstackmark(&smark);
12565
12566         status = 0;
12567         /* On exception inside execution loop, we must popfile().
12568          * Try interactively:
12569          *      readonly a=a
12570          *      command eval "a=b"  # throws "is read only" error
12571          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12572          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12573          */
12574         savehandler = exception_handler;
12575         ex = setjmp(jmploc.loc);
12576         if (ex)
12577                 goto out;
12578         exception_handler = &jmploc;
12579
12580         while ((n = parsecmd(0)) != NODE_EOF) {
12581                 int i;
12582
12583                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12584                 if (n)
12585                         status = i;
12586                 popstackmark(&smark);
12587                 if (evalskip)
12588                         break;
12589         }
12590  out:
12591         popstackmark(&smark);
12592         popfile();
12593         stunalloc(s);
12594
12595         exception_handler = savehandler;
12596         if (ex)
12597                 longjmp(exception_handler->loc, ex);
12598
12599         return status;
12600 }
12601
12602 /*
12603  * The eval command.
12604  */
12605 static int FAST_FUNC
12606 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12607 {
12608         char *p;
12609         char *concat;
12610
12611         if (argv[1]) {
12612                 p = argv[1];
12613                 argv += 2;
12614                 if (argv[0]) {
12615                         STARTSTACKSTR(concat);
12616                         for (;;) {
12617                                 concat = stack_putstr(p, concat);
12618                                 p = *argv++;
12619                                 if (p == NULL)
12620                                         break;
12621                                 STPUTC(' ', concat);
12622                         }
12623                         STPUTC('\0', concat);
12624                         p = grabstackstr(concat);
12625                 }
12626                 return evalstring(p, flags & EV_TESTED);
12627         }
12628         return 0;
12629 }
12630
12631 /*
12632  * Read and execute commands.
12633  * "Top" is nonzero for the top level command loop;
12634  * it turns on prompting if the shell is interactive.
12635  */
12636 static int
12637 cmdloop(int top)
12638 {
12639         union node *n;
12640         struct stackmark smark;
12641         int inter;
12642         int status = 0;
12643         int numeof = 0;
12644
12645         TRACE(("cmdloop(%d) called\n", top));
12646         for (;;) {
12647                 int skip;
12648
12649                 setstackmark(&smark);
12650 #if JOBS
12651                 if (doing_jobctl)
12652                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12653 #endif
12654                 inter = 0;
12655                 if (iflag && top) {
12656                         inter++;
12657                         chkmail();
12658                 }
12659                 n = parsecmd(inter);
12660 #if DEBUG
12661                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12662                         showtree(n);
12663 #endif
12664                 if (n == NODE_EOF) {
12665                         if (!top || numeof >= 50)
12666                                 break;
12667                         if (!stoppedjobs()) {
12668                                 if (!Iflag)
12669                                         break;
12670                                 out2str("\nUse \"exit\" to leave shell.\n");
12671                         }
12672                         numeof++;
12673                 } else if (nflag == 0) {
12674                         int i;
12675
12676                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12677                         job_warning >>= 1;
12678                         numeof = 0;
12679                         i = evaltree(n, 0);
12680                         if (n)
12681                                 status = i;
12682                 }
12683                 popstackmark(&smark);
12684                 skip = evalskip;
12685
12686                 if (skip) {
12687                         evalskip &= ~SKIPFUNC;
12688                         break;
12689                 }
12690         }
12691         return status;
12692 }
12693
12694 /*
12695  * Take commands from a file.  To be compatible we should do a path
12696  * search for the file, which is necessary to find sub-commands.
12697  */
12698 static char *
12699 find_dot_file(char *name)
12700 {
12701         char *fullname;
12702         const char *path = pathval();
12703         struct stat statb;
12704
12705         /* don't try this for absolute or relative paths */
12706         if (strchr(name, '/'))
12707                 return name;
12708
12709         while ((fullname = path_advance(&path, name)) != NULL) {
12710                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12711                         /*
12712                          * Don't bother freeing here, since it will
12713                          * be freed by the caller.
12714                          */
12715                         return fullname;
12716                 }
12717                 if (fullname != name)
12718                         stunalloc(fullname);
12719         }
12720
12721         /* not found in the PATH */
12722         ash_msg_and_raise_error("%s: not found", name);
12723         /* NOTREACHED */
12724 }
12725
12726 static int FAST_FUNC
12727 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12728 {
12729         /* "false; . empty_file; echo $?" should print 0, not 1: */
12730         int status = 0;
12731         char *fullname;
12732         char **argv;
12733         char *args_need_save;
12734         volatile struct shparam saveparam;
12735
12736 //???
12737 //      struct strlist *sp;
12738 //      for (sp = cmdenviron; sp; sp = sp->next)
12739 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12740
12741         nextopt(nullstr); /* handle possible "--" */
12742         argv = argptr;
12743
12744         if (!argv[0]) {
12745                 /* bash says: "bash: .: filename argument required" */
12746                 return 2; /* bash compat */
12747         }
12748
12749         /* This aborts if file isn't found, which is POSIXly correct.
12750          * bash returns exitcode 1 instead.
12751          */
12752         fullname = find_dot_file(argv[0]);
12753         argv++;
12754         args_need_save = argv[0];
12755         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12756                 int argc;
12757                 saveparam = shellparam;
12758                 shellparam.malloced = 0;
12759                 argc = 1;
12760                 while (argv[argc])
12761                         argc++;
12762                 shellparam.nparam = argc;
12763                 shellparam.p = argv;
12764         };
12765
12766         /* This aborts if file can't be opened, which is POSIXly correct.
12767          * bash returns exitcode 1 instead.
12768          */
12769         setinputfile(fullname, INPUT_PUSH_FILE);
12770         commandname = fullname;
12771         status = cmdloop(0);
12772         popfile();
12773
12774         if (args_need_save) {
12775                 freeparam(&shellparam);
12776                 shellparam = saveparam;
12777         };
12778
12779         return status;
12780 }
12781
12782 static int FAST_FUNC
12783 exitcmd(int argc UNUSED_PARAM, char **argv)
12784 {
12785         if (stoppedjobs())
12786                 return 0;
12787         if (argv[1])
12788                 exitstatus = number(argv[1]);
12789         raise_exception(EXEXIT);
12790         /* NOTREACHED */
12791 }
12792
12793 /*
12794  * Read a file containing shell functions.
12795  */
12796 static void
12797 readcmdfile(char *name)
12798 {
12799         setinputfile(name, INPUT_PUSH_FILE);
12800         cmdloop(0);
12801         popfile();
12802 }
12803
12804
12805 /* ============ find_command inplementation */
12806
12807 /*
12808  * Resolve a command name.  If you change this routine, you may have to
12809  * change the shellexec routine as well.
12810  */
12811 static void
12812 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12813 {
12814         struct tblentry *cmdp;
12815         int idx;
12816         int prev;
12817         char *fullname;
12818         struct stat statb;
12819         int e;
12820         int updatetbl;
12821         struct builtincmd *bcmd;
12822
12823         /* If name contains a slash, don't use PATH or hash table */
12824         if (strchr(name, '/') != NULL) {
12825                 entry->u.index = -1;
12826                 if (act & DO_ABS) {
12827                         while (stat(name, &statb) < 0) {
12828 #ifdef SYSV
12829                                 if (errno == EINTR)
12830                                         continue;
12831 #endif
12832                                 entry->cmdtype = CMDUNKNOWN;
12833                                 return;
12834                         }
12835                 }
12836                 entry->cmdtype = CMDNORMAL;
12837                 return;
12838         }
12839
12840 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12841
12842         updatetbl = (path == pathval());
12843         if (!updatetbl) {
12844                 act |= DO_ALTPATH;
12845                 if (strstr(path, "%builtin") != NULL)
12846                         act |= DO_ALTBLTIN;
12847         }
12848
12849         /* If name is in the table, check answer will be ok */
12850         cmdp = cmdlookup(name, 0);
12851         if (cmdp != NULL) {
12852                 int bit;
12853
12854                 switch (cmdp->cmdtype) {
12855                 default:
12856 #if DEBUG
12857                         abort();
12858 #endif
12859                 case CMDNORMAL:
12860                         bit = DO_ALTPATH;
12861                         break;
12862                 case CMDFUNCTION:
12863                         bit = DO_NOFUNC;
12864                         break;
12865                 case CMDBUILTIN:
12866                         bit = DO_ALTBLTIN;
12867                         break;
12868                 }
12869                 if (act & bit) {
12870                         updatetbl = 0;
12871                         cmdp = NULL;
12872                 } else if (cmdp->rehash == 0)
12873                         /* if not invalidated by cd, we're done */
12874                         goto success;
12875         }
12876
12877         /* If %builtin not in path, check for builtin next */
12878         bcmd = find_builtin(name);
12879         if (bcmd) {
12880                 if (IS_BUILTIN_REGULAR(bcmd))
12881                         goto builtin_success;
12882                 if (act & DO_ALTPATH) {
12883                         if (!(act & DO_ALTBLTIN))
12884                                 goto builtin_success;
12885                 } else if (builtinloc <= 0) {
12886                         goto builtin_success;
12887                 }
12888         }
12889
12890 #if ENABLE_FEATURE_SH_STANDALONE
12891         {
12892                 int applet_no = find_applet_by_name(name);
12893                 if (applet_no >= 0) {
12894                         entry->cmdtype = CMDNORMAL;
12895                         entry->u.index = -2 - applet_no;
12896                         return;
12897                 }
12898         }
12899 #endif
12900
12901         /* We have to search path. */
12902         prev = -1;              /* where to start */
12903         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12904                 if (cmdp->cmdtype == CMDBUILTIN)
12905                         prev = builtinloc;
12906                 else
12907                         prev = cmdp->param.index;
12908         }
12909
12910         e = ENOENT;
12911         idx = -1;
12912  loop:
12913         while ((fullname = path_advance(&path, name)) != NULL) {
12914                 stunalloc(fullname);
12915                 /* NB: code below will still use fullname
12916                  * despite it being "unallocated" */
12917                 idx++;
12918                 if (pathopt) {
12919                         if (prefix(pathopt, "builtin")) {
12920                                 if (bcmd)
12921                                         goto builtin_success;
12922                                 continue;
12923                         }
12924                         if ((act & DO_NOFUNC)
12925                          || !prefix(pathopt, "func")
12926                         ) {     /* ignore unimplemented options */
12927                                 continue;
12928                         }
12929                 }
12930                 /* if rehash, don't redo absolute path names */
12931                 if (fullname[0] == '/' && idx <= prev) {
12932                         if (idx < prev)
12933                                 continue;
12934                         TRACE(("searchexec \"%s\": no change\n", name));
12935                         goto success;
12936                 }
12937                 while (stat(fullname, &statb) < 0) {
12938 #ifdef SYSV
12939                         if (errno == EINTR)
12940                                 continue;
12941 #endif
12942                         if (errno != ENOENT && errno != ENOTDIR)
12943                                 e = errno;
12944                         goto loop;
12945                 }
12946                 e = EACCES;     /* if we fail, this will be the error */
12947                 if (!S_ISREG(statb.st_mode))
12948                         continue;
12949                 if (pathopt) {          /* this is a %func directory */
12950                         stalloc(strlen(fullname) + 1);
12951                         /* NB: stalloc will return space pointed by fullname
12952                          * (because we don't have any intervening allocations
12953                          * between stunalloc above and this stalloc) */
12954                         readcmdfile(fullname);
12955                         cmdp = cmdlookup(name, 0);
12956                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12957                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12958                         stunalloc(fullname);
12959                         goto success;
12960                 }
12961                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12962                 if (!updatetbl) {
12963                         entry->cmdtype = CMDNORMAL;
12964                         entry->u.index = idx;
12965                         return;
12966                 }
12967                 INT_OFF;
12968                 cmdp = cmdlookup(name, 1);
12969                 cmdp->cmdtype = CMDNORMAL;
12970                 cmdp->param.index = idx;
12971                 INT_ON;
12972                 goto success;
12973         }
12974
12975         /* We failed.  If there was an entry for this command, delete it */
12976         if (cmdp && updatetbl)
12977                 delete_cmd_entry();
12978         if (act & DO_ERR)
12979                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12980         entry->cmdtype = CMDUNKNOWN;
12981         return;
12982
12983  builtin_success:
12984         if (!updatetbl) {
12985                 entry->cmdtype = CMDBUILTIN;
12986                 entry->u.cmd = bcmd;
12987                 return;
12988         }
12989         INT_OFF;
12990         cmdp = cmdlookup(name, 1);
12991         cmdp->cmdtype = CMDBUILTIN;
12992         cmdp->param.cmd = bcmd;
12993         INT_ON;
12994  success:
12995         cmdp->rehash = 0;
12996         entry->cmdtype = cmdp->cmdtype;
12997         entry->u = cmdp->param;
12998 }
12999
13000
13001 /*
13002  * The trap builtin.
13003  */
13004 static int FAST_FUNC
13005 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13006 {
13007         char *action;
13008         char **ap;
13009         int signo, exitcode;
13010
13011         nextopt(nullstr);
13012         ap = argptr;
13013         if (!*ap) {
13014                 for (signo = 0; signo < NSIG; signo++) {
13015                         char *tr = trap_ptr[signo];
13016                         if (tr) {
13017                                 /* note: bash adds "SIG", but only if invoked
13018                                  * as "bash". If called as "sh", or if set -o posix,
13019                                  * then it prints short signal names.
13020                                  * We are printing short names: */
13021                                 out1fmt("trap -- %s %s\n",
13022                                                 single_quote(tr),
13023                                                 get_signame(signo));
13024                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13025                  * In this case, we will exit very soon, no need to free(). */
13026                                 /* if (trap_ptr != trap && tp[0]) */
13027                                 /*      free(tr); */
13028                         }
13029                 }
13030                 /*
13031                 if (trap_ptr != trap) {
13032                         free(trap_ptr);
13033                         trap_ptr = trap;
13034                 }
13035                 */
13036                 return 0;
13037         }
13038
13039         /* Why the second check?
13040          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13041          * In this case, NUM is signal no, not an action.
13042          */
13043         action = NULL;
13044         if (ap[1] && !is_number(ap[0]))
13045                 action = *ap++;
13046
13047         exitcode = 0;
13048         while (*ap) {
13049                 signo = get_signum(*ap);
13050                 if (signo < 0) {
13051                         /* Mimic bash message exactly */
13052                         ash_msg("%s: invalid signal specification", *ap);
13053                         exitcode = 1;
13054                         goto next;
13055                 }
13056                 INT_OFF;
13057                 if (action) {
13058                         if (LONE_DASH(action))
13059                                 action = NULL;
13060                         else {
13061                                 if (action[0]) /* not NULL and not "" and not "-" */
13062                                         may_have_traps = 1;
13063                                 action = ckstrdup(action);
13064                         }
13065                 }
13066                 free(trap[signo]);
13067                 trap[signo] = action;
13068                 if (signo != 0)
13069                         setsignal(signo);
13070                 INT_ON;
13071  next:
13072                 ap++;
13073         }
13074         return exitcode;
13075 }
13076
13077
13078 /* ============ Builtins */
13079
13080 #if ENABLE_ASH_HELP
13081 static int FAST_FUNC
13082 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13083 {
13084         unsigned col;
13085         unsigned i;
13086
13087         out1fmt(
13088                 "Built-in commands:\n"
13089                 "------------------\n");
13090         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13091                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13092                                         builtintab[i].name + 1);
13093                 if (col > 60) {
13094                         out1fmt("\n");
13095                         col = 0;
13096                 }
13097         }
13098 # if ENABLE_FEATURE_SH_STANDALONE
13099         {
13100                 const char *a = applet_names;
13101                 while (*a) {
13102                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13103                         if (col > 60) {
13104                                 out1fmt("\n");
13105                                 col = 0;
13106                         }
13107                         while (*a++ != '\0')
13108                                 continue;
13109                 }
13110         }
13111 # endif
13112         newline_and_flush(stdout);
13113         return EXIT_SUCCESS;
13114 }
13115 #endif
13116
13117 #if MAX_HISTORY
13118 static int FAST_FUNC
13119 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13120 {
13121         show_history(line_input_state);
13122         return EXIT_SUCCESS;
13123 }
13124 #endif
13125
13126 /*
13127  * The export and readonly commands.
13128  */
13129 static int FAST_FUNC
13130 exportcmd(int argc UNUSED_PARAM, char **argv)
13131 {
13132         struct var *vp;
13133         char *name;
13134         const char *p;
13135         char **aptr;
13136         char opt;
13137         int flag;
13138         int flag_off;
13139
13140         /* "readonly" in bash accepts, but ignores -n.
13141          * We do the same: it saves a conditional in nextopt's param.
13142          */
13143         flag_off = 0;
13144         while ((opt = nextopt("np")) != '\0') {
13145                 if (opt == 'n')
13146                         flag_off = VEXPORT;
13147         }
13148         flag = VEXPORT;
13149         if (argv[0][0] == 'r') {
13150                 flag = VREADONLY;
13151                 flag_off = 0; /* readonly ignores -n */
13152         }
13153         flag_off = ~flag_off;
13154
13155         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13156         {
13157                 aptr = argptr;
13158                 name = *aptr;
13159                 if (name) {
13160                         do {
13161                                 p = strchr(name, '=');
13162                                 if (p != NULL) {
13163                                         p++;
13164                                 } else {
13165                                         vp = *findvar(hashvar(name), name);
13166                                         if (vp) {
13167                                                 vp->flags = ((vp->flags | flag) & flag_off);
13168                                                 continue;
13169                                         }
13170                                 }
13171                                 setvar(name, p, (flag & flag_off));
13172                         } while ((name = *++aptr) != NULL);
13173                         return 0;
13174                 }
13175         }
13176
13177         /* No arguments. Show the list of exported or readonly vars.
13178          * -n is ignored.
13179          */
13180         showvars(argv[0], flag, 0);
13181         return 0;
13182 }
13183
13184 /*
13185  * Delete a function if it exists.
13186  */
13187 static void
13188 unsetfunc(const char *name)
13189 {
13190         struct tblentry *cmdp;
13191
13192         cmdp = cmdlookup(name, 0);
13193         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13194                 delete_cmd_entry();
13195 }
13196
13197 /*
13198  * The unset builtin command.  We unset the function before we unset the
13199  * variable to allow a function to be unset when there is a readonly variable
13200  * with the same name.
13201  */
13202 static int FAST_FUNC
13203 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13204 {
13205         char **ap;
13206         int i;
13207         int flag = 0;
13208
13209         while ((i = nextopt("vf")) != 0) {
13210                 flag = i;
13211         }
13212
13213         for (ap = argptr; *ap; ap++) {
13214                 if (flag != 'f') {
13215                         unsetvar(*ap);
13216                         continue;
13217                 }
13218                 if (flag != 'v')
13219                         unsetfunc(*ap);
13220         }
13221         return 0;
13222 }
13223
13224 static const unsigned char timescmd_str[] ALIGN1 = {
13225         ' ',  offsetof(struct tms, tms_utime),
13226         '\n', offsetof(struct tms, tms_stime),
13227         ' ',  offsetof(struct tms, tms_cutime),
13228         '\n', offsetof(struct tms, tms_cstime),
13229         0
13230 };
13231 static int FAST_FUNC
13232 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13233 {
13234         unsigned long clk_tck, s, t;
13235         const unsigned char *p;
13236         struct tms buf;
13237
13238         clk_tck = bb_clk_tck();
13239         times(&buf);
13240
13241         p = timescmd_str;
13242         do {
13243                 t = *(clock_t *)(((char *) &buf) + p[1]);
13244                 s = t / clk_tck;
13245                 t = t % clk_tck;
13246                 out1fmt("%lum%lu.%03lus%c",
13247                         s / 60, s % 60,
13248                         (t * 1000) / clk_tck,
13249                         p[0]);
13250                 p += 2;
13251         } while (*p);
13252
13253         return 0;
13254 }
13255
13256 #if ENABLE_FEATURE_SH_MATH
13257 /*
13258  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13259  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13260  *
13261  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13262  */
13263 static int FAST_FUNC
13264 letcmd(int argc UNUSED_PARAM, char **argv)
13265 {
13266         arith_t i;
13267
13268         argv++;
13269         if (!*argv)
13270                 ash_msg_and_raise_error("expression expected");
13271         do {
13272                 i = ash_arith(*argv);
13273         } while (*++argv);
13274
13275         return !i;
13276 }
13277 #endif
13278
13279 /*
13280  * The read builtin. Options:
13281  *      -r              Do not interpret '\' specially
13282  *      -s              Turn off echo (tty only)
13283  *      -n NCHARS       Read NCHARS max
13284  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13285  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13286  *      -u FD           Read from given FD instead of fd 0
13287  * This uses unbuffered input, which may be avoidable in some cases.
13288  * TODO: bash also has:
13289  *      -a ARRAY        Read into array[0],[1],etc
13290  *      -d DELIM        End on DELIM char, not newline
13291  *      -e              Use line editing (tty only)
13292  */
13293 static int FAST_FUNC
13294 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13295 {
13296         char *opt_n = NULL;
13297         char *opt_p = NULL;
13298         char *opt_t = NULL;
13299         char *opt_u = NULL;
13300         int read_flags = 0;
13301         const char *r;
13302         int i;
13303
13304         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13305                 switch (i) {
13306                 case 'p':
13307                         opt_p = optionarg;
13308                         break;
13309                 case 'n':
13310                         opt_n = optionarg;
13311                         break;
13312                 case 's':
13313                         read_flags |= BUILTIN_READ_SILENT;
13314                         break;
13315                 case 't':
13316                         opt_t = optionarg;
13317                         break;
13318                 case 'r':
13319                         read_flags |= BUILTIN_READ_RAW;
13320                         break;
13321                 case 'u':
13322                         opt_u = optionarg;
13323                         break;
13324                 default:
13325                         break;
13326                 }
13327         }
13328
13329         /* "read -s" needs to save/restore termios, can't allow ^C
13330          * to jump out of it.
13331          */
13332  again:
13333         INT_OFF;
13334         r = shell_builtin_read(setvar0,
13335                 argptr,
13336                 bltinlookup("IFS"), /* can be NULL */
13337                 read_flags,
13338                 opt_n,
13339                 opt_p,
13340                 opt_t,
13341                 opt_u
13342         );
13343         INT_ON;
13344
13345         if ((uintptr_t)r == 1 && errno == EINTR) {
13346                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13347                 if (pending_sig == 0)
13348                         goto again;
13349         }
13350
13351         if ((uintptr_t)r > 1)
13352                 ash_msg_and_raise_error(r);
13353
13354         return (uintptr_t)r;
13355 }
13356
13357 static int FAST_FUNC
13358 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13359 {
13360         static const char permuser[3] ALIGN1 = "ogu";
13361
13362         mode_t mask;
13363         int symbolic_mode = 0;
13364
13365         while (nextopt("S") != '\0') {
13366                 symbolic_mode = 1;
13367         }
13368
13369         INT_OFF;
13370         mask = umask(0);
13371         umask(mask);
13372         INT_ON;
13373
13374         if (*argptr == NULL) {
13375                 if (symbolic_mode) {
13376                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13377                         char *p = buf;
13378                         int i;
13379
13380                         i = 2;
13381                         for (;;) {
13382                                 *p++ = ',';
13383                                 *p++ = permuser[i];
13384                                 *p++ = '=';
13385                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13386                                 if (!(mask & 0400)) *p++ = 'r';
13387                                 if (!(mask & 0200)) *p++ = 'w';
13388                                 if (!(mask & 0100)) *p++ = 'x';
13389                                 mask <<= 3;
13390                                 if (--i < 0)
13391                                         break;
13392                         }
13393                         *p = '\0';
13394                         puts(buf + 1);
13395                 } else {
13396                         out1fmt("%04o\n", mask);
13397                 }
13398         } else {
13399                 char *modestr = *argptr;
13400                 /* numeric umasks are taken as-is */
13401                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13402                 if (!isdigit(modestr[0]))
13403                         mask ^= 0777;
13404                 mask = bb_parse_mode(modestr, mask);
13405                 if ((unsigned)mask > 0777) {
13406                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13407                 }
13408                 if (!isdigit(modestr[0]))
13409                         mask ^= 0777;
13410                 umask(mask);
13411         }
13412         return 0;
13413 }
13414
13415 static int FAST_FUNC
13416 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13417 {
13418         return shell_builtin_ulimit(argv);
13419 }
13420
13421 /* ============ main() and helpers */
13422
13423 /*
13424  * Called to exit the shell.
13425  */
13426 static void
13427 exitshell(void)
13428 {
13429         struct jmploc loc;
13430         char *p;
13431         int status;
13432
13433 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13434         save_history(line_input_state);
13435 #endif
13436         status = exitstatus;
13437         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13438         if (setjmp(loc.loc)) {
13439                 if (exception_type == EXEXIT)
13440                         status = exitstatus;
13441                 goto out;
13442         }
13443         exception_handler = &loc;
13444         p = trap[0];
13445         if (p) {
13446                 trap[0] = NULL;
13447                 evalskip = 0;
13448                 evalstring(p, 0);
13449                 /*free(p); - we'll exit soon */
13450         }
13451  out:
13452         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13453          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13454          */
13455         setjobctl(0);
13456         flush_stdout_stderr();
13457         _exit(status);
13458         /* NOTREACHED */
13459 }
13460
13461 static void
13462 init(void)
13463 {
13464         /* we will never free this */
13465         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13466
13467         sigmode[SIGCHLD - 1] = S_DFL;
13468         setsignal(SIGCHLD);
13469
13470         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13471          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13472          */
13473         signal(SIGHUP, SIG_DFL);
13474
13475         {
13476                 char **envp;
13477                 const char *p;
13478                 struct stat st1, st2;
13479
13480                 initvar();
13481                 for (envp = environ; envp && *envp; envp++) {
13482                         p = endofname(*envp);
13483                         if (p != *envp && *p == '=') {
13484                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13485                         }
13486                 }
13487
13488                 setvareq((char*)defoptindvar, VTEXTFIXED);
13489
13490                 setvar0("PPID", utoa(getppid()));
13491 #if BASH_SHLVL_VAR
13492                 p = lookupvar("SHLVL");
13493                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13494 #endif
13495 #if BASH_HOSTNAME_VAR
13496                 if (!lookupvar("HOSTNAME")) {
13497                         struct utsname uts;
13498                         uname(&uts);
13499                         setvar0("HOSTNAME", uts.nodename);
13500                 }
13501 #endif
13502                 p = lookupvar("PWD");
13503                 if (p) {
13504                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13505                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13506                         ) {
13507                                 p = NULL;
13508                         }
13509                 }
13510                 setpwd(p, 0);
13511         }
13512 }
13513
13514
13515 //usage:#define ash_trivial_usage
13516 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13517 //usage:#define ash_full_usage "\n\n"
13518 //usage:        "Unix shell interpreter"
13519
13520 /*
13521  * Process the shell command line arguments.
13522  */
13523 static void
13524 procargs(char **argv)
13525 {
13526         int i;
13527         const char *xminusc;
13528         char **xargv;
13529
13530         xargv = argv;
13531         arg0 = xargv[0];
13532         /* if (xargv[0]) - mmm, this is always true! */
13533                 xargv++;
13534         for (i = 0; i < NOPTS; i++)
13535                 optlist[i] = 2;
13536         argptr = xargv;
13537         if (options(/*cmdline:*/ 1)) {
13538                 /* it already printed err message */
13539                 raise_exception(EXERROR);
13540         }
13541         xargv = argptr;
13542         xminusc = minusc;
13543         if (*xargv == NULL) {
13544                 if (xminusc)
13545                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13546                 sflag = 1;
13547         }
13548         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13549                 iflag = 1;
13550         if (mflag == 2)
13551                 mflag = iflag;
13552         for (i = 0; i < NOPTS; i++)
13553                 if (optlist[i] == 2)
13554                         optlist[i] = 0;
13555 #if DEBUG == 2
13556         debug = 1;
13557 #endif
13558         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13559         if (xminusc) {
13560                 minusc = *xargv++;
13561                 if (*xargv)
13562                         goto setarg0;
13563         } else if (!sflag) {
13564                 setinputfile(*xargv, 0);
13565  setarg0:
13566                 arg0 = *xargv++;
13567                 commandname = arg0;
13568         }
13569
13570         shellparam.p = xargv;
13571 #if ENABLE_ASH_GETOPTS
13572         shellparam.optind = 1;
13573         shellparam.optoff = -1;
13574 #endif
13575         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13576         while (*xargv) {
13577                 shellparam.nparam++;
13578                 xargv++;
13579         }
13580         optschanged();
13581 }
13582
13583 /*
13584  * Read /etc/profile, ~/.profile, $ENV.
13585  */
13586 static void
13587 read_profile(const char *name)
13588 {
13589         name = expandstr(name, DQSYNTAX);
13590         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13591                 return;
13592         cmdloop(0);
13593         popfile();
13594 }
13595
13596 /*
13597  * This routine is called when an error or an interrupt occurs in an
13598  * interactive shell and control is returned to the main command loop.
13599  * (In dash, this function is auto-generated by build machinery).
13600  */
13601 static void
13602 reset(void)
13603 {
13604         /* from eval.c: */
13605         evalskip = 0;
13606         loopnest = 0;
13607
13608         /* from expand.c: */
13609         ifsfree();
13610
13611         /* from input.c: */
13612         g_parsefile->left_in_buffer = 0;
13613         g_parsefile->left_in_line = 0;      /* clear input buffer */
13614         popallfiles();
13615
13616         /* from redir.c: */
13617         unwindredir(NULL);
13618
13619         /* from var.c: */
13620         unwindlocalvars(NULL);
13621 }
13622
13623 #if PROFILE
13624 static short profile_buf[16384];
13625 extern int etext();
13626 #endif
13627
13628 /*
13629  * Main routine.  We initialize things, parse the arguments, execute
13630  * profiles if we're a login shell, and then call cmdloop to execute
13631  * commands.  The setjmp call sets up the location to jump to when an
13632  * exception occurs.  When an exception occurs the variable "state"
13633  * is used to figure out how far we had gotten.
13634  */
13635 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13636 int ash_main(int argc UNUSED_PARAM, char **argv)
13637 {
13638         volatile smallint state;
13639         struct jmploc jmploc;
13640         struct stackmark smark;
13641
13642         /* Initialize global data */
13643         INIT_G_misc();
13644         INIT_G_memstack();
13645         INIT_G_var();
13646 #if ENABLE_ASH_ALIAS
13647         INIT_G_alias();
13648 #endif
13649         INIT_G_cmdtable();
13650
13651 #if PROFILE
13652         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13653 #endif
13654
13655 #if ENABLE_FEATURE_EDITING
13656         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13657 #endif
13658         state = 0;
13659         if (setjmp(jmploc.loc)) {
13660                 smallint e;
13661                 smallint s;
13662
13663                 reset();
13664
13665                 e = exception_type;
13666                 s = state;
13667                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13668                         exitshell();
13669                 }
13670                 if (e == EXINT) {
13671                         newline_and_flush(stderr);
13672                 }
13673
13674                 popstackmark(&smark);
13675                 FORCE_INT_ON; /* enable interrupts */
13676                 if (s == 1)
13677                         goto state1;
13678                 if (s == 2)
13679                         goto state2;
13680                 if (s == 3)
13681                         goto state3;
13682                 goto state4;
13683         }
13684         exception_handler = &jmploc;
13685         rootpid = getpid();
13686
13687         init();
13688         setstackmark(&smark);
13689         procargs(argv);
13690 #if DEBUG
13691         TRACE(("Shell args: "));
13692         trace_puts_args(argv);
13693 #endif
13694
13695         if (argv[0] && argv[0][0] == '-')
13696                 isloginsh = 1;
13697         if (isloginsh) {
13698                 const char *hp;
13699
13700                 state = 1;
13701                 read_profile("/etc/profile");
13702  state1:
13703                 state = 2;
13704                 hp = lookupvar("HOME");
13705                 if (hp)
13706                         read_profile("$HOME/.profile");
13707         }
13708  state2:
13709         state = 3;
13710         if (
13711 #ifndef linux
13712          getuid() == geteuid() && getgid() == getegid() &&
13713 #endif
13714          iflag
13715         ) {
13716                 const char *shinit = lookupvar("ENV");
13717                 if (shinit != NULL && *shinit != '\0')
13718                         read_profile(shinit);
13719         }
13720         popstackmark(&smark);
13721  state3:
13722         state = 4;
13723         if (minusc) {
13724                 /* evalstring pushes parsefile stack.
13725                  * Ensure we don't falsely claim that 0 (stdin)
13726                  * is one of stacked source fds.
13727                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13728                 // if (!sflag) g_parsefile->pf_fd = -1;
13729                 // ^^ not necessary since now we special-case fd 0
13730                 // in is_hidden_fd() to not be considered "hidden fd"
13731                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13732         }
13733
13734         if (sflag || minusc == NULL) {
13735 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13736                 if (iflag) {
13737                         const char *hp = lookupvar("HISTFILE");
13738                         if (!hp) {
13739                                 hp = lookupvar("HOME");
13740                                 if (hp) {
13741                                         INT_OFF;
13742                                         hp = concat_path_file(hp, ".ash_history");
13743                                         setvar0("HISTFILE", hp);
13744                                         free((char*)hp);
13745                                         INT_ON;
13746                                         hp = lookupvar("HISTFILE");
13747                                 }
13748                         }
13749                         if (hp)
13750                                 line_input_state->hist_file = hp;
13751 # if ENABLE_FEATURE_SH_HISTFILESIZE
13752                         hp = lookupvar("HISTFILESIZE");
13753                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13754 # endif
13755                 }
13756 #endif
13757  state4: /* XXX ??? - why isn't this before the "if" statement */
13758                 cmdloop(1);
13759         }
13760 #if PROFILE
13761         monitor(0);
13762 #endif
13763 #ifdef GPROF
13764         {
13765                 extern void _mcleanup(void);
13766                 _mcleanup();
13767         }
13768 #endif
13769         TRACE(("End of main reached\n"));
13770         exitshell();
13771         /* NOTREACHED */
13772 }
13773
13774
13775 /*-
13776  * Copyright (c) 1989, 1991, 1993, 1994
13777  *      The Regents of the University of California.  All rights reserved.
13778  *
13779  * This code is derived from software contributed to Berkeley by
13780  * Kenneth Almquist.
13781  *
13782  * Redistribution and use in source and binary forms, with or without
13783  * modification, are permitted provided that the following conditions
13784  * are met:
13785  * 1. Redistributions of source code must retain the above copyright
13786  *    notice, this list of conditions and the following disclaimer.
13787  * 2. Redistributions in binary form must reproduce the above copyright
13788  *    notice, this list of conditions and the following disclaimer in the
13789  *    documentation and/or other materials provided with the distribution.
13790  * 3. Neither the name of the University nor the names of its contributors
13791  *    may be used to endorse or promote products derived from this software
13792  *    without specific prior written permission.
13793  *
13794  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13795  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13796  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13797  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13798  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13799  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13800  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13801  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13802  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13803  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13804  * SUCH DAMAGE.
13805  */