ash: [PARSER] Add FAKEEOFMARK for expandstr
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps, int syntax_type);
2492 /* Values for syntax param */
2493 #define BASESYNTAX 0    /* not in quotes */
2494 #define DQSYNTAX   1    /* in double quotes */
2495 #define SQSYNTAX   2    /* in single quotes */
2496 #define ARISYNTAX  3    /* in arithmetic */
2497 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2498 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2499
2500 /*
2501  * called by editline -- any expansions to the prompt should be added here.
2502  */
2503 static void
2504 setprompt_if(smallint do_set, int whichprompt)
2505 {
2506         const char *prompt;
2507         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2508
2509         if (!do_set)
2510                 return;
2511
2512         needprompt = 0;
2513
2514         switch (whichprompt) {
2515         case 1:
2516                 prompt = ps1val();
2517                 break;
2518         case 2:
2519                 prompt = ps2val();
2520                 break;
2521         default:                        /* 0 */
2522                 prompt = nullstr;
2523         }
2524 #if ENABLE_ASH_EXPAND_PRMT
2525         pushstackmark(&smark, stackblocksize());
2526         putprompt(expandstr(prompt, PSSYNTAX));
2527         popstackmark(&smark);
2528 #else
2529         putprompt(prompt);
2530 #endif
2531 }
2532
2533
2534 /* ============ The cd and pwd commands */
2535
2536 #define CD_PHYSICAL 1
2537 #define CD_PRINT 2
2538
2539 static int
2540 cdopt(void)
2541 {
2542         int flags = 0;
2543         int i, j;
2544
2545         j = 'L';
2546         while ((i = nextopt("LP")) != '\0') {
2547                 if (i != j) {
2548                         flags ^= CD_PHYSICAL;
2549                         j = i;
2550                 }
2551         }
2552
2553         return flags;
2554 }
2555
2556 /*
2557  * Update curdir (the name of the current directory) in response to a
2558  * cd command.
2559  */
2560 static const char *
2561 updatepwd(const char *dir)
2562 {
2563         char *new;
2564         char *p;
2565         char *cdcomppath;
2566         const char *lim;
2567
2568         cdcomppath = sstrdup(dir);
2569         STARTSTACKSTR(new);
2570         if (*dir != '/') {
2571                 if (curdir == nullstr)
2572                         return 0;
2573                 new = stack_putstr(curdir, new);
2574         }
2575         new = makestrspace(strlen(dir) + 2, new);
2576         lim = (char *)stackblock() + 1;
2577         if (*dir != '/') {
2578                 if (new[-1] != '/')
2579                         USTPUTC('/', new);
2580                 if (new > lim && *lim == '/')
2581                         lim++;
2582         } else {
2583                 USTPUTC('/', new);
2584                 cdcomppath++;
2585                 if (dir[1] == '/' && dir[2] != '/') {
2586                         USTPUTC('/', new);
2587                         cdcomppath++;
2588                         lim++;
2589                 }
2590         }
2591         p = strtok(cdcomppath, "/");
2592         while (p) {
2593                 switch (*p) {
2594                 case '.':
2595                         if (p[1] == '.' && p[2] == '\0') {
2596                                 while (new > lim) {
2597                                         STUNPUTC(new);
2598                                         if (new[-1] == '/')
2599                                                 break;
2600                                 }
2601                                 break;
2602                         }
2603                         if (p[1] == '\0')
2604                                 break;
2605                         /* fall through */
2606                 default:
2607                         new = stack_putstr(p, new);
2608                         USTPUTC('/', new);
2609                 }
2610                 p = strtok(NULL, "/");
2611         }
2612         if (new > lim)
2613                 STUNPUTC(new);
2614         *new = 0;
2615         return stackblock();
2616 }
2617
2618 /*
2619  * Find out what the current directory is. If we already know the current
2620  * directory, this routine returns immediately.
2621  */
2622 static char *
2623 getpwd(void)
2624 {
2625         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2626         return dir ? dir : nullstr;
2627 }
2628
2629 static void
2630 setpwd(const char *val, int setold)
2631 {
2632         char *oldcur, *dir;
2633
2634         oldcur = dir = curdir;
2635
2636         if (setold) {
2637                 setvar("OLDPWD", oldcur, VEXPORT);
2638         }
2639         INT_OFF;
2640         if (physdir != nullstr) {
2641                 if (physdir != oldcur)
2642                         free(physdir);
2643                 physdir = nullstr;
2644         }
2645         if (oldcur == val || !val) {
2646                 char *s = getpwd();
2647                 physdir = s;
2648                 if (!val)
2649                         dir = s;
2650         } else
2651                 dir = ckstrdup(val);
2652         if (oldcur != dir && oldcur != nullstr) {
2653                 free(oldcur);
2654         }
2655         curdir = dir;
2656         INT_ON;
2657         setvar("PWD", dir, VEXPORT);
2658 }
2659
2660 static void hashcd(void);
2661
2662 /*
2663  * Actually do the chdir.  We also call hashcd to let other routines
2664  * know that the current directory has changed.
2665  */
2666 static int
2667 docd(const char *dest, int flags)
2668 {
2669         const char *dir = NULL;
2670         int err;
2671
2672         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2673
2674         INT_OFF;
2675         if (!(flags & CD_PHYSICAL)) {
2676                 dir = updatepwd(dest);
2677                 if (dir)
2678                         dest = dir;
2679         }
2680         err = chdir(dest);
2681         if (err)
2682                 goto out;
2683         setpwd(dir, 1);
2684         hashcd();
2685  out:
2686         INT_ON;
2687         return err;
2688 }
2689
2690 static int FAST_FUNC
2691 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2692 {
2693         const char *dest;
2694         const char *path;
2695         const char *p;
2696         char c;
2697         struct stat statb;
2698         int flags;
2699
2700         flags = cdopt();
2701         dest = *argptr;
2702         if (!dest)
2703                 dest = bltinlookup("HOME");
2704         else if (LONE_DASH(dest)) {
2705                 dest = bltinlookup("OLDPWD");
2706                 flags |= CD_PRINT;
2707         }
2708         if (!dest)
2709                 dest = nullstr;
2710         if (*dest == '/')
2711                 goto step6;
2712         if (*dest == '.') {
2713                 c = dest[1];
2714  dotdot:
2715                 switch (c) {
2716                 case '\0':
2717                 case '/':
2718                         goto step6;
2719                 case '.':
2720                         c = dest[2];
2721                         if (c != '.')
2722                                 goto dotdot;
2723                 }
2724         }
2725         if (!*dest)
2726                 dest = ".";
2727         path = bltinlookup("CDPATH");
2728         while (path) {
2729                 c = *path;
2730                 p = path_advance(&path, dest);
2731                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2732                         if (c && c != ':')
2733                                 flags |= CD_PRINT;
2734  docd:
2735                         if (!docd(p, flags))
2736                                 goto out;
2737                         goto err;
2738                 }
2739         }
2740
2741  step6:
2742         p = dest;
2743         goto docd;
2744
2745  err:
2746         ash_msg_and_raise_error("can't cd to %s", dest);
2747         /* NOTREACHED */
2748  out:
2749         if (flags & CD_PRINT)
2750                 out1fmt("%s\n", curdir);
2751         return 0;
2752 }
2753
2754 static int FAST_FUNC
2755 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2756 {
2757         int flags;
2758         const char *dir = curdir;
2759
2760         flags = cdopt();
2761         if (flags) {
2762                 if (physdir == nullstr)
2763                         setpwd(dir, 0);
2764                 dir = physdir;
2765         }
2766         out1fmt("%s\n", dir);
2767         return 0;
2768 }
2769
2770
2771 /* ============ ... */
2772
2773
2774 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2775
2776 /* Syntax classes */
2777 #define CWORD     0             /* character is nothing special */
2778 #define CNL       1             /* newline character */
2779 #define CBACK     2             /* a backslash character */
2780 #define CSQUOTE   3             /* single quote */
2781 #define CDQUOTE   4             /* double quote */
2782 #define CENDQUOTE 5             /* a terminating quote */
2783 #define CBQUOTE   6             /* backwards single quote */
2784 #define CVAR      7             /* a dollar sign */
2785 #define CENDVAR   8             /* a '}' character */
2786 #define CLP       9             /* a left paren in arithmetic */
2787 #define CRP      10             /* a right paren in arithmetic */
2788 #define CENDFILE 11             /* end of file */
2789 #define CCTL     12             /* like CWORD, except it must be escaped */
2790 #define CSPCL    13             /* these terminate a word */
2791 #define CIGN     14             /* character should be ignored */
2792
2793 #define PEOF     256
2794 #if ENABLE_ASH_ALIAS
2795 # define PEOA    257
2796 #endif
2797
2798 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2799
2800 #if ENABLE_FEATURE_SH_MATH
2801 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2802 #else
2803 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2804 #endif
2805 static const uint16_t S_I_T[] ALIGN2 = {
2806 #if ENABLE_ASH_ALIAS
2807         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2808 #endif
2809         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2810         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2811         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2812         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2813         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2814         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2815         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2816         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2817         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2818         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2819         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2820 #if !USE_SIT_FUNCTION
2821         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2822         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2823         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2824 #endif
2825 #undef SIT_ITEM
2826 };
2827 /* Constants below must match table above */
2828 enum {
2829 #if ENABLE_ASH_ALIAS
2830         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2831 #endif
2832         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2833         CNL_CNL_CNL_CNL                    , /*  2 */
2834         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2835         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2836         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2837         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2838         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2839         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2840         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2841         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2842         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2843         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2844         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2845         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2846 };
2847
2848 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2849  * caller must ensure proper cast on it if c is *char_ptr!
2850  */
2851 #if USE_SIT_FUNCTION
2852
2853 static int
2854 SIT(int c, int syntax)
2855 {
2856         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2857         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2858         /*
2859          * This causes '/' to be prepended with CTLESC in dquoted string,
2860          * making "./file"* treated incorrectly because we feed
2861          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2862          * The "homegrown" glob implementation is okay with that,
2863          * but glibc one isn't. With '/' always treated as CWORD,
2864          * both work fine.
2865          */
2866 # if ENABLE_ASH_ALIAS
2867         static const uint8_t syntax_index_table[] ALIGN1 = {
2868                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2869                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2870                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2871                 11, 3                           /* "}~" */
2872         };
2873 # else
2874         static const uint8_t syntax_index_table[] ALIGN1 = {
2875                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2876                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2877                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2878                 10, 2                           /* "}~" */
2879         };
2880 # endif
2881         const char *s;
2882         int indx;
2883
2884         if (c == PEOF)
2885                 return CENDFILE;
2886 # if ENABLE_ASH_ALIAS
2887         if (c == PEOA)
2888                 indx = 0;
2889         else
2890 # endif
2891         {
2892                 /* Cast is purely for paranoia here,
2893                  * just in case someone passed signed char to us */
2894                 if ((unsigned char)c >= CTL_FIRST
2895                  && (unsigned char)c <= CTL_LAST
2896                 ) {
2897                         return CCTL;
2898                 }
2899                 s = strchrnul(spec_symbls, c);
2900                 if (*s == '\0')
2901                         return CWORD;
2902                 indx = syntax_index_table[s - spec_symbls];
2903         }
2904         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2905 }
2906
2907 #else   /* !USE_SIT_FUNCTION */
2908
2909 static const uint8_t syntax_index_table[] ALIGN1 = {
2910         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2911         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2912         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2913         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2921         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2922         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2944         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2945         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2946         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2948         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2950         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2951         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2952         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2953         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2954         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2956         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2957         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2958 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2959         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2971         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2972         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2973         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2974         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2975         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3004         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3005         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3006         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3009         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3011         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3037         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3038         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3039         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3040         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3041         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3042         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3043         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3044         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3045         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3046         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3047         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3048         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3049         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3168         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3169 # if ENABLE_ASH_ALIAS
3170         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3171 # endif
3172 };
3173
3174 #if 1
3175 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3176 #else /* debug version, caught one signed char bug */
3177 # define SIT(c, syntax) \
3178         ({ \
3179                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3180                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3181                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3182                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3183                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3184         })
3185 #endif
3186
3187 #endif  /* !USE_SIT_FUNCTION */
3188
3189
3190 /* ============ Alias handling */
3191
3192 #if ENABLE_ASH_ALIAS
3193
3194 #define ALIASINUSE 1
3195 #define ALIASDEAD  2
3196
3197 struct alias {
3198         struct alias *next;
3199         char *name;
3200         char *val;
3201         int flag;
3202 };
3203
3204
3205 static struct alias **atab; // [ATABSIZE];
3206 #define INIT_G_alias() do { \
3207         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3208 } while (0)
3209
3210
3211 static struct alias **
3212 __lookupalias(const char *name)
3213 {
3214         unsigned int hashval;
3215         struct alias **app;
3216         const char *p;
3217         unsigned int ch;
3218
3219         p = name;
3220
3221         ch = (unsigned char)*p;
3222         hashval = ch << 4;
3223         while (ch) {
3224                 hashval += ch;
3225                 ch = (unsigned char)*++p;
3226         }
3227         app = &atab[hashval % ATABSIZE];
3228
3229         for (; *app; app = &(*app)->next) {
3230                 if (strcmp(name, (*app)->name) == 0) {
3231                         break;
3232                 }
3233         }
3234
3235         return app;
3236 }
3237
3238 static struct alias *
3239 lookupalias(const char *name, int check)
3240 {
3241         struct alias *ap = *__lookupalias(name);
3242
3243         if (check && ap && (ap->flag & ALIASINUSE))
3244                 return NULL;
3245         return ap;
3246 }
3247
3248 static struct alias *
3249 freealias(struct alias *ap)
3250 {
3251         struct alias *next;
3252
3253         if (ap->flag & ALIASINUSE) {
3254                 ap->flag |= ALIASDEAD;
3255                 return ap;
3256         }
3257
3258         next = ap->next;
3259         free(ap->name);
3260         free(ap->val);
3261         free(ap);
3262         return next;
3263 }
3264
3265 static void
3266 setalias(const char *name, const char *val)
3267 {
3268         struct alias *ap, **app;
3269
3270         app = __lookupalias(name);
3271         ap = *app;
3272         INT_OFF;
3273         if (ap) {
3274                 if (!(ap->flag & ALIASINUSE)) {
3275                         free(ap->val);
3276                 }
3277                 ap->val = ckstrdup(val);
3278                 ap->flag &= ~ALIASDEAD;
3279         } else {
3280                 /* not found */
3281                 ap = ckzalloc(sizeof(struct alias));
3282                 ap->name = ckstrdup(name);
3283                 ap->val = ckstrdup(val);
3284                 /*ap->flag = 0; - ckzalloc did it */
3285                 /*ap->next = NULL;*/
3286                 *app = ap;
3287         }
3288         INT_ON;
3289 }
3290
3291 static int
3292 unalias(const char *name)
3293 {
3294         struct alias **app;
3295
3296         app = __lookupalias(name);
3297
3298         if (*app) {
3299                 INT_OFF;
3300                 *app = freealias(*app);
3301                 INT_ON;
3302                 return 0;
3303         }
3304
3305         return 1;
3306 }
3307
3308 static void
3309 rmaliases(void)
3310 {
3311         struct alias *ap, **app;
3312         int i;
3313
3314         INT_OFF;
3315         for (i = 0; i < ATABSIZE; i++) {
3316                 app = &atab[i];
3317                 for (ap = *app; ap; ap = *app) {
3318                         *app = freealias(*app);
3319                         if (ap == *app) {
3320                                 app = &ap->next;
3321                         }
3322                 }
3323         }
3324         INT_ON;
3325 }
3326
3327 static void
3328 printalias(const struct alias *ap)
3329 {
3330         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3331 }
3332
3333 /*
3334  * TODO - sort output
3335  */
3336 static int FAST_FUNC
3337 aliascmd(int argc UNUSED_PARAM, char **argv)
3338 {
3339         char *n, *v;
3340         int ret = 0;
3341         struct alias *ap;
3342
3343         if (!argv[1]) {
3344                 int i;
3345
3346                 for (i = 0; i < ATABSIZE; i++) {
3347                         for (ap = atab[i]; ap; ap = ap->next) {
3348                                 printalias(ap);
3349                         }
3350                 }
3351                 return 0;
3352         }
3353         while ((n = *++argv) != NULL) {
3354                 v = strchr(n+1, '=');
3355                 if (v == NULL) { /* n+1: funny ksh stuff */
3356                         ap = *__lookupalias(n);
3357                         if (ap == NULL) {
3358                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3359                                 ret = 1;
3360                         } else
3361                                 printalias(ap);
3362                 } else {
3363                         *v++ = '\0';
3364                         setalias(n, v);
3365                 }
3366         }
3367
3368         return ret;
3369 }
3370
3371 static int FAST_FUNC
3372 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3373 {
3374         int i;
3375
3376         while (nextopt("a") != '\0') {
3377                 rmaliases();
3378                 return 0;
3379         }
3380         for (i = 0; *argptr; argptr++) {
3381                 if (unalias(*argptr)) {
3382                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3383                         i = 1;
3384                 }
3385         }
3386
3387         return i;
3388 }
3389
3390 #endif /* ASH_ALIAS */
3391
3392
3393 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3394 #define FORK_FG    0
3395 #define FORK_BG    1
3396 #define FORK_NOJOB 2
3397
3398 /* mode flags for showjob(s) */
3399 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3400 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3401 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3402 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3403
3404 /*
3405  * A job structure contains information about a job.  A job is either a
3406  * single process or a set of processes contained in a pipeline.  In the
3407  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3408  * array of pids.
3409  */
3410 struct procstat {
3411         pid_t   ps_pid;         /* process id */
3412         int     ps_status;      /* last process status from wait() */
3413         char    *ps_cmd;        /* text of command being run */
3414 };
3415
3416 struct job {
3417         struct procstat ps0;    /* status of process */
3418         struct procstat *ps;    /* status or processes when more than one */
3419 #if JOBS
3420         int stopstatus;         /* status of a stopped job */
3421 #endif
3422         unsigned nprocs;        /* number of processes */
3423
3424 #define JOBRUNNING      0       /* at least one proc running */
3425 #define JOBSTOPPED      1       /* all procs are stopped */
3426 #define JOBDONE         2       /* all procs are completed */
3427         unsigned
3428                 state: 8,
3429 #if JOBS
3430                 sigint: 1,      /* job was killed by SIGINT */
3431                 jobctl: 1,      /* job running under job control */
3432 #endif
3433                 waited: 1,      /* true if this entry has been waited for */
3434                 used: 1,        /* true if this entry is in used */
3435                 changed: 1;     /* true if status has changed */
3436         struct job *prev_job;   /* previous job */
3437 };
3438
3439 static struct job *makejob(/*union node *,*/ int);
3440 static int forkshell(struct job *, union node *, int);
3441 static int waitforjob(struct job *);
3442
3443 #if !JOBS
3444 enum { doing_jobctl = 0 };
3445 #define setjobctl(on) do {} while (0)
3446 #else
3447 static smallint doing_jobctl; //references:8
3448 static void setjobctl(int);
3449 #endif
3450
3451 /*
3452  * Ignore a signal.
3453  */
3454 static void
3455 ignoresig(int signo)
3456 {
3457         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3458         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3459                 /* No, need to do it */
3460                 signal(signo, SIG_IGN);
3461         }
3462         sigmode[signo - 1] = S_HARD_IGN;
3463 }
3464
3465 /*
3466  * Only one usage site - in setsignal()
3467  */
3468 static void
3469 signal_handler(int signo)
3470 {
3471         if (signo == SIGCHLD) {
3472                 got_sigchld = 1;
3473                 if (!trap[SIGCHLD])
3474                         return;
3475         }
3476
3477         gotsig[signo - 1] = 1;
3478         pending_sig = signo;
3479
3480         if (signo == SIGINT && !trap[SIGINT]) {
3481                 if (!suppress_int) {
3482                         pending_sig = 0;
3483                         raise_interrupt(); /* does not return */
3484                 }
3485                 pending_int = 1;
3486         }
3487 }
3488
3489 /*
3490  * Set the signal handler for the specified signal.  The routine figures
3491  * out what it should be set to.
3492  */
3493 static void
3494 setsignal(int signo)
3495 {
3496         char *t;
3497         char cur_act, new_act;
3498         struct sigaction act;
3499
3500         t = trap[signo];
3501         new_act = S_DFL;
3502         if (t != NULL) { /* trap for this sig is set */
3503                 new_act = S_CATCH;
3504                 if (t[0] == '\0') /* trap is "": ignore this sig */
3505                         new_act = S_IGN;
3506         }
3507
3508         if (rootshell && new_act == S_DFL) {
3509                 switch (signo) {
3510                 case SIGINT:
3511                         if (iflag || minusc || sflag == 0)
3512                                 new_act = S_CATCH;
3513                         break;
3514                 case SIGQUIT:
3515 #if DEBUG
3516                         if (debug)
3517                                 break;
3518 #endif
3519                         /* man bash:
3520                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3521                          * commands run by bash have signal handlers
3522                          * set to the values inherited by the shell
3523                          * from its parent". */
3524                         new_act = S_IGN;
3525                         break;
3526                 case SIGTERM:
3527                         if (iflag)
3528                                 new_act = S_IGN;
3529                         break;
3530 #if JOBS
3531                 case SIGTSTP:
3532                 case SIGTTOU:
3533                         if (mflag)
3534                                 new_act = S_IGN;
3535                         break;
3536 #endif
3537                 }
3538         }
3539 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3540 //whereas we have to restore it to what shell got on entry
3541 //from the parent. See comment above
3542
3543         if (signo == SIGCHLD)
3544                 new_act = S_CATCH;
3545
3546         t = &sigmode[signo - 1];
3547         cur_act = *t;
3548         if (cur_act == 0) {
3549                 /* current setting is not yet known */
3550                 if (sigaction(signo, NULL, &act)) {
3551                         /* pretend it worked; maybe we should give a warning,
3552                          * but other shells don't. We don't alter sigmode,
3553                          * so we retry every time.
3554                          * btw, in Linux it never fails. --vda */
3555                         return;
3556                 }
3557                 if (act.sa_handler == SIG_IGN) {
3558                         cur_act = S_HARD_IGN;
3559                         if (mflag
3560                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3561                         ) {
3562                                 cur_act = S_IGN;   /* don't hard ignore these */
3563                         }
3564                 }
3565         }
3566         if (cur_act == S_HARD_IGN || cur_act == new_act)
3567                 return;
3568
3569         act.sa_handler = SIG_DFL;
3570         switch (new_act) {
3571         case S_CATCH:
3572                 act.sa_handler = signal_handler;
3573                 break;
3574         case S_IGN:
3575                 act.sa_handler = SIG_IGN;
3576                 break;
3577         }
3578
3579         /* flags and mask matter only if !DFL and !IGN, but we do it
3580          * for all cases for more deterministic behavior:
3581          */
3582         act.sa_flags = 0;
3583         sigfillset(&act.sa_mask);
3584
3585         sigaction_set(signo, &act);
3586
3587         *t = new_act;
3588 }
3589
3590 /* mode flags for set_curjob */
3591 #define CUR_DELETE 2
3592 #define CUR_RUNNING 1
3593 #define CUR_STOPPED 0
3594
3595 #if JOBS
3596 /* pgrp of shell on invocation */
3597 static int initialpgrp; //references:2
3598 static int ttyfd = -1; //5
3599 #endif
3600 /* array of jobs */
3601 static struct job *jobtab; //5
3602 /* size of array */
3603 static unsigned njobs; //4
3604 /* current job */
3605 static struct job *curjob; //lots
3606 /* number of presumed living untracked jobs */
3607 static int jobless; //4
3608
3609 #if 0
3610 /* Bash has a feature: it restores termios after a successful wait for
3611  * a foreground job which had at least one stopped or sigkilled member.
3612  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3613  * properly restoring tty state. Should we do this too?
3614  * A reproducer: ^Z an interactive python:
3615  *
3616  * # python
3617  * Python 2.7.12 (...)
3618  * >>> ^Z
3619  *      { python leaves tty in -icanon -echo state. We do survive that... }
3620  *  [1]+  Stopped                    python
3621  *      { ...however, next program (python #2) does not survive it well: }
3622  * # python
3623  * Python 2.7.12 (...)
3624  * >>> Traceback (most recent call last):
3625  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3626  *   File "<stdin>", line 1, in <module>
3627  * NameError: name 'qwerty' is not defined
3628  *
3629  * The implementation below is modeled on bash code and seems to work.
3630  * However, I'm not sure we should do this. For one: what if I'd fg
3631  * the stopped python instead? It'll be confused by "restored" tty state.
3632  */
3633 static struct termios shell_tty_info;
3634 static void
3635 get_tty_state(void)
3636 {
3637         if (rootshell && ttyfd >= 0)
3638                 tcgetattr(ttyfd, &shell_tty_info);
3639 }
3640 static void
3641 set_tty_state(void)
3642 {
3643         /* if (rootshell) - caller ensures this */
3644         if (ttyfd >= 0)
3645                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3646 }
3647 static int
3648 job_signal_status(struct job *jp)
3649 {
3650         int status;
3651         unsigned i;
3652         struct procstat *ps = jp->ps;
3653         for (i = 0; i < jp->nprocs; i++) {
3654                 status = ps[i].ps_status;
3655                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3656                         return status;
3657         }
3658         return 0;
3659 }
3660 static void
3661 restore_tty_if_stopped_or_signaled(struct job *jp)
3662 {
3663 //TODO: check what happens if we come from waitforjob() in expbackq()
3664         if (rootshell) {
3665                 int s = job_signal_status(jp);
3666                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3667                         set_tty_state();
3668         }
3669 }
3670 #else
3671 # define get_tty_state() ((void)0)
3672 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3673 #endif
3674
3675 static void
3676 set_curjob(struct job *jp, unsigned mode)
3677 {
3678         struct job *jp1;
3679         struct job **jpp, **curp;
3680
3681         /* first remove from list */
3682         jpp = curp = &curjob;
3683         while (1) {
3684                 jp1 = *jpp;
3685                 if (jp1 == jp)
3686                         break;
3687                 jpp = &jp1->prev_job;
3688         }
3689         *jpp = jp1->prev_job;
3690
3691         /* Then re-insert in correct position */
3692         jpp = curp;
3693         switch (mode) {
3694         default:
3695 #if DEBUG
3696                 abort();
3697 #endif
3698         case CUR_DELETE:
3699                 /* job being deleted */
3700                 break;
3701         case CUR_RUNNING:
3702                 /* newly created job or backgrounded job,
3703                  * put after all stopped jobs.
3704                  */
3705                 while (1) {
3706                         jp1 = *jpp;
3707 #if JOBS
3708                         if (!jp1 || jp1->state != JOBSTOPPED)
3709 #endif
3710                                 break;
3711                         jpp = &jp1->prev_job;
3712                 }
3713                 /* FALLTHROUGH */
3714 #if JOBS
3715         case CUR_STOPPED:
3716 #endif
3717                 /* newly stopped job - becomes curjob */
3718                 jp->prev_job = *jpp;
3719                 *jpp = jp;
3720                 break;
3721         }
3722 }
3723
3724 #if JOBS || DEBUG
3725 static int
3726 jobno(const struct job *jp)
3727 {
3728         return jp - jobtab + 1;
3729 }
3730 #endif
3731
3732 /*
3733  * Convert a job name to a job structure.
3734  */
3735 #if !JOBS
3736 #define getjob(name, getctl) getjob(name)
3737 #endif
3738 static struct job *
3739 getjob(const char *name, int getctl)
3740 {
3741         struct job *jp;
3742         struct job *found;
3743         const char *err_msg = "%s: no such job";
3744         unsigned num;
3745         int c;
3746         const char *p;
3747         char *(*match)(const char *, const char *);
3748
3749         jp = curjob;
3750         p = name;
3751         if (!p)
3752                 goto currentjob;
3753
3754         if (*p != '%')
3755                 goto err;
3756
3757         c = *++p;
3758         if (!c)
3759                 goto currentjob;
3760
3761         if (!p[1]) {
3762                 if (c == '+' || c == '%') {
3763  currentjob:
3764                         err_msg = "No current job";
3765                         goto check;
3766                 }
3767                 if (c == '-') {
3768                         if (jp)
3769                                 jp = jp->prev_job;
3770                         err_msg = "No previous job";
3771  check:
3772                         if (!jp)
3773                                 goto err;
3774                         goto gotit;
3775                 }
3776         }
3777
3778         if (is_number(p)) {
3779                 num = atoi(p);
3780                 if (num > 0 && num <= njobs) {
3781                         jp = jobtab + num - 1;
3782                         if (jp->used)
3783                                 goto gotit;
3784                         goto err;
3785                 }
3786         }
3787
3788         match = prefix;
3789         if (*p == '?') {
3790                 match = strstr;
3791                 p++;
3792         }
3793
3794         found = NULL;
3795         while (jp) {
3796                 if (match(jp->ps[0].ps_cmd, p)) {
3797                         if (found)
3798                                 goto err;
3799                         found = jp;
3800                         err_msg = "%s: ambiguous";
3801                 }
3802                 jp = jp->prev_job;
3803         }
3804         if (!found)
3805                 goto err;
3806         jp = found;
3807
3808  gotit:
3809 #if JOBS
3810         err_msg = "job %s not created under job control";
3811         if (getctl && jp->jobctl == 0)
3812                 goto err;
3813 #endif
3814         return jp;
3815  err:
3816         ash_msg_and_raise_error(err_msg, name);
3817 }
3818
3819 /*
3820  * Mark a job structure as unused.
3821  */
3822 static void
3823 freejob(struct job *jp)
3824 {
3825         struct procstat *ps;
3826         int i;
3827
3828         INT_OFF;
3829         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3830                 if (ps->ps_cmd != nullstr)
3831                         free(ps->ps_cmd);
3832         }
3833         if (jp->ps != &jp->ps0)
3834                 free(jp->ps);
3835         jp->used = 0;
3836         set_curjob(jp, CUR_DELETE);
3837         INT_ON;
3838 }
3839
3840 #if JOBS
3841 static void
3842 xtcsetpgrp(int fd, pid_t pgrp)
3843 {
3844         if (tcsetpgrp(fd, pgrp))
3845                 ash_msg_and_raise_perror("can't set tty process group");
3846 }
3847
3848 /*
3849  * Turn job control on and off.
3850  *
3851  * Note:  This code assumes that the third arg to ioctl is a character
3852  * pointer, which is true on Berkeley systems but not System V.  Since
3853  * System V doesn't have job control yet, this isn't a problem now.
3854  *
3855  * Called with interrupts off.
3856  */
3857 static void
3858 setjobctl(int on)
3859 {
3860         int fd;
3861         int pgrp;
3862
3863         if (on == doing_jobctl || rootshell == 0)
3864                 return;
3865         if (on) {
3866                 int ofd;
3867                 ofd = fd = open(_PATH_TTY, O_RDWR);
3868                 if (fd < 0) {
3869         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3870          * That sometimes helps to acquire controlling tty.
3871          * Obviously, a workaround for bugs when someone
3872          * failed to provide a controlling tty to bash! :) */
3873                         fd = 2;
3874                         while (!isatty(fd))
3875                                 if (--fd < 0)
3876                                         goto out;
3877                 }
3878                 /* fd is a tty at this point */
3879                 fd = fcntl(fd, F_DUPFD, 10);
3880                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3881                         close(ofd);
3882                 if (fd < 0)
3883                         goto out; /* F_DUPFD failed */
3884                 close_on_exec_on(fd);
3885                 while (1) { /* while we are in the background */
3886                         pgrp = tcgetpgrp(fd);
3887                         if (pgrp < 0) {
3888  out:
3889                                 ash_msg("can't access tty; job control turned off");
3890                                 mflag = on = 0;
3891                                 goto close;
3892                         }
3893                         if (pgrp == getpgrp())
3894                                 break;
3895                         killpg(0, SIGTTIN);
3896                 }
3897                 initialpgrp = pgrp;
3898
3899                 setsignal(SIGTSTP);
3900                 setsignal(SIGTTOU);
3901                 setsignal(SIGTTIN);
3902                 pgrp = rootpid;
3903                 setpgid(0, pgrp);
3904                 xtcsetpgrp(fd, pgrp);
3905         } else {
3906                 /* turning job control off */
3907                 fd = ttyfd;
3908                 pgrp = initialpgrp;
3909                 /* was xtcsetpgrp, but this can make exiting ash
3910                  * loop forever if pty is already deleted */
3911                 tcsetpgrp(fd, pgrp);
3912                 setpgid(0, pgrp);
3913                 setsignal(SIGTSTP);
3914                 setsignal(SIGTTOU);
3915                 setsignal(SIGTTIN);
3916  close:
3917                 if (fd >= 0)
3918                         close(fd);
3919                 fd = -1;
3920         }
3921         ttyfd = fd;
3922         doing_jobctl = on;
3923 }
3924
3925 static int FAST_FUNC
3926 killcmd(int argc, char **argv)
3927 {
3928         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3929                 int i = 1;
3930                 do {
3931                         if (argv[i][0] == '%') {
3932                                 /*
3933                                  * "kill %N" - job kill
3934                                  * Converting to pgrp / pid kill
3935                                  */
3936                                 struct job *jp;
3937                                 char *dst;
3938                                 int j, n;
3939
3940                                 jp = getjob(argv[i], 0);
3941                                 /*
3942                                  * In jobs started under job control, we signal
3943                                  * entire process group by kill -PGRP_ID.
3944                                  * This happens, f.e., in interactive shell.
3945                                  *
3946                                  * Otherwise, we signal each child via
3947                                  * kill PID1 PID2 PID3.
3948                                  * Testcases:
3949                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3950                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3951                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3952                                  */
3953                                 n = jp->nprocs; /* can't be 0 (I hope) */
3954                                 if (jp->jobctl)
3955                                         n = 1;
3956                                 dst = alloca(n * sizeof(int)*4);
3957                                 argv[i] = dst;
3958                                 for (j = 0; j < n; j++) {
3959                                         struct procstat *ps = &jp->ps[j];
3960                                         /* Skip non-running and not-stopped members
3961                                          * (i.e. dead members) of the job
3962                                          */
3963                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3964                                                 continue;
3965                                         /*
3966                                          * kill_main has matching code to expect
3967                                          * leading space. Needed to not confuse
3968                                          * negative pids with "kill -SIGNAL_NO" syntax
3969                                          */
3970                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3971                                 }
3972                                 *dst = '\0';
3973                         }
3974                 } while (argv[++i]);
3975         }
3976         return kill_main(argc, argv);
3977 }
3978
3979 static void
3980 showpipe(struct job *jp /*, FILE *out*/)
3981 {
3982         struct procstat *ps;
3983         struct procstat *psend;
3984
3985         psend = jp->ps + jp->nprocs;
3986         for (ps = jp->ps + 1; ps < psend; ps++)
3987                 printf(" | %s", ps->ps_cmd);
3988         newline_and_flush(stdout);
3989         flush_stdout_stderr();
3990 }
3991
3992
3993 static int
3994 restartjob(struct job *jp, int mode)
3995 {
3996         struct procstat *ps;
3997         int i;
3998         int status;
3999         pid_t pgid;
4000
4001         INT_OFF;
4002         if (jp->state == JOBDONE)
4003                 goto out;
4004         jp->state = JOBRUNNING;
4005         pgid = jp->ps[0].ps_pid;
4006         if (mode == FORK_FG) {
4007                 get_tty_state();
4008                 xtcsetpgrp(ttyfd, pgid);
4009         }
4010         killpg(pgid, SIGCONT);
4011         ps = jp->ps;
4012         i = jp->nprocs;
4013         do {
4014                 if (WIFSTOPPED(ps->ps_status)) {
4015                         ps->ps_status = -1;
4016                 }
4017                 ps++;
4018         } while (--i);
4019  out:
4020         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4021         INT_ON;
4022         return status;
4023 }
4024
4025 static int FAST_FUNC
4026 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4027 {
4028         struct job *jp;
4029         int mode;
4030         int retval;
4031
4032         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4033         nextopt(nullstr);
4034         argv = argptr;
4035         do {
4036                 jp = getjob(*argv, 1);
4037                 if (mode == FORK_BG) {
4038                         set_curjob(jp, CUR_RUNNING);
4039                         printf("[%d] ", jobno(jp));
4040                 }
4041                 out1str(jp->ps[0].ps_cmd);
4042                 showpipe(jp /*, stdout*/);
4043                 retval = restartjob(jp, mode);
4044         } while (*argv && *++argv);
4045         return retval;
4046 }
4047 #endif
4048
4049 static int
4050 sprint_status48(char *s, int status, int sigonly)
4051 {
4052         int col;
4053         int st;
4054
4055         col = 0;
4056         if (!WIFEXITED(status)) {
4057 #if JOBS
4058                 if (WIFSTOPPED(status))
4059                         st = WSTOPSIG(status);
4060                 else
4061 #endif
4062                         st = WTERMSIG(status);
4063                 if (sigonly) {
4064                         if (st == SIGINT || st == SIGPIPE)
4065                                 goto out;
4066 #if JOBS
4067                         if (WIFSTOPPED(status))
4068                                 goto out;
4069 #endif
4070                 }
4071                 st &= 0x7f;
4072 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4073                 col = fmtstr(s, 32, strsignal(st));
4074                 if (WCOREDUMP(status)) {
4075                         strcpy(s + col, " (core dumped)");
4076                         col += sizeof(" (core dumped)")-1;
4077                 }
4078         } else if (!sigonly) {
4079                 st = WEXITSTATUS(status);
4080                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4081         }
4082  out:
4083         return col;
4084 }
4085
4086 static int
4087 wait_block_or_sig(int *status)
4088 {
4089         int pid;
4090
4091         do {
4092                 sigset_t mask;
4093
4094                 /* Poll all children for changes in their state */
4095                 got_sigchld = 0;
4096                 /* if job control is active, accept stopped processes too */
4097                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4098                 if (pid != 0)
4099                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4100
4101                 /* Children exist, but none are ready. Sleep until interesting signal */
4102 #if 1
4103                 sigfillset(&mask);
4104                 sigprocmask(SIG_SETMASK, &mask, &mask);
4105                 while (!got_sigchld && !pending_sig)
4106                         sigsuspend(&mask);
4107                 sigprocmask(SIG_SETMASK, &mask, NULL);
4108 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4109                 while (!got_sigchld && !pending_sig)
4110                         pause();
4111 #endif
4112
4113                 /* If it was SIGCHLD, poll children again */
4114         } while (got_sigchld);
4115
4116         return pid;
4117 }
4118
4119 #define DOWAIT_NONBLOCK 0
4120 #define DOWAIT_BLOCK    1
4121 #define DOWAIT_BLOCK_OR_SIG 2
4122
4123 static int
4124 dowait(int block, struct job *job)
4125 {
4126         int pid;
4127         int status;
4128         struct job *jp;
4129         struct job *thisjob = NULL;
4130
4131         TRACE(("dowait(0x%x) called\n", block));
4132
4133         /* It's wrong to call waitpid() outside of INT_OFF region:
4134          * signal can arrive just after syscall return and handler can
4135          * longjmp away, losing stop/exit notification processing.
4136          * Thus, for "jobs" builtin, and for waiting for a fg job,
4137          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4138          *
4139          * However, for "wait" builtin it is wrong to simply call waitpid()
4140          * in INT_OFF region: "wait" needs to wait for any running job
4141          * to change state, but should exit on any trap too.
4142          * In INT_OFF region, a signal just before syscall entry can set
4143          * pending_sig variables, but we can't check them, and we would
4144          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4145          *
4146          * Because of this, we run inside INT_OFF, but use a special routine
4147          * which combines waitpid() and sigsuspend().
4148          * This is the reason why we need to have a handler for SIGCHLD:
4149          * SIG_DFL handler does not wake sigsuspend().
4150          */
4151         INT_OFF;
4152         if (block == DOWAIT_BLOCK_OR_SIG) {
4153                 pid = wait_block_or_sig(&status);
4154         } else {
4155                 int wait_flags = 0;
4156                 if (block == DOWAIT_NONBLOCK)
4157                         wait_flags = WNOHANG;
4158                 /* if job control is active, accept stopped processes too */
4159                 if (doing_jobctl)
4160                         wait_flags |= WUNTRACED;
4161                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4162                 pid = waitpid(-1, &status, wait_flags);
4163         }
4164         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4165                                 pid, status, errno, strerror(errno)));
4166         if (pid <= 0)
4167                 goto out;
4168
4169         thisjob = NULL;
4170         for (jp = curjob; jp; jp = jp->prev_job) {
4171                 int jobstate;
4172                 struct procstat *ps;
4173                 struct procstat *psend;
4174                 if (jp->state == JOBDONE)
4175                         continue;
4176                 jobstate = JOBDONE;
4177                 ps = jp->ps;
4178                 psend = ps + jp->nprocs;
4179                 do {
4180                         if (ps->ps_pid == pid) {
4181                                 TRACE(("Job %d: changing status of proc %d "
4182                                         "from 0x%x to 0x%x\n",
4183                                         jobno(jp), pid, ps->ps_status, status));
4184                                 ps->ps_status = status;
4185                                 thisjob = jp;
4186                         }
4187                         if (ps->ps_status == -1)
4188                                 jobstate = JOBRUNNING;
4189 #if JOBS
4190                         if (jobstate == JOBRUNNING)
4191                                 continue;
4192                         if (WIFSTOPPED(ps->ps_status)) {
4193                                 jp->stopstatus = ps->ps_status;
4194                                 jobstate = JOBSTOPPED;
4195                         }
4196 #endif
4197                 } while (++ps < psend);
4198                 if (!thisjob)
4199                         continue;
4200
4201                 /* Found the job where one of its processes changed its state.
4202                  * Is there at least one live and running process in this job? */
4203                 if (jobstate != JOBRUNNING) {
4204                         /* No. All live processes in the job are stopped
4205                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4206                          */
4207                         thisjob->changed = 1;
4208                         if (thisjob->state != jobstate) {
4209                                 TRACE(("Job %d: changing state from %d to %d\n",
4210                                         jobno(thisjob), thisjob->state, jobstate));
4211                                 thisjob->state = jobstate;
4212 #if JOBS
4213                                 if (jobstate == JOBSTOPPED)
4214                                         set_curjob(thisjob, CUR_STOPPED);
4215 #endif
4216                         }
4217                 }
4218                 goto out;
4219         }
4220         /* The process wasn't found in job list */
4221 #if JOBS
4222         if (!WIFSTOPPED(status))
4223                 jobless--;
4224 #endif
4225  out:
4226         INT_ON;
4227
4228         if (thisjob && thisjob == job) {
4229                 char s[48 + 1];
4230                 int len;
4231
4232                 len = sprint_status48(s, status, 1);
4233                 if (len) {
4234                         s[len] = '\n';
4235                         s[len + 1] = '\0';
4236                         out2str(s);
4237                 }
4238         }
4239         return pid;
4240 }
4241
4242 #if JOBS
4243 static void
4244 showjob(struct job *jp, int mode)
4245 {
4246         struct procstat *ps;
4247         struct procstat *psend;
4248         int col;
4249         int indent_col;
4250         char s[16 + 16 + 48];
4251         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4252
4253         ps = jp->ps;
4254
4255         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4256                 /* just output process (group) id of pipeline */
4257                 fprintf(out, "%d\n", ps->ps_pid);
4258                 return;
4259         }
4260
4261         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4262         indent_col = col;
4263
4264         if (jp == curjob)
4265                 s[col - 3] = '+';
4266         else if (curjob && jp == curjob->prev_job)
4267                 s[col - 3] = '-';
4268
4269         if (mode & SHOW_PIDS)
4270                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4271
4272         psend = ps + jp->nprocs;
4273
4274         if (jp->state == JOBRUNNING) {
4275                 strcpy(s + col, "Running");
4276                 col += sizeof("Running") - 1;
4277         } else {
4278                 int status = psend[-1].ps_status;
4279                 if (jp->state == JOBSTOPPED)
4280                         status = jp->stopstatus;
4281                 col += sprint_status48(s + col, status, 0);
4282         }
4283         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4284
4285         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4286          * or prints several "PID             | <cmdN>" lines,
4287          * depending on SHOW_PIDS bit.
4288          * We do not print status of individual processes
4289          * between PID and <cmdN>. bash does it, but not very well:
4290          * first line shows overall job status, not process status,
4291          * making it impossible to know 1st process status.
4292          */
4293         goto start;
4294         do {
4295                 /* for each process */
4296                 s[0] = '\0';
4297                 col = 33;
4298                 if (mode & SHOW_PIDS)
4299                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4300  start:
4301                 fprintf(out, "%s%*c%s%s",
4302                                 s,
4303                                 33 - col >= 0 ? 33 - col : 0, ' ',
4304                                 ps == jp->ps ? "" : "| ",
4305                                 ps->ps_cmd
4306                 );
4307         } while (++ps != psend);
4308         newline_and_flush(out);
4309
4310         jp->changed = 0;
4311
4312         if (jp->state == JOBDONE) {
4313                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4314                 freejob(jp);
4315         }
4316 }
4317
4318 /*
4319  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4320  * statuses have changed since the last call to showjobs.
4321  */
4322 static void
4323 showjobs(int mode)
4324 {
4325         struct job *jp;
4326
4327         TRACE(("showjobs(0x%x) called\n", mode));
4328
4329         /* Handle all finished jobs */
4330         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4331                 continue;
4332
4333         for (jp = curjob; jp; jp = jp->prev_job) {
4334                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4335                         showjob(jp, mode);
4336                 }
4337         }
4338 }
4339
4340 static int FAST_FUNC
4341 jobscmd(int argc UNUSED_PARAM, char **argv)
4342 {
4343         int mode, m;
4344
4345         mode = 0;
4346         while ((m = nextopt("lp")) != '\0') {
4347                 if (m == 'l')
4348                         mode |= SHOW_PIDS;
4349                 else
4350                         mode |= SHOW_ONLY_PGID;
4351         }
4352
4353         argv = argptr;
4354         if (*argv) {
4355                 do
4356                         showjob(getjob(*argv, 0), mode);
4357                 while (*++argv);
4358         } else {
4359                 showjobs(mode);
4360         }
4361
4362         return 0;
4363 }
4364 #endif /* JOBS */
4365
4366 /* Called only on finished or stopped jobs (no members are running) */
4367 static int
4368 getstatus(struct job *job)
4369 {
4370         int status;
4371         int retval;
4372         struct procstat *ps;
4373
4374         /* Fetch last member's status */
4375         ps = job->ps + job->nprocs - 1;
4376         status = ps->ps_status;
4377         if (pipefail) {
4378                 /* "set -o pipefail" mode: use last _nonzero_ status */
4379                 while (status == 0 && --ps >= job->ps)
4380                         status = ps->ps_status;
4381         }
4382
4383         retval = WEXITSTATUS(status);
4384         if (!WIFEXITED(status)) {
4385 #if JOBS
4386                 retval = WSTOPSIG(status);
4387                 if (!WIFSTOPPED(status))
4388 #endif
4389                 {
4390                         /* XXX: limits number of signals */
4391                         retval = WTERMSIG(status);
4392 #if JOBS
4393                         if (retval == SIGINT)
4394                                 job->sigint = 1;
4395 #endif
4396                 }
4397                 retval += 128;
4398         }
4399         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4400                 jobno(job), job->nprocs, status, retval));
4401         return retval;
4402 }
4403
4404 static int FAST_FUNC
4405 waitcmd(int argc UNUSED_PARAM, char **argv)
4406 {
4407         struct job *job;
4408         int retval;
4409         struct job *jp;
4410
4411         nextopt(nullstr);
4412         retval = 0;
4413
4414         argv = argptr;
4415         if (!*argv) {
4416                 /* wait for all jobs */
4417                 for (;;) {
4418                         jp = curjob;
4419                         while (1) {
4420                                 if (!jp) /* no running procs */
4421                                         goto ret;
4422                                 if (jp->state == JOBRUNNING)
4423                                         break;
4424                                 jp->waited = 1;
4425                                 jp = jp->prev_job;
4426                         }
4427         /* man bash:
4428          * "When bash is waiting for an asynchronous command via
4429          * the wait builtin, the reception of a signal for which a trap
4430          * has been set will cause the wait builtin to return immediately
4431          * with an exit status greater than 128, immediately after which
4432          * the trap is executed."
4433          */
4434                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4435         /* if child sends us a signal *and immediately exits*,
4436          * dowait() returns pid > 0. Check this case,
4437          * not "if (dowait() < 0)"!
4438          */
4439                         if (pending_sig)
4440                                 goto sigout;
4441                 }
4442         }
4443
4444         retval = 127;
4445         do {
4446                 if (**argv != '%') {
4447                         pid_t pid = number(*argv);
4448                         job = curjob;
4449                         while (1) {
4450                                 if (!job)
4451                                         goto repeat;
4452                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4453                                         break;
4454                                 job = job->prev_job;
4455                         }
4456                 } else {
4457                         job = getjob(*argv, 0);
4458                 }
4459                 /* loop until process terminated or stopped */
4460                 while (job->state == JOBRUNNING) {
4461                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4462                         if (pending_sig)
4463                                 goto sigout;
4464                 }
4465                 job->waited = 1;
4466                 retval = getstatus(job);
4467  repeat: ;
4468         } while (*++argv);
4469
4470  ret:
4471         return retval;
4472  sigout:
4473         retval = 128 + pending_sig;
4474         return retval;
4475 }
4476
4477 static struct job *
4478 growjobtab(void)
4479 {
4480         size_t len;
4481         ptrdiff_t offset;
4482         struct job *jp, *jq;
4483
4484         len = njobs * sizeof(*jp);
4485         jq = jobtab;
4486         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4487
4488         offset = (char *)jp - (char *)jq;
4489         if (offset) {
4490                 /* Relocate pointers */
4491                 size_t l = len;
4492
4493                 jq = (struct job *)((char *)jq + l);
4494                 while (l) {
4495                         l -= sizeof(*jp);
4496                         jq--;
4497 #define joff(p) ((struct job *)((char *)(p) + l))
4498 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4499                         if (joff(jp)->ps == &jq->ps0)
4500                                 jmove(joff(jp)->ps);
4501                         if (joff(jp)->prev_job)
4502                                 jmove(joff(jp)->prev_job);
4503                 }
4504                 if (curjob)
4505                         jmove(curjob);
4506 #undef joff
4507 #undef jmove
4508         }
4509
4510         njobs += 4;
4511         jobtab = jp;
4512         jp = (struct job *)((char *)jp + len);
4513         jq = jp + 3;
4514         do {
4515                 jq->used = 0;
4516         } while (--jq >= jp);
4517         return jp;
4518 }
4519
4520 /*
4521  * Return a new job structure.
4522  * Called with interrupts off.
4523  */
4524 static struct job *
4525 makejob(/*union node *node,*/ int nprocs)
4526 {
4527         int i;
4528         struct job *jp;
4529
4530         for (i = njobs, jp = jobtab; ; jp++) {
4531                 if (--i < 0) {
4532                         jp = growjobtab();
4533                         break;
4534                 }
4535                 if (jp->used == 0)
4536                         break;
4537                 if (jp->state != JOBDONE || !jp->waited)
4538                         continue;
4539 #if JOBS
4540                 if (doing_jobctl)
4541                         continue;
4542 #endif
4543                 freejob(jp);
4544                 break;
4545         }
4546         memset(jp, 0, sizeof(*jp));
4547 #if JOBS
4548         /* jp->jobctl is a bitfield.
4549          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4550         if (doing_jobctl)
4551                 jp->jobctl = 1;
4552 #endif
4553         jp->prev_job = curjob;
4554         curjob = jp;
4555         jp->used = 1;
4556         jp->ps = &jp->ps0;
4557         if (nprocs > 1) {
4558                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4559         }
4560         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4561                                 jobno(jp)));
4562         return jp;
4563 }
4564
4565 #if JOBS
4566 /*
4567  * Return a string identifying a command (to be printed by the
4568  * jobs command).
4569  */
4570 static char *cmdnextc;
4571
4572 static void
4573 cmdputs(const char *s)
4574 {
4575         static const char vstype[VSTYPE + 1][3] = {
4576                 "", "}", "-", "+", "?", "=",
4577                 "%", "%%", "#", "##"
4578                 IF_BASH_SUBSTR(, ":")
4579                 IF_BASH_PATTERN_SUBST(, "/", "//")
4580         };
4581
4582         const char *p, *str;
4583         char cc[2];
4584         char *nextc;
4585         unsigned char c;
4586         unsigned char subtype = 0;
4587         int quoted = 0;
4588
4589         cc[1] = '\0';
4590         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4591         p = s;
4592         while ((c = *p++) != '\0') {
4593                 str = NULL;
4594                 switch (c) {
4595                 case CTLESC:
4596                         c = *p++;
4597                         break;
4598                 case CTLVAR:
4599                         subtype = *p++;
4600                         if ((subtype & VSTYPE) == VSLENGTH)
4601                                 str = "${#";
4602                         else
4603                                 str = "${";
4604                         goto dostr;
4605                 case CTLENDVAR:
4606                         str = "\"}" + !(quoted & 1);
4607                         quoted >>= 1;
4608                         subtype = 0;
4609                         goto dostr;
4610                 case CTLBACKQ:
4611                         str = "$(...)";
4612                         goto dostr;
4613 #if ENABLE_FEATURE_SH_MATH
4614                 case CTLARI:
4615                         str = "$((";
4616                         goto dostr;
4617                 case CTLENDARI:
4618                         str = "))";
4619                         goto dostr;
4620 #endif
4621                 case CTLQUOTEMARK:
4622                         quoted ^= 1;
4623                         c = '"';
4624                         break;
4625                 case '=':
4626                         if (subtype == 0)
4627                                 break;
4628                         if ((subtype & VSTYPE) != VSNORMAL)
4629                                 quoted <<= 1;
4630                         str = vstype[subtype & VSTYPE];
4631                         if (subtype & VSNUL)
4632                                 c = ':';
4633                         else
4634                                 goto checkstr;
4635                         break;
4636                 case '\'':
4637                 case '\\':
4638                 case '"':
4639                 case '$':
4640                         /* These can only happen inside quotes */
4641                         cc[0] = c;
4642                         str = cc;
4643                         c = '\\';
4644                         break;
4645                 default:
4646                         break;
4647                 }
4648                 USTPUTC(c, nextc);
4649  checkstr:
4650                 if (!str)
4651                         continue;
4652  dostr:
4653                 while ((c = *str++) != '\0') {
4654                         USTPUTC(c, nextc);
4655                 }
4656         } /* while *p++ not NUL */
4657
4658         if (quoted & 1) {
4659                 USTPUTC('"', nextc);
4660         }
4661         *nextc = 0;
4662         cmdnextc = nextc;
4663 }
4664
4665 /* cmdtxt() and cmdlist() call each other */
4666 static void cmdtxt(union node *n);
4667
4668 static void
4669 cmdlist(union node *np, int sep)
4670 {
4671         for (; np; np = np->narg.next) {
4672                 if (!sep)
4673                         cmdputs(" ");
4674                 cmdtxt(np);
4675                 if (sep && np->narg.next)
4676                         cmdputs(" ");
4677         }
4678 }
4679
4680 static void
4681 cmdtxt(union node *n)
4682 {
4683         union node *np;
4684         struct nodelist *lp;
4685         const char *p;
4686
4687         if (!n)
4688                 return;
4689         switch (n->type) {
4690         default:
4691 #if DEBUG
4692                 abort();
4693 #endif
4694         case NPIPE:
4695                 lp = n->npipe.cmdlist;
4696                 for (;;) {
4697                         cmdtxt(lp->n);
4698                         lp = lp->next;
4699                         if (!lp)
4700                                 break;
4701                         cmdputs(" | ");
4702                 }
4703                 break;
4704         case NSEMI:
4705                 p = "; ";
4706                 goto binop;
4707         case NAND:
4708                 p = " && ";
4709                 goto binop;
4710         case NOR:
4711                 p = " || ";
4712  binop:
4713                 cmdtxt(n->nbinary.ch1);
4714                 cmdputs(p);
4715                 n = n->nbinary.ch2;
4716                 goto donode;
4717         case NREDIR:
4718         case NBACKGND:
4719                 n = n->nredir.n;
4720                 goto donode;
4721         case NNOT:
4722                 cmdputs("!");
4723                 n = n->nnot.com;
4724  donode:
4725                 cmdtxt(n);
4726                 break;
4727         case NIF:
4728                 cmdputs("if ");
4729                 cmdtxt(n->nif.test);
4730                 cmdputs("; then ");
4731                 if (n->nif.elsepart) {
4732                         cmdtxt(n->nif.ifpart);
4733                         cmdputs("; else ");
4734                         n = n->nif.elsepart;
4735                 } else {
4736                         n = n->nif.ifpart;
4737                 }
4738                 p = "; fi";
4739                 goto dotail;
4740         case NSUBSHELL:
4741                 cmdputs("(");
4742                 n = n->nredir.n;
4743                 p = ")";
4744                 goto dotail;
4745         case NWHILE:
4746                 p = "while ";
4747                 goto until;
4748         case NUNTIL:
4749                 p = "until ";
4750  until:
4751                 cmdputs(p);
4752                 cmdtxt(n->nbinary.ch1);
4753                 n = n->nbinary.ch2;
4754                 p = "; done";
4755  dodo:
4756                 cmdputs("; do ");
4757  dotail:
4758                 cmdtxt(n);
4759                 goto dotail2;
4760         case NFOR:
4761                 cmdputs("for ");
4762                 cmdputs(n->nfor.var);
4763                 cmdputs(" in ");
4764                 cmdlist(n->nfor.args, 1);
4765                 n = n->nfor.body;
4766                 p = "; done";
4767                 goto dodo;
4768         case NDEFUN:
4769                 cmdputs(n->narg.text);
4770                 p = "() { ... }";
4771                 goto dotail2;
4772         case NCMD:
4773                 cmdlist(n->ncmd.args, 1);
4774                 cmdlist(n->ncmd.redirect, 0);
4775                 break;
4776         case NARG:
4777                 p = n->narg.text;
4778  dotail2:
4779                 cmdputs(p);
4780                 break;
4781         case NHERE:
4782         case NXHERE:
4783                 p = "<<...";
4784                 goto dotail2;
4785         case NCASE:
4786                 cmdputs("case ");
4787                 cmdputs(n->ncase.expr->narg.text);
4788                 cmdputs(" in ");
4789                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4790                         cmdtxt(np->nclist.pattern);
4791                         cmdputs(") ");
4792                         cmdtxt(np->nclist.body);
4793                         cmdputs(";; ");
4794                 }
4795                 p = "esac";
4796                 goto dotail2;
4797         case NTO:
4798                 p = ">";
4799                 goto redir;
4800         case NCLOBBER:
4801                 p = ">|";
4802                 goto redir;
4803         case NAPPEND:
4804                 p = ">>";
4805                 goto redir;
4806 #if BASH_REDIR_OUTPUT
4807         case NTO2:
4808 #endif
4809         case NTOFD:
4810                 p = ">&";
4811                 goto redir;
4812         case NFROM:
4813                 p = "<";
4814                 goto redir;
4815         case NFROMFD:
4816                 p = "<&";
4817                 goto redir;
4818         case NFROMTO:
4819                 p = "<>";
4820  redir:
4821                 cmdputs(utoa(n->nfile.fd));
4822                 cmdputs(p);
4823                 if (n->type == NTOFD || n->type == NFROMFD) {
4824                         cmdputs(utoa(n->ndup.dupfd));
4825                         break;
4826                 }
4827                 n = n->nfile.fname;
4828                 goto donode;
4829         }
4830 }
4831
4832 static char *
4833 commandtext(union node *n)
4834 {
4835         char *name;
4836
4837         STARTSTACKSTR(cmdnextc);
4838         cmdtxt(n);
4839         name = stackblock();
4840         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4841         return ckstrdup(name);
4842 }
4843 #endif /* JOBS */
4844
4845 /*
4846  * Fork off a subshell.  If we are doing job control, give the subshell its
4847  * own process group.  Jp is a job structure that the job is to be added to.
4848  * N is the command that will be evaluated by the child.  Both jp and n may
4849  * be NULL.  The mode parameter can be one of the following:
4850  *      FORK_FG - Fork off a foreground process.
4851  *      FORK_BG - Fork off a background process.
4852  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4853  *                   process group even if job control is on.
4854  *
4855  * When job control is turned off, background processes have their standard
4856  * input redirected to /dev/null (except for the second and later processes
4857  * in a pipeline).
4858  *
4859  * Called with interrupts off.
4860  */
4861 /*
4862  * Clear traps on a fork.
4863  */
4864 static void
4865 clear_traps(void)
4866 {
4867         char **tp;
4868
4869         INT_OFF;
4870         for (tp = trap; tp < &trap[NSIG]; tp++) {
4871                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4872                         if (trap_ptr == trap)
4873                                 free(*tp);
4874                         /* else: it "belongs" to trap_ptr vector, don't free */
4875                         *tp = NULL;
4876                         if ((tp - trap) != 0)
4877                                 setsignal(tp - trap);
4878                 }
4879         }
4880         may_have_traps = 0;
4881         INT_ON;
4882 }
4883
4884 /* Lives far away from here, needed for forkchild */
4885 static void closescript(void);
4886
4887 /* Called after fork(), in child */
4888 /* jp and n are NULL when called by openhere() for heredoc support */
4889 static NOINLINE void
4890 forkchild(struct job *jp, union node *n, int mode)
4891 {
4892         int oldlvl;
4893
4894         TRACE(("Child shell %d\n", getpid()));
4895         oldlvl = shlvl;
4896         shlvl++;
4897
4898         /* man bash: "Non-builtin commands run by bash have signal handlers
4899          * set to the values inherited by the shell from its parent".
4900          * Do we do it correctly? */
4901
4902         closescript();
4903
4904         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4905          && n && n->type == NCMD        /* is it single cmd? */
4906         /* && n->ncmd.args->type == NARG - always true? */
4907          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4908          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4909         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4910         ) {
4911                 TRACE(("Trap hack\n"));
4912                 /* Awful hack for `trap` or $(trap).
4913                  *
4914                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4915                  * contains an example where "trap" is executed in a subshell:
4916                  *
4917                  * save_traps=$(trap)
4918                  * ...
4919                  * eval "$save_traps"
4920                  *
4921                  * Standard does not say that "trap" in subshell shall print
4922                  * parent shell's traps. It only says that its output
4923                  * must have suitable form, but then, in the above example
4924                  * (which is not supposed to be normative), it implies that.
4925                  *
4926                  * bash (and probably other shell) does implement it
4927                  * (traps are reset to defaults, but "trap" still shows them),
4928                  * but as a result, "trap" logic is hopelessly messed up:
4929                  *
4930                  * # trap
4931                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4932                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4933                  * # true | trap   <--- trap is in subshell - no output (ditto)
4934                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4935                  * trap -- 'echo Ho' SIGWINCH
4936                  * # echo `(trap)`         <--- in subshell in subshell - output
4937                  * trap -- 'echo Ho' SIGWINCH
4938                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4939                  * trap -- 'echo Ho' SIGWINCH
4940                  *
4941                  * The rules when to forget and when to not forget traps
4942                  * get really complex and nonsensical.
4943                  *
4944                  * Our solution: ONLY bare $(trap) or `trap` is special.
4945                  */
4946                 /* Save trap handler strings for trap builtin to print */
4947                 trap_ptr = xmemdup(trap, sizeof(trap));
4948                 /* Fall through into clearing traps */
4949         }
4950         clear_traps();
4951 #if JOBS
4952         /* do job control only in root shell */
4953         doing_jobctl = 0;
4954         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4955                 pid_t pgrp;
4956
4957                 if (jp->nprocs == 0)
4958                         pgrp = getpid();
4959                 else
4960                         pgrp = jp->ps[0].ps_pid;
4961                 /* this can fail because we are doing it in the parent also */
4962                 setpgid(0, pgrp);
4963                 if (mode == FORK_FG)
4964                         xtcsetpgrp(ttyfd, pgrp);
4965                 setsignal(SIGTSTP);
4966                 setsignal(SIGTTOU);
4967         } else
4968 #endif
4969         if (mode == FORK_BG) {
4970                 /* man bash: "When job control is not in effect,
4971                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4972                 ignoresig(SIGINT);
4973                 ignoresig(SIGQUIT);
4974                 if (jp->nprocs == 0) {
4975                         close(0);
4976                         if (open(bb_dev_null, O_RDONLY) != 0)
4977                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4978                 }
4979         }
4980         if (oldlvl == 0) {
4981                 if (iflag) { /* why if iflag only? */
4982                         setsignal(SIGINT);
4983                         setsignal(SIGTERM);
4984                 }
4985                 /* man bash:
4986                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4987                  * commands run by bash have signal handlers
4988                  * set to the values inherited by the shell
4989                  * from its parent".
4990                  * Take care of the second rule: */
4991                 setsignal(SIGQUIT);
4992         }
4993 #if JOBS
4994         if (n && n->type == NCMD
4995          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4996         ) {
4997                 TRACE(("Job hack\n"));
4998                 /* "jobs": we do not want to clear job list for it,
4999                  * instead we remove only _its_ own_ job from job list.
5000                  * This makes "jobs .... | cat" more useful.
5001                  */
5002                 freejob(curjob);
5003                 return;
5004         }
5005 #endif
5006         for (jp = curjob; jp; jp = jp->prev_job)
5007                 freejob(jp);
5008         jobless = 0;
5009 }
5010
5011 /* Called after fork(), in parent */
5012 #if !JOBS
5013 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5014 #endif
5015 static void
5016 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5017 {
5018         TRACE(("In parent shell: child = %d\n", pid));
5019         if (!jp) {
5020                 /* jp is NULL when called by openhere() for heredoc support */
5021                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5022                         continue;
5023                 jobless++;
5024                 return;
5025         }
5026 #if JOBS
5027         if (mode != FORK_NOJOB && jp->jobctl) {
5028                 int pgrp;
5029
5030                 if (jp->nprocs == 0)
5031                         pgrp = pid;
5032                 else
5033                         pgrp = jp->ps[0].ps_pid;
5034                 /* This can fail because we are doing it in the child also */
5035                 setpgid(pid, pgrp);
5036         }
5037 #endif
5038         if (mode == FORK_BG) {
5039                 backgndpid = pid;               /* set $! */
5040                 set_curjob(jp, CUR_RUNNING);
5041         }
5042         if (jp) {
5043                 struct procstat *ps = &jp->ps[jp->nprocs++];
5044                 ps->ps_pid = pid;
5045                 ps->ps_status = -1;
5046                 ps->ps_cmd = nullstr;
5047 #if JOBS
5048                 if (doing_jobctl && n)
5049                         ps->ps_cmd = commandtext(n);
5050 #endif
5051         }
5052 }
5053
5054 /* jp and n are NULL when called by openhere() for heredoc support */
5055 static int
5056 forkshell(struct job *jp, union node *n, int mode)
5057 {
5058         int pid;
5059
5060         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5061         pid = fork();
5062         if (pid < 0) {
5063                 TRACE(("Fork failed, errno=%d", errno));
5064                 if (jp)
5065                         freejob(jp);
5066                 ash_msg_and_raise_error("can't fork");
5067         }
5068         if (pid == 0) {
5069                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5070                 forkchild(jp, n, mode);
5071         } else {
5072                 forkparent(jp, n, mode, pid);
5073         }
5074         return pid;
5075 }
5076
5077 /*
5078  * Wait for job to finish.
5079  *
5080  * Under job control we have the problem that while a child process
5081  * is running interrupts generated by the user are sent to the child
5082  * but not to the shell.  This means that an infinite loop started by
5083  * an interactive user may be hard to kill.  With job control turned off,
5084  * an interactive user may place an interactive program inside a loop.
5085  * If the interactive program catches interrupts, the user doesn't want
5086  * these interrupts to also abort the loop.  The approach we take here
5087  * is to have the shell ignore interrupt signals while waiting for a
5088  * foreground process to terminate, and then send itself an interrupt
5089  * signal if the child process was terminated by an interrupt signal.
5090  * Unfortunately, some programs want to do a bit of cleanup and then
5091  * exit on interrupt; unless these processes terminate themselves by
5092  * sending a signal to themselves (instead of calling exit) they will
5093  * confuse this approach.
5094  *
5095  * Called with interrupts off.
5096  */
5097 static int
5098 waitforjob(struct job *jp)
5099 {
5100         int st;
5101
5102         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5103
5104         INT_OFF;
5105         while (jp->state == JOBRUNNING) {
5106                 /* In non-interactive shells, we _can_ get
5107                  * a keyboard signal here and be EINTRed,
5108                  * but we just loop back, waiting for command to complete.
5109                  *
5110                  * man bash:
5111                  * "If bash is waiting for a command to complete and receives
5112                  * a signal for which a trap has been set, the trap
5113                  * will not be executed until the command completes."
5114                  *
5115                  * Reality is that even if trap is not set, bash
5116                  * will not act on the signal until command completes.
5117                  * Try this. sleep5intoff.c:
5118                  * #include <signal.h>
5119                  * #include <unistd.h>
5120                  * int main() {
5121                  *         sigset_t set;
5122                  *         sigemptyset(&set);
5123                  *         sigaddset(&set, SIGINT);
5124                  *         sigaddset(&set, SIGQUIT);
5125                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5126                  *         sleep(5);
5127                  *         return 0;
5128                  * }
5129                  * $ bash -c './sleep5intoff; echo hi'
5130                  * ^C^C^C^C <--- pressing ^C once a second
5131                  * $ _
5132                  * $ bash -c './sleep5intoff; echo hi'
5133                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5134                  * $ _
5135                  */
5136                 dowait(DOWAIT_BLOCK, jp);
5137         }
5138         INT_ON;
5139
5140         st = getstatus(jp);
5141 #if JOBS
5142         if (jp->jobctl) {
5143                 xtcsetpgrp(ttyfd, rootpid);
5144                 restore_tty_if_stopped_or_signaled(jp);
5145
5146                 /*
5147                  * This is truly gross.
5148                  * If we're doing job control, then we did a TIOCSPGRP which
5149                  * caused us (the shell) to no longer be in the controlling
5150                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5151                  * intuit from the subprocess exit status whether a SIGINT
5152                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5153                  */
5154                 if (jp->sigint) /* TODO: do the same with all signals */
5155                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5156         }
5157         if (jp->state == JOBDONE)
5158 #endif
5159                 freejob(jp);
5160         return st;
5161 }
5162
5163 /*
5164  * return 1 if there are stopped jobs, otherwise 0
5165  */
5166 static int
5167 stoppedjobs(void)
5168 {
5169         struct job *jp;
5170         int retval;
5171
5172         retval = 0;
5173         if (job_warning)
5174                 goto out;
5175         jp = curjob;
5176         if (jp && jp->state == JOBSTOPPED) {
5177                 out2str("You have stopped jobs.\n");
5178                 job_warning = 2;
5179                 retval++;
5180         }
5181  out:
5182         return retval;
5183 }
5184
5185
5186 /*
5187  * Code for dealing with input/output redirection.
5188  */
5189
5190 #undef EMPTY
5191 #undef CLOSED
5192 #define EMPTY -2                /* marks an unused slot in redirtab */
5193 #define CLOSED -3               /* marks a slot of previously-closed fd */
5194
5195 /*
5196  * Handle here documents.  Normally we fork off a process to write the
5197  * data to a pipe.  If the document is short, we can stuff the data in
5198  * the pipe without forking.
5199  */
5200 /* openhere needs this forward reference */
5201 static void expandhere(union node *arg, int fd);
5202 static int
5203 openhere(union node *redir)
5204 {
5205         int pip[2];
5206         size_t len = 0;
5207
5208         if (pipe(pip) < 0)
5209                 ash_msg_and_raise_error("pipe call failed");
5210         if (redir->type == NHERE) {
5211                 len = strlen(redir->nhere.doc->narg.text);
5212                 if (len <= PIPE_BUF) {
5213                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5214                         goto out;
5215                 }
5216         }
5217         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5218                 /* child */
5219                 close(pip[0]);
5220                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5221                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5222                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5223                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5224                 signal(SIGPIPE, SIG_DFL);
5225                 if (redir->type == NHERE)
5226                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5227                 else /* NXHERE */
5228                         expandhere(redir->nhere.doc, pip[1]);
5229                 _exit(EXIT_SUCCESS);
5230         }
5231  out:
5232         close(pip[1]);
5233         return pip[0];
5234 }
5235
5236 static int
5237 openredirect(union node *redir)
5238 {
5239         struct stat sb;
5240         char *fname;
5241         int f;
5242
5243         switch (redir->nfile.type) {
5244 /* Can't happen, our single caller does this itself */
5245 //      case NTOFD:
5246 //      case NFROMFD:
5247 //              return -1;
5248         case NHERE:
5249         case NXHERE:
5250                 return openhere(redir);
5251         }
5252
5253         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5254          * allocated space. Do it only when we know it is safe.
5255          */
5256         fname = redir->nfile.expfname;
5257
5258         switch (redir->nfile.type) {
5259         default:
5260 #if DEBUG
5261                 abort();
5262 #endif
5263         case NFROM:
5264                 f = open(fname, O_RDONLY);
5265                 if (f < 0)
5266                         goto eopen;
5267                 break;
5268         case NFROMTO:
5269                 f = open(fname, O_RDWR|O_CREAT, 0666);
5270                 if (f < 0)
5271                         goto ecreate;
5272                 break;
5273         case NTO:
5274 #if BASH_REDIR_OUTPUT
5275         case NTO2:
5276 #endif
5277                 /* Take care of noclobber mode. */
5278                 if (Cflag) {
5279                         if (stat(fname, &sb) < 0) {
5280                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5281                                 if (f < 0)
5282                                         goto ecreate;
5283                         } else if (!S_ISREG(sb.st_mode)) {
5284                                 f = open(fname, O_WRONLY, 0666);
5285                                 if (f < 0)
5286                                         goto ecreate;
5287                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5288                                         close(f);
5289                                         errno = EEXIST;
5290                                         goto ecreate;
5291                                 }
5292                         } else {
5293                                 errno = EEXIST;
5294                                 goto ecreate;
5295                         }
5296                         break;
5297                 }
5298                 /* FALLTHROUGH */
5299         case NCLOBBER:
5300                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5301                 if (f < 0)
5302                         goto ecreate;
5303                 break;
5304         case NAPPEND:
5305                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5306                 if (f < 0)
5307                         goto ecreate;
5308                 break;
5309         }
5310
5311         return f;
5312  ecreate:
5313         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5314  eopen:
5315         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5316 }
5317
5318 /*
5319  * Copy a file descriptor to be >= 10. Throws exception on error.
5320  */
5321 static int
5322 savefd(int from)
5323 {
5324         int newfd;
5325         int err;
5326
5327         newfd = fcntl(from, F_DUPFD, 10);
5328         err = newfd < 0 ? errno : 0;
5329         if (err != EBADF) {
5330                 if (err)
5331                         ash_msg_and_raise_perror("%d", from);
5332                 close(from);
5333                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5334         }
5335
5336         return newfd;
5337 }
5338 static int
5339 dup2_or_raise(int from, int to)
5340 {
5341         int newfd;
5342
5343         newfd = (from != to) ? dup2(from, to) : to;
5344         if (newfd < 0) {
5345                 /* Happens when source fd is not open: try "echo >&99" */
5346                 ash_msg_and_raise_perror("%d", from);
5347         }
5348         return newfd;
5349 }
5350
5351 /* Struct def and variable are moved down to the first usage site */
5352 struct two_fd_t {
5353         int orig, copy;
5354 };
5355 struct redirtab {
5356         struct redirtab *next;
5357         int pair_count;
5358         struct two_fd_t two_fd[];
5359 };
5360 #define redirlist (G_var.redirlist)
5361 enum {
5362         COPYFD_RESTORE = (int)~(INT_MAX),
5363 };
5364
5365 static int
5366 need_to_remember(struct redirtab *rp, int fd)
5367 {
5368         int i;
5369
5370         if (!rp) /* remembering was not requested */
5371                 return 0;
5372
5373         for (i = 0; i < rp->pair_count; i++) {
5374                 if (rp->two_fd[i].orig == fd) {
5375                         /* already remembered */
5376                         return 0;
5377                 }
5378         }
5379         return 1;
5380 }
5381
5382 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5383 static int
5384 is_hidden_fd(struct redirtab *rp, int fd)
5385 {
5386         int i;
5387         struct parsefile *pf;
5388
5389         if (fd == -1)
5390                 return 0;
5391         /* Check open scripts' fds */
5392         pf = g_parsefile;
5393         while (pf) {
5394                 /* We skip pf_fd == 0 case because of the following case:
5395                  * $ ash  # running ash interactively
5396                  * $ . ./script.sh
5397                  * and in script.sh: "exec 9>&0".
5398                  * Even though top-level pf_fd _is_ 0,
5399                  * it's still ok to use it: "read" builtin uses it,
5400                  * why should we cripple "exec" builtin?
5401                  */
5402                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5403                         return 1;
5404                 }
5405                 pf = pf->prev;
5406         }
5407
5408         if (!rp)
5409                 return 0;
5410         /* Check saved fds of redirects */
5411         fd |= COPYFD_RESTORE;
5412         for (i = 0; i < rp->pair_count; i++) {
5413                 if (rp->two_fd[i].copy == fd) {
5414                         return 1;
5415                 }
5416         }
5417         return 0;
5418 }
5419
5420 /*
5421  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5422  * old file descriptors are stashed away so that the redirection can be
5423  * undone by calling popredir.
5424  */
5425 /* flags passed to redirect */
5426 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5427 #define REDIR_SAVEFD2 03        /* set preverrout */
5428 static void
5429 redirect(union node *redir, int flags)
5430 {
5431         struct redirtab *sv;
5432         int sv_pos;
5433         int i;
5434         int fd;
5435         int newfd;
5436         int copied_fd2 = -1;
5437
5438         if (!redir) {
5439                 return;
5440         }
5441
5442         sv = NULL;
5443         sv_pos = 0;
5444         INT_OFF;
5445         if (flags & REDIR_PUSH) {
5446                 union node *tmp = redir;
5447                 do {
5448                         sv_pos++;
5449 #if BASH_REDIR_OUTPUT
5450                         if (tmp->nfile.type == NTO2)
5451                                 sv_pos++;
5452 #endif
5453                         tmp = tmp->nfile.next;
5454                 } while (tmp);
5455                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5456                 sv->next = redirlist;
5457                 sv->pair_count = sv_pos;
5458                 redirlist = sv;
5459                 while (sv_pos > 0) {
5460                         sv_pos--;
5461                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5462                 }
5463         }
5464
5465         do {
5466                 int right_fd = -1;
5467                 fd = redir->nfile.fd;
5468                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5469                         right_fd = redir->ndup.dupfd;
5470                         //bb_error_msg("doing %d > %d", fd, right_fd);
5471                         /* redirect from/to same file descriptor? */
5472                         if (right_fd == fd)
5473                                 continue;
5474                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5475                         if (is_hidden_fd(sv, right_fd)) {
5476                                 errno = EBADF; /* as if it is closed */
5477                                 ash_msg_and_raise_perror("%d", right_fd);
5478                         }
5479                         newfd = -1;
5480                 } else {
5481                         newfd = openredirect(redir); /* always >= 0 */
5482                         if (fd == newfd) {
5483                                 /* Descriptor wasn't open before redirect.
5484                                  * Mark it for close in the future */
5485                                 if (need_to_remember(sv, fd)) {
5486                                         goto remember_to_close;
5487                                 }
5488                                 continue;
5489                         }
5490                 }
5491 #if BASH_REDIR_OUTPUT
5492  redirect_more:
5493 #endif
5494                 if (need_to_remember(sv, fd)) {
5495                         /* Copy old descriptor */
5496                         /* Careful to not accidentally "save"
5497                          * to the same fd as right side fd in N>&M */
5498                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5499 #if defined(F_DUPFD_CLOEXEC)
5500                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5501 #else
5502                         i = fcntl(fd, F_DUPFD, minfd);
5503 #endif
5504                         if (i == -1) {
5505                                 i = errno;
5506                                 if (i != EBADF) {
5507                                         /* Strange error (e.g. "too many files" EMFILE?) */
5508                                         if (newfd >= 0)
5509                                                 close(newfd);
5510                                         errno = i;
5511                                         ash_msg_and_raise_perror("%d", fd);
5512                                         /* NOTREACHED */
5513                                 }
5514                                 /* EBADF: it is not open - good, remember to close it */
5515  remember_to_close:
5516                                 i = CLOSED;
5517                         } else { /* fd is open, save its copy */
5518 #if !defined(F_DUPFD_CLOEXEC)
5519                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5520 #endif
5521                                 /* "exec fd>&-" should not close fds
5522                                  * which point to script file(s).
5523                                  * Force them to be restored afterwards */
5524                                 if (is_hidden_fd(sv, fd))
5525                                         i |= COPYFD_RESTORE;
5526                         }
5527                         if (fd == 2)
5528                                 copied_fd2 = i;
5529                         sv->two_fd[sv_pos].orig = fd;
5530                         sv->two_fd[sv_pos].copy = i;
5531                         sv_pos++;
5532                 }
5533                 if (newfd < 0) {
5534                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5535                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5536                                 /* Don't want to trigger debugging */
5537                                 if (fd != -1)
5538                                         close(fd);
5539                         } else {
5540                                 dup2_or_raise(redir->ndup.dupfd, fd);
5541                         }
5542                 } else if (fd != newfd) { /* move newfd to fd */
5543                         dup2_or_raise(newfd, fd);
5544 #if BASH_REDIR_OUTPUT
5545                         if (!(redir->nfile.type == NTO2 && fd == 2))
5546 #endif
5547                                 close(newfd);
5548                 }
5549 #if BASH_REDIR_OUTPUT
5550                 if (redir->nfile.type == NTO2 && fd == 1) {
5551                         /* We already redirected it to fd 1, now copy it to 2 */
5552                         newfd = 1;
5553                         fd = 2;
5554                         goto redirect_more;
5555                 }
5556 #endif
5557         } while ((redir = redir->nfile.next) != NULL);
5558
5559         INT_ON;
5560         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5561                 preverrout_fd = copied_fd2;
5562 }
5563
5564 static int
5565 redirectsafe(union node *redir, int flags)
5566 {
5567         int err;
5568         volatile int saveint;
5569         struct jmploc *volatile savehandler = exception_handler;
5570         struct jmploc jmploc;
5571
5572         SAVE_INT(saveint);
5573         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5574         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5575         if (!err) {
5576                 exception_handler = &jmploc;
5577                 redirect(redir, flags);
5578         }
5579         exception_handler = savehandler;
5580         if (err && exception_type != EXERROR)
5581                 longjmp(exception_handler->loc, 1);
5582         RESTORE_INT(saveint);
5583         return err;
5584 }
5585
5586 /*
5587  * Undo the effects of the last redirection.
5588  */
5589 static void
5590 popredir(int drop, int restore)
5591 {
5592         struct redirtab *rp;
5593         int i;
5594
5595         if (redirlist == NULL)
5596                 return;
5597         INT_OFF;
5598         rp = redirlist;
5599         for (i = 0; i < rp->pair_count; i++) {
5600                 int fd = rp->two_fd[i].orig;
5601                 int copy = rp->two_fd[i].copy;
5602                 if (copy == CLOSED) {
5603                         if (!drop)
5604                                 close(fd);
5605                         continue;
5606                 }
5607                 if (copy != EMPTY) {
5608                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5609                                 copy &= ~COPYFD_RESTORE;
5610                                 /*close(fd);*/
5611                                 dup2_or_raise(copy, fd);
5612                         }
5613                         close(copy & ~COPYFD_RESTORE);
5614                 }
5615         }
5616         redirlist = rp->next;
5617         free(rp);
5618         INT_ON;
5619 }
5620
5621
5622 /* ============ Routines to expand arguments to commands
5623  *
5624  * We have to deal with backquotes, shell variables, and file metacharacters.
5625  */
5626
5627 #if ENABLE_FEATURE_SH_MATH
5628 static arith_t
5629 ash_arith(const char *s)
5630 {
5631         arith_state_t math_state;
5632         arith_t result;
5633
5634         math_state.lookupvar = lookupvar;
5635         math_state.setvar    = setvar0;
5636         //math_state.endofname = endofname;
5637
5638         INT_OFF;
5639         result = arith(&math_state, s);
5640         if (math_state.errmsg)
5641                 ash_msg_and_raise_error(math_state.errmsg);
5642         INT_ON;
5643
5644         return result;
5645 }
5646 #endif
5647
5648 /*
5649  * expandarg flags
5650  */
5651 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5652 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5653 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5654 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5655 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5656  * POSIX says for this case:
5657  *  Pathname expansion shall not be performed on the word by a
5658  *  non-interactive shell; an interactive shell may perform it, but shall
5659  *  do so only when the expansion would result in one word.
5660  * Currently, our code complies to the above rule by never globbing
5661  * redirection filenames.
5662  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5663  * (this means that on a typical Linux distro, bash almost always
5664  * performs globbing, and thus diverges from what we do).
5665  */
5666 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5667 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5668 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5669 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5670 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5671 /*
5672  * rmescape() flags
5673  */
5674 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5675 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5676 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5677 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5678 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5679
5680 /* Add CTLESC when necessary. */
5681 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5682 /* Do not skip NUL characters. */
5683 #define QUOTES_KEEPNUL EXP_TILDE
5684
5685 /*
5686  * Structure specifying which parts of the string should be searched
5687  * for IFS characters.
5688  */
5689 struct ifsregion {
5690         struct ifsregion *next; /* next region in list */
5691         int begoff;             /* offset of start of region */
5692         int endoff;             /* offset of end of region */
5693         int nulonly;            /* search for nul bytes only */
5694 };
5695
5696 struct arglist {
5697         struct strlist *list;
5698         struct strlist **lastp;
5699 };
5700
5701 /* output of current string */
5702 static char *expdest;
5703 /* list of back quote expressions */
5704 static struct nodelist *argbackq;
5705 /* first struct in list of ifs regions */
5706 static struct ifsregion ifsfirst;
5707 /* last struct in list */
5708 static struct ifsregion *ifslastp;
5709 /* holds expanded arg list */
5710 static struct arglist exparg;
5711
5712 /*
5713  * Our own itoa().
5714  * cvtnum() is used even if math support is off (to prepare $? values and such).
5715  */
5716 static int
5717 cvtnum(arith_t num)
5718 {
5719         int len;
5720
5721         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5722         len = sizeof(arith_t) * 3;
5723         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5724         if (sizeof(arith_t) < 4) len += 2;
5725
5726         expdest = makestrspace(len, expdest);
5727         len = fmtstr(expdest, len, ARITH_FMT, num);
5728         STADJUST(len, expdest);
5729         return len;
5730 }
5731
5732 /*
5733  * Break the argument string into pieces based upon IFS and add the
5734  * strings to the argument list.  The regions of the string to be
5735  * searched for IFS characters have been stored by recordregion.
5736  */
5737 static void
5738 ifsbreakup(char *string, struct arglist *arglist)
5739 {
5740         struct ifsregion *ifsp;
5741         struct strlist *sp;
5742         char *start;
5743         char *p;
5744         char *q;
5745         const char *ifs, *realifs;
5746         int ifsspc;
5747         int nulonly;
5748
5749         start = string;
5750         if (ifslastp != NULL) {
5751                 ifsspc = 0;
5752                 nulonly = 0;
5753                 realifs = ifsset() ? ifsval() : defifs;
5754                 ifsp = &ifsfirst;
5755                 do {
5756                         p = string + ifsp->begoff;
5757                         nulonly = ifsp->nulonly;
5758                         ifs = nulonly ? nullstr : realifs;
5759                         ifsspc = 0;
5760                         while (p < string + ifsp->endoff) {
5761                                 q = p;
5762                                 if ((unsigned char)*p == CTLESC)
5763                                         p++;
5764                                 if (!strchr(ifs, *p)) {
5765                                         p++;
5766                                         continue;
5767                                 }
5768                                 if (!nulonly)
5769                                         ifsspc = (strchr(defifs, *p) != NULL);
5770                                 /* Ignore IFS whitespace at start */
5771                                 if (q == start && ifsspc) {
5772                                         p++;
5773                                         start = p;
5774                                         continue;
5775                                 }
5776                                 *q = '\0';
5777                                 sp = stzalloc(sizeof(*sp));
5778                                 sp->text = start;
5779                                 *arglist->lastp = sp;
5780                                 arglist->lastp = &sp->next;
5781                                 p++;
5782                                 if (!nulonly) {
5783                                         for (;;) {
5784                                                 if (p >= string + ifsp->endoff) {
5785                                                         break;
5786                                                 }
5787                                                 q = p;
5788                                                 if ((unsigned char)*p == CTLESC)
5789                                                         p++;
5790                                                 if (strchr(ifs, *p) == NULL) {
5791                                                         p = q;
5792                                                         break;
5793                                                 }
5794                                                 if (strchr(defifs, *p) == NULL) {
5795                                                         if (ifsspc) {
5796                                                                 p++;
5797                                                                 ifsspc = 0;
5798                                                         } else {
5799                                                                 p = q;
5800                                                                 break;
5801                                                         }
5802                                                 } else
5803                                                         p++;
5804                                         }
5805                                 }
5806                                 start = p;
5807                         } /* while */
5808                         ifsp = ifsp->next;
5809                 } while (ifsp != NULL);
5810                 if (nulonly)
5811                         goto add;
5812         }
5813
5814         if (!*start)
5815                 return;
5816
5817  add:
5818         sp = stzalloc(sizeof(*sp));
5819         sp->text = start;
5820         *arglist->lastp = sp;
5821         arglist->lastp = &sp->next;
5822 }
5823
5824 static void
5825 ifsfree(void)
5826 {
5827         struct ifsregion *p = ifsfirst.next;
5828
5829         if (!p)
5830                 goto out;
5831
5832         INT_OFF;
5833         do {
5834                 struct ifsregion *ifsp;
5835                 ifsp = p->next;
5836                 free(p);
5837                 p = ifsp;
5838         } while (p);
5839         ifsfirst.next = NULL;
5840         INT_ON;
5841  out:
5842         ifslastp = NULL;
5843 }
5844
5845 static size_t
5846 esclen(const char *start, const char *p)
5847 {
5848         size_t esc = 0;
5849
5850         while (p > start && (unsigned char)*--p == CTLESC) {
5851                 esc++;
5852         }
5853         return esc;
5854 }
5855
5856 /*
5857  * Remove any CTLESC characters from a string.
5858  */
5859 static char *
5860 rmescapes(char *str, int flag)
5861 {
5862         static const char qchars[] ALIGN1 = {
5863                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5864
5865         char *p, *q, *r;
5866         unsigned inquotes;
5867         unsigned protect_against_glob;
5868         unsigned globbing;
5869         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5870
5871         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5872         if (!p)
5873                 return str;
5874
5875         q = p;
5876         r = str;
5877         if (flag & RMESCAPE_ALLOC) {
5878                 size_t len = p - str;
5879                 size_t fulllen = len + strlen(p) + 1;
5880
5881                 if (flag & RMESCAPE_GROW) {
5882                         int strloc = str - (char *)stackblock();
5883                         r = makestrspace(fulllen, expdest);
5884                         /* p and str may be invalidated by makestrspace */
5885                         str = (char *)stackblock() + strloc;
5886                         p = str + len;
5887                 } else if (flag & RMESCAPE_HEAP) {
5888                         r = ckmalloc(fulllen);
5889                 } else {
5890                         r = stalloc(fulllen);
5891                 }
5892                 q = r;
5893                 if (len > 0) {
5894                         q = (char *)mempcpy(q, str, len);
5895                 }
5896         }
5897
5898         inquotes = 0;
5899         globbing = flag & RMESCAPE_GLOB;
5900         protect_against_glob = globbing;
5901         while (*p) {
5902                 if ((unsigned char)*p == CTLQUOTEMARK) {
5903 // Note: both inquotes and protect_against_glob only affect whether
5904 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5905                         inquotes = ~inquotes;
5906                         p++;
5907                         protect_against_glob = globbing;
5908                         continue;
5909                 }
5910                 if ((unsigned char)*p == CTLESC) {
5911                         p++;
5912 #if DEBUG
5913                         if (*p == '\0')
5914                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5915 #endif
5916                         if (protect_against_glob) {
5917                                 /*
5918                                  * We used to trust glob() and fnmatch() to eat
5919                                  * superfluous escapes (\z where z has no
5920                                  * special meaning anyway). But this causes
5921                                  * bugs such as string of one greek letter rho
5922                                  * (unicode-encoded as two bytes "cf,81")
5923                                  * getting encoded as "cf,CTLESC,81"
5924                                  * and here, converted to "cf,\,81" -
5925                                  * which does not go well with some flavors
5926                                  * of fnmatch() in unicode locales
5927                                  * (for example, glibc <= 2.22).
5928                                  *
5929                                  * Lets add "\" only on the chars which need it.
5930                                  * Testcases for less obvious chars are shown.
5931                                  */
5932                                 if (*p == '*'
5933                                  || *p == '?'
5934                                  || *p == '['
5935                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5936                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5937                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5938                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5939                                 /* Some libc support [^negate], that's why "^" also needs love */
5940                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5941                                 ) {
5942                                         *q++ = '\\';
5943                                 }
5944                         }
5945                 } else if (*p == '\\' && !inquotes) {
5946                         /* naked back slash */
5947                         protect_against_glob = 0;
5948                         goto copy;
5949                 }
5950 #if BASH_PATTERN_SUBST
5951                 else if (*p == '/' && slash) {
5952                         /* stop handling globbing and mark location of slash */
5953                         globbing = slash = 0;
5954                         *p = CTLESC;
5955                 }
5956 #endif
5957                 protect_against_glob = globbing;
5958  copy:
5959                 *q++ = *p++;
5960         }
5961         *q = '\0';
5962         if (flag & RMESCAPE_GROW) {
5963                 expdest = r;
5964                 STADJUST(q - r + 1, expdest);
5965         }
5966         return r;
5967 }
5968 #define pmatch(a, b) !fnmatch((a), (b), 0)
5969
5970 /*
5971  * Prepare a pattern for a expmeta (internal glob(3)) call.
5972  *
5973  * Returns an stalloced string.
5974  */
5975 static char *
5976 preglob(const char *pattern, int flag)
5977 {
5978         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5979 }
5980
5981 /*
5982  * Put a string on the stack.
5983  */
5984 static void
5985 memtodest(const char *p, size_t len, int syntax, int quotes)
5986 {
5987         char *q;
5988
5989         if (!len)
5990                 return;
5991
5992         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5993
5994         do {
5995                 unsigned char c = *p++;
5996                 if (c) {
5997                         if (quotes & QUOTES_ESC) {
5998                                 int n = SIT(c, syntax);
5999                                 if (n == CCTL
6000                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6001                                      && n == CBACK
6002                                     )
6003                                 ) {
6004                                         USTPUTC(CTLESC, q);
6005                                 }
6006                         }
6007                 } else if (!(quotes & QUOTES_KEEPNUL))
6008                         continue;
6009                 USTPUTC(c, q);
6010         } while (--len);
6011
6012         expdest = q;
6013 }
6014
6015 static size_t
6016 strtodest(const char *p, int syntax, int quotes)
6017 {
6018         size_t len = strlen(p);
6019         memtodest(p, len, syntax, quotes);
6020         return len;
6021 }
6022
6023 /*
6024  * Record the fact that we have to scan this region of the
6025  * string for IFS characters.
6026  */
6027 static void
6028 recordregion(int start, int end, int nulonly)
6029 {
6030         struct ifsregion *ifsp;
6031
6032         if (ifslastp == NULL) {
6033                 ifsp = &ifsfirst;
6034         } else {
6035                 INT_OFF;
6036                 ifsp = ckzalloc(sizeof(*ifsp));
6037                 /*ifsp->next = NULL; - ckzalloc did it */
6038                 ifslastp->next = ifsp;
6039                 INT_ON;
6040         }
6041         ifslastp = ifsp;
6042         ifslastp->begoff = start;
6043         ifslastp->endoff = end;
6044         ifslastp->nulonly = nulonly;
6045 }
6046
6047 static void
6048 removerecordregions(int endoff)
6049 {
6050         if (ifslastp == NULL)
6051                 return;
6052
6053         if (ifsfirst.endoff > endoff) {
6054                 while (ifsfirst.next) {
6055                         struct ifsregion *ifsp;
6056                         INT_OFF;
6057                         ifsp = ifsfirst.next->next;
6058                         free(ifsfirst.next);
6059                         ifsfirst.next = ifsp;
6060                         INT_ON;
6061                 }
6062                 if (ifsfirst.begoff > endoff) {
6063                         ifslastp = NULL;
6064                 } else {
6065                         ifslastp = &ifsfirst;
6066                         ifsfirst.endoff = endoff;
6067                 }
6068                 return;
6069         }
6070
6071         ifslastp = &ifsfirst;
6072         while (ifslastp->next && ifslastp->next->begoff < endoff)
6073                 ifslastp = ifslastp->next;
6074         while (ifslastp->next) {
6075                 struct ifsregion *ifsp;
6076                 INT_OFF;
6077                 ifsp = ifslastp->next->next;
6078                 free(ifslastp->next);
6079                 ifslastp->next = ifsp;
6080                 INT_ON;
6081         }
6082         if (ifslastp->endoff > endoff)
6083                 ifslastp->endoff = endoff;
6084 }
6085
6086 static char *
6087 exptilde(char *startp, char *p, int flags)
6088 {
6089         unsigned char c;
6090         char *name;
6091         struct passwd *pw;
6092         const char *home;
6093         int quotes = flags & QUOTES_ESC;
6094
6095         name = p + 1;
6096
6097         while ((c = *++p) != '\0') {
6098                 switch (c) {
6099                 case CTLESC:
6100                         return startp;
6101                 case CTLQUOTEMARK:
6102                         return startp;
6103                 case ':':
6104                         if (flags & EXP_VARTILDE)
6105                                 goto done;
6106                         break;
6107                 case '/':
6108                 case CTLENDVAR:
6109                         goto done;
6110                 }
6111         }
6112  done:
6113         *p = '\0';
6114         if (*name == '\0') {
6115                 home = lookupvar("HOME");
6116         } else {
6117                 pw = getpwnam(name);
6118                 if (pw == NULL)
6119                         goto lose;
6120                 home = pw->pw_dir;
6121         }
6122         if (!home || !*home)
6123                 goto lose;
6124         *p = c;
6125         strtodest(home, SQSYNTAX, quotes);
6126         return p;
6127  lose:
6128         *p = c;
6129         return startp;
6130 }
6131
6132 /*
6133  * Execute a command inside back quotes.  If it's a builtin command, we
6134  * want to save its output in a block obtained from malloc.  Otherwise
6135  * we fork off a subprocess and get the output of the command via a pipe.
6136  * Should be called with interrupts off.
6137  */
6138 struct backcmd {                /* result of evalbackcmd */
6139         int fd;                 /* file descriptor to read from */
6140         int nleft;              /* number of chars in buffer */
6141         char *buf;              /* buffer */
6142         struct job *jp;         /* job structure for command */
6143 };
6144
6145 /* These forward decls are needed to use "eval" code for backticks handling: */
6146 /* flags in argument to evaltree */
6147 #define EV_EXIT    01           /* exit after evaluating tree */
6148 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6149 static int evaltree(union node *, int);
6150
6151 /* An evaltree() which is known to never return.
6152  * Used to use an alias:
6153  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6154  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6155  */
6156 static ALWAYS_INLINE NORETURN void
6157 evaltreenr(union node *n, int flags)
6158 {
6159         evaltree(n, flags);
6160         bb_unreachable(abort());
6161         /* NOTREACHED */
6162 }
6163
6164 static void FAST_FUNC
6165 evalbackcmd(union node *n, struct backcmd *result)
6166 {
6167         int pip[2];
6168         struct job *jp;
6169
6170         result->fd = -1;
6171         result->buf = NULL;
6172         result->nleft = 0;
6173         result->jp = NULL;
6174         if (n == NULL) {
6175                 goto out;
6176         }
6177
6178         if (pipe(pip) < 0)
6179                 ash_msg_and_raise_error("pipe call failed");
6180         jp = makejob(/*n,*/ 1);
6181         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6182                 /* child */
6183                 FORCE_INT_ON;
6184                 close(pip[0]);
6185                 if (pip[1] != 1) {
6186                         /*close(1);*/
6187                         dup2_or_raise(pip[1], 1);
6188                         close(pip[1]);
6189                 }
6190 /* TODO: eflag clearing makes the following not abort:
6191  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6192  * which is what bash does (unless it is in POSIX mode).
6193  * dash deleted "eflag = 0" line in the commit
6194  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6195  *  [EVAL] Don't clear eflag in evalbackcmd
6196  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6197  */
6198                 eflag = 0;
6199                 ifsfree();
6200                 evaltreenr(n, EV_EXIT);
6201                 /* NOTREACHED */
6202         }
6203         /* parent */
6204         close(pip[1]);
6205         result->fd = pip[0];
6206         result->jp = jp;
6207
6208  out:
6209         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6210                 result->fd, result->buf, result->nleft, result->jp));
6211 }
6212
6213 /*
6214  * Expand stuff in backwards quotes.
6215  */
6216 static void
6217 expbackq(union node *cmd, int flag)
6218 {
6219         struct backcmd in;
6220         int i;
6221         char buf[128];
6222         char *p;
6223         char *dest;
6224         int startloc;
6225         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6226         struct stackmark smark;
6227
6228         INT_OFF;
6229         startloc = expdest - (char *)stackblock();
6230         pushstackmark(&smark, startloc);
6231         evalbackcmd(cmd, &in);
6232         popstackmark(&smark);
6233
6234         p = in.buf;
6235         i = in.nleft;
6236         if (i == 0)
6237                 goto read;
6238         for (;;) {
6239                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6240  read:
6241                 if (in.fd < 0)
6242                         break;
6243                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6244                 TRACE(("expbackq: read returns %d\n", i));
6245                 if (i <= 0)
6246                         break;
6247                 p = buf;
6248         }
6249
6250         free(in.buf);
6251         if (in.fd >= 0) {
6252                 close(in.fd);
6253                 back_exitstatus = waitforjob(in.jp);
6254         }
6255         INT_ON;
6256
6257         /* Eat all trailing newlines */
6258         dest = expdest;
6259         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6260                 STUNPUTC(dest);
6261         expdest = dest;
6262
6263         if (!(flag & EXP_QUOTED))
6264                 recordregion(startloc, dest - (char *)stackblock(), 0);
6265         TRACE(("evalbackq: size:%d:'%.*s'\n",
6266                 (int)((dest - (char *)stackblock()) - startloc),
6267                 (int)((dest - (char *)stackblock()) - startloc),
6268                 stackblock() + startloc));
6269 }
6270
6271 #if ENABLE_FEATURE_SH_MATH
6272 /*
6273  * Expand arithmetic expression.  Backup to start of expression,
6274  * evaluate, place result in (backed up) result, adjust string position.
6275  */
6276 static void
6277 expari(int flag)
6278 {
6279         char *p, *start;
6280         int begoff;
6281         int len;
6282
6283         /* ifsfree(); */
6284
6285         /*
6286          * This routine is slightly over-complicated for
6287          * efficiency.  Next we scan backwards looking for the
6288          * start of arithmetic.
6289          */
6290         start = stackblock();
6291         p = expdest - 1;
6292         *p = '\0';
6293         p--;
6294         while (1) {
6295                 int esc;
6296
6297                 while ((unsigned char)*p != CTLARI) {
6298                         p--;
6299 #if DEBUG
6300                         if (p < start) {
6301                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6302                         }
6303 #endif
6304                 }
6305
6306                 esc = esclen(start, p);
6307                 if (!(esc % 2)) {
6308                         break;
6309                 }
6310
6311                 p -= esc + 1;
6312         }
6313
6314         begoff = p - start;
6315
6316         removerecordregions(begoff);
6317
6318         expdest = p;
6319
6320         if (flag & QUOTES_ESC)
6321                 rmescapes(p + 1, 0);
6322
6323         len = cvtnum(ash_arith(p + 1));
6324
6325         if (!(flag & EXP_QUOTED))
6326                 recordregion(begoff, begoff + len, 0);
6327 }
6328 #endif
6329
6330 /* argstr needs it */
6331 static char *evalvar(char *p, int flags);
6332
6333 /*
6334  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6335  * characters to allow for further processing.  Otherwise treat
6336  * $@ like $* since no splitting will be performed.
6337  */
6338 static void
6339 argstr(char *p, int flags)
6340 {
6341         static const char spclchars[] ALIGN1 = {
6342                 '=',
6343                 ':',
6344                 CTLQUOTEMARK,
6345                 CTLENDVAR,
6346                 CTLESC,
6347                 CTLVAR,
6348                 CTLBACKQ,
6349 #if ENABLE_FEATURE_SH_MATH
6350                 CTLENDARI,
6351 #endif
6352                 '\0'
6353         };
6354         const char *reject = spclchars;
6355         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6356         int inquotes;
6357         size_t length;
6358         int startloc;
6359
6360         if (!(flags & EXP_VARTILDE)) {
6361                 reject += 2;
6362         } else if (flags & EXP_VARTILDE2) {
6363                 reject++;
6364         }
6365         inquotes = 0;
6366         length = 0;
6367         if (flags & EXP_TILDE) {
6368                 char *q;
6369
6370                 flags &= ~EXP_TILDE;
6371  tilde:
6372                 q = p;
6373                 if (*q == '~')
6374                         p = exptilde(p, q, flags);
6375         }
6376  start:
6377         startloc = expdest - (char *)stackblock();
6378         for (;;) {
6379                 unsigned char c;
6380
6381                 length += strcspn(p + length, reject);
6382                 c = p[length];
6383                 if (c) {
6384                         if (!(c & 0x80)
6385                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6386                         ) {
6387                                 /* c == '=' || c == ':' || c == CTLENDARI */
6388                                 length++;
6389                         }
6390                 }
6391                 if (length > 0) {
6392                         int newloc;
6393                         expdest = stack_nputstr(p, length, expdest);
6394                         newloc = expdest - (char *)stackblock();
6395                         if (breakall && !inquotes && newloc > startloc) {
6396                                 recordregion(startloc, newloc, 0);
6397                         }
6398                         startloc = newloc;
6399                 }
6400                 p += length + 1;
6401                 length = 0;
6402
6403                 switch (c) {
6404                 case '\0':
6405                         goto breakloop;
6406                 case '=':
6407                         if (flags & EXP_VARTILDE2) {
6408                                 p--;
6409                                 continue;
6410                         }
6411                         flags |= EXP_VARTILDE2;
6412                         reject++;
6413                         /* fall through */
6414                 case ':':
6415                         /*
6416                          * sort of a hack - expand tildes in variable
6417                          * assignments (after the first '=' and after ':'s).
6418                          */
6419                         if (*--p == '~') {
6420                                 goto tilde;
6421                         }
6422                         continue;
6423                 }
6424
6425                 switch (c) {
6426                 case CTLENDVAR: /* ??? */
6427                         goto breakloop;
6428                 case CTLQUOTEMARK:
6429                         inquotes ^= EXP_QUOTED;
6430                         /* "$@" syntax adherence hack */
6431                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6432                                 p = evalvar(p + 1, flags | inquotes) + 1;
6433                                 goto start;
6434                         }
6435  addquote:
6436                         if (flags & QUOTES_ESC) {
6437                                 p--;
6438                                 length++;
6439                                 startloc++;
6440                         }
6441                         break;
6442                 case CTLESC:
6443                         startloc++;
6444                         length++;
6445
6446                         /*
6447                          * Quoted parameter expansion pattern: remove quote
6448                          * unless inside inner quotes or we have a literal
6449                          * backslash.
6450                          */
6451                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6452                             EXP_QPAT && *p != '\\')
6453                                 break;
6454
6455                         goto addquote;
6456                 case CTLVAR:
6457                         TRACE(("argstr: evalvar('%s')\n", p));
6458                         p = evalvar(p, flags | inquotes);
6459                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6460                         goto start;
6461                 case CTLBACKQ:
6462                         expbackq(argbackq->n, flags | inquotes);
6463                         argbackq = argbackq->next;
6464                         goto start;
6465 #if ENABLE_FEATURE_SH_MATH
6466                 case CTLENDARI:
6467                         p--;
6468                         expari(flags | inquotes);
6469                         goto start;
6470 #endif
6471                 }
6472         }
6473  breakloop: ;
6474 }
6475
6476 static char *
6477 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6478                 char *pattern, int quotes, int zero)
6479 {
6480         char *loc, *loc2;
6481         char c;
6482
6483         loc = startp;
6484         loc2 = rmesc;
6485         do {
6486                 int match;
6487                 const char *s = loc2;
6488
6489                 c = *loc2;
6490                 if (zero) {
6491                         *loc2 = '\0';
6492                         s = rmesc;
6493                 }
6494                 match = pmatch(pattern, s);
6495
6496                 *loc2 = c;
6497                 if (match)
6498                         return loc;
6499                 if (quotes && (unsigned char)*loc == CTLESC)
6500                         loc++;
6501                 loc++;
6502                 loc2++;
6503         } while (c);
6504         return NULL;
6505 }
6506
6507 static char *
6508 scanright(char *startp, char *rmesc, char *rmescend,
6509                 char *pattern, int quotes, int match_at_start)
6510 {
6511 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6512         int try2optimize = match_at_start;
6513 #endif
6514         int esc = 0;
6515         char *loc;
6516         char *loc2;
6517
6518         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6519          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6520          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6521          * Logic:
6522          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6523          * and on each iteration they go back two/one char until they reach the beginning.
6524          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6525          */
6526         /* TODO: document in what other circumstances we are called. */
6527
6528         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6529                 int match;
6530                 char c = *loc2;
6531                 const char *s = loc2;
6532                 if (match_at_start) {
6533                         *loc2 = '\0';
6534                         s = rmesc;
6535                 }
6536                 match = pmatch(pattern, s);
6537                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6538                 *loc2 = c;
6539                 if (match)
6540                         return loc;
6541 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6542                 if (try2optimize) {
6543                         /* Maybe we can optimize this:
6544                          * if pattern ends with unescaped *, we can avoid checking
6545                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6546                          * it won't match truncated "raw_value_of_" strings too.
6547                          */
6548                         unsigned plen = strlen(pattern);
6549                         /* Does it end with "*"? */
6550                         if (plen != 0 && pattern[--plen] == '*') {
6551                                 /* "xxxx*" is not escaped */
6552                                 /* "xxx\*" is escaped */
6553                                 /* "xx\\*" is not escaped */
6554                                 /* "x\\\*" is escaped */
6555                                 int slashes = 0;
6556                                 while (plen != 0 && pattern[--plen] == '\\')
6557                                         slashes++;
6558                                 if (!(slashes & 1))
6559                                         break; /* ends with unescaped "*" */
6560                         }
6561                         try2optimize = 0;
6562                 }
6563 #endif
6564                 loc--;
6565                 if (quotes) {
6566                         if (--esc < 0) {
6567                                 esc = esclen(startp, loc);
6568                         }
6569                         if (esc % 2) {
6570                                 esc--;
6571                                 loc--;
6572                         }
6573                 }
6574         }
6575         return NULL;
6576 }
6577
6578 static void varunset(const char *, const char *, const char *, int) NORETURN;
6579 static void
6580 varunset(const char *end, const char *var, const char *umsg, int varflags)
6581 {
6582         const char *msg;
6583         const char *tail;
6584
6585         tail = nullstr;
6586         msg = "parameter not set";
6587         if (umsg) {
6588                 if ((unsigned char)*end == CTLENDVAR) {
6589                         if (varflags & VSNUL)
6590                                 tail = " or null";
6591                 } else {
6592                         msg = umsg;
6593                 }
6594         }
6595         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6596 }
6597
6598 static const char *
6599 subevalvar(char *p, char *varname, int strloc, int subtype,
6600                 int startloc, int varflags, int flag)
6601 {
6602         struct nodelist *saveargbackq = argbackq;
6603         int quotes = flag & QUOTES_ESC;
6604         char *startp;
6605         char *loc;
6606         char *rmesc, *rmescend;
6607         char *str;
6608         int amount, resetloc;
6609         IF_BASH_PATTERN_SUBST(int workloc;)
6610         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6611         int zero;
6612         char *(*scan)(char*, char*, char*, char*, int, int);
6613
6614         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6615         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6616
6617         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6618                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6619         );
6620         STPUTC('\0', expdest);
6621         argbackq = saveargbackq;
6622         startp = (char *)stackblock() + startloc;
6623
6624         switch (subtype) {
6625         case VSASSIGN:
6626                 setvar0(varname, startp);
6627                 amount = startp - expdest;
6628                 STADJUST(amount, expdest);
6629                 return startp;
6630
6631         case VSQUESTION:
6632                 varunset(p, varname, startp, varflags);
6633                 /* NOTREACHED */
6634
6635 #if BASH_SUBSTR
6636         case VSSUBSTR: {
6637                 int pos, len, orig_len;
6638                 char *colon;
6639
6640                 loc = str = stackblock() + strloc;
6641
6642 # if !ENABLE_FEATURE_SH_MATH
6643 #  define ash_arith number
6644 # endif
6645                 /* Read POS in ${var:POS:LEN} */
6646                 colon = strchr(loc, ':');
6647                 if (colon) *colon = '\0';
6648                 pos = ash_arith(loc);
6649                 if (colon) *colon = ':';
6650
6651                 /* Read LEN in ${var:POS:LEN} */
6652                 len = str - startp - 1;
6653                 /* *loc != '\0', guaranteed by parser */
6654                 if (quotes) {
6655                         char *ptr;
6656
6657                         /* Adjust the length by the number of escapes */
6658                         for (ptr = startp; ptr < (str - 1); ptr++) {
6659                                 if ((unsigned char)*ptr == CTLESC) {
6660                                         len--;
6661                                         ptr++;
6662                                 }
6663                         }
6664                 }
6665                 orig_len = len;
6666                 if (*loc++ == ':') {
6667                         /* ${var::LEN} */
6668                         len = ash_arith(loc);
6669                 } else {
6670                         /* Skip POS in ${var:POS:LEN} */
6671                         len = orig_len;
6672                         while (*loc && *loc != ':') {
6673                                 loc++;
6674                         }
6675                         if (*loc++ == ':') {
6676                                 len = ash_arith(loc);
6677                         }
6678                 }
6679 #  undef ash_arith
6680
6681                 if (pos < 0) {
6682                         /* ${VAR:$((-n)):l} starts n chars from the end */
6683                         pos = orig_len + pos;
6684                 }
6685                 if ((unsigned)pos >= orig_len) {
6686                         /* apart from obvious ${VAR:999999:l},
6687                          * covers ${VAR:$((-9999999)):l} - result is ""
6688                          * (bash compat)
6689                          */
6690                         pos = 0;
6691                         len = 0;
6692                 }
6693                 if (len < 0) {
6694                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6695                         len = (orig_len - pos) + len;
6696                 }
6697                 if ((unsigned)len > (orig_len - pos))
6698                         len = orig_len - pos;
6699
6700                 for (str = startp; pos; str++, pos--) {
6701                         if (quotes && (unsigned char)*str == CTLESC)
6702                                 str++;
6703                 }
6704                 for (loc = startp; len; len--) {
6705                         if (quotes && (unsigned char)*str == CTLESC)
6706                                 *loc++ = *str++;
6707                         *loc++ = *str++;
6708                 }
6709                 *loc = '\0';
6710                 amount = loc - expdest;
6711                 STADJUST(amount, expdest);
6712                 return loc;
6713         }
6714 #endif /* BASH_SUBSTR */
6715         }
6716
6717         resetloc = expdest - (char *)stackblock();
6718
6719 #if BASH_PATTERN_SUBST
6720         /* We'll comeback here if we grow the stack while handling
6721          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6722          * stack will need rebasing, and we'll need to remove our work
6723          * areas each time
6724          */
6725  restart:
6726 #endif
6727
6728         amount = expdest - ((char *)stackblock() + resetloc);
6729         STADJUST(-amount, expdest);
6730         startp = (char *)stackblock() + startloc;
6731
6732         rmesc = startp;
6733         rmescend = (char *)stackblock() + strloc;
6734         if (quotes) {
6735                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6736                 if (rmesc != startp) {
6737                         rmescend = expdest;
6738                         startp = (char *)stackblock() + startloc;
6739                 }
6740         }
6741         rmescend--;
6742         str = (char *)stackblock() + strloc;
6743         /*
6744          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6745          * The result is a_\_z_c (not a\_\_z_c)!
6746          *
6747          * The search pattern and replace string treat backslashes differently!
6748          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6749          * and string.  It's only used on the first call.
6750          */
6751         preglob(str, IF_BASH_PATTERN_SUBST(
6752                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6753                         RMESCAPE_SLASH : ) 0);
6754
6755 #if BASH_PATTERN_SUBST
6756         workloc = expdest - (char *)stackblock();
6757         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6758                 int len;
6759                 char *idx, *end;
6760
6761                 if (!repl) {
6762                         repl = strchr(str, CTLESC);
6763                         if (repl)
6764                                 *repl++ = '\0';
6765                         else
6766                                 repl = nullstr;
6767                 }
6768                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6769
6770                 /* If there's no pattern to match, return the expansion unmolested */
6771                 if (str[0] == '\0')
6772                         return NULL;
6773
6774                 len = 0;
6775                 idx = startp;
6776                 end = str - 1;
6777                 while (idx < end) {
6778  try_to_match:
6779                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6780                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6781                         if (!loc) {
6782                                 /* No match, advance */
6783                                 char *restart_detect = stackblock();
6784  skip_matching:
6785                                 STPUTC(*idx, expdest);
6786                                 if (quotes && (unsigned char)*idx == CTLESC) {
6787                                         idx++;
6788                                         len++;
6789                                         STPUTC(*idx, expdest);
6790                                 }
6791                                 if (stackblock() != restart_detect)
6792                                         goto restart;
6793                                 idx++;
6794                                 len++;
6795                                 rmesc++;
6796                                 /* continue; - prone to quadratic behavior, smarter code: */
6797                                 if (idx >= end)
6798                                         break;
6799                                 if (str[0] == '*') {
6800                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6801                                          * it would never match "ong_string" etc, no point in trying.
6802                                          */
6803                                         goto skip_matching;
6804                                 }
6805                                 goto try_to_match;
6806                         }
6807
6808                         if (subtype == VSREPLACEALL) {
6809                                 while (idx < loc) {
6810                                         if (quotes && (unsigned char)*idx == CTLESC)
6811                                                 idx++;
6812                                         idx++;
6813                                         rmesc++;
6814                                 }
6815                         } else {
6816                                 idx = loc;
6817                         }
6818
6819                         //bb_error_msg("repl:'%s'", repl);
6820                         for (loc = (char*)repl; *loc; loc++) {
6821                                 char *restart_detect = stackblock();
6822                                 if (quotes && *loc == '\\') {
6823                                         STPUTC(CTLESC, expdest);
6824                                         len++;
6825                                 }
6826                                 STPUTC(*loc, expdest);
6827                                 if (stackblock() != restart_detect)
6828                                         goto restart;
6829                                 len++;
6830                         }
6831
6832                         if (subtype == VSREPLACE) {
6833                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6834                                 while (*idx) {
6835                                         char *restart_detect = stackblock();
6836                                         STPUTC(*idx, expdest);
6837                                         if (stackblock() != restart_detect)
6838                                                 goto restart;
6839                                         len++;
6840                                         idx++;
6841                                 }
6842                                 break;
6843                         }
6844                 }
6845
6846                 /* We've put the replaced text into a buffer at workloc, now
6847                  * move it to the right place and adjust the stack.
6848                  */
6849                 STPUTC('\0', expdest);
6850                 startp = (char *)stackblock() + startloc;
6851                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6852                 //bb_error_msg("startp:'%s'", startp);
6853                 amount = expdest - (startp + len);
6854                 STADJUST(-amount, expdest);
6855                 return startp;
6856         }
6857 #endif /* BASH_PATTERN_SUBST */
6858
6859         subtype -= VSTRIMRIGHT;
6860 #if DEBUG
6861         if (subtype < 0 || subtype > 7)
6862                 abort();
6863 #endif
6864         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6865         zero = subtype >> 1;
6866         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6867         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6868
6869         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6870         if (loc) {
6871                 if (zero) {
6872                         memmove(startp, loc, str - loc);
6873                         loc = startp + (str - loc) - 1;
6874                 }
6875                 *loc = '\0';
6876                 amount = loc - expdest;
6877                 STADJUST(amount, expdest);
6878         }
6879         return loc;
6880 }
6881
6882 /*
6883  * Add the value of a specialized variable to the stack string.
6884  * name parameter (examples):
6885  * ash -c 'echo $1'      name:'1='
6886  * ash -c 'echo $qwe'    name:'qwe='
6887  * ash -c 'echo $$'      name:'$='
6888  * ash -c 'echo ${$}'    name:'$='
6889  * ash -c 'echo ${$##q}' name:'$=q'
6890  * ash -c 'echo ${#$}'   name:'$='
6891  * note: examples with bad shell syntax:
6892  * ash -c 'echo ${#$1}'  name:'$=1'
6893  * ash -c 'echo ${#1#}'  name:'1=#'
6894  */
6895 static NOINLINE ssize_t
6896 varvalue(char *name, int varflags, int flags, int *quotedp)
6897 {
6898         const char *p;
6899         int num;
6900         int i;
6901         ssize_t len = 0;
6902         int sep;
6903         int quoted = *quotedp;
6904         int subtype = varflags & VSTYPE;
6905         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6906         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6907         int syntax;
6908
6909         sep = (flags & EXP_FULL) << CHAR_BIT;
6910         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6911
6912         switch (*name) {
6913         case '$':
6914                 num = rootpid;
6915                 goto numvar;
6916         case '?':
6917                 num = exitstatus;
6918                 goto numvar;
6919         case '#':
6920                 num = shellparam.nparam;
6921                 goto numvar;
6922         case '!':
6923                 num = backgndpid;
6924                 if (num == 0)
6925                         return -1;
6926  numvar:
6927                 len = cvtnum(num);
6928                 goto check_1char_name;
6929         case '-':
6930                 expdest = makestrspace(NOPTS, expdest);
6931                 for (i = NOPTS - 1; i >= 0; i--) {
6932                         if (optlist[i]) {
6933                                 USTPUTC(optletters(i), expdest);
6934                                 len++;
6935                         }
6936                 }
6937  check_1char_name:
6938 #if 0
6939                 /* handles cases similar to ${#$1} */
6940                 if (name[2] != '\0')
6941                         raise_error_syntax("bad substitution");
6942 #endif
6943                 break;
6944         case '@':
6945                 if (quoted && sep)
6946                         goto param;
6947                 /* fall through */
6948         case '*': {
6949                 char **ap;
6950                 char sepc;
6951
6952                 if (quoted)
6953                         sep = 0;
6954                 sep |= ifsset() ? ifsval()[0] : ' ';
6955  param:
6956                 sepc = sep;
6957                 *quotedp = !sepc;
6958                 ap = shellparam.p;
6959                 if (!ap)
6960                         return -1;
6961                 while ((p = *ap++) != NULL) {
6962                         len += strtodest(p, syntax, quotes);
6963
6964                         if (*ap && sep) {
6965                                 len++;
6966                                 memtodest(&sepc, 1, syntax, quotes);
6967                         }
6968                 }
6969                 break;
6970         } /* case '*' */
6971         case '0':
6972         case '1':
6973         case '2':
6974         case '3':
6975         case '4':
6976         case '5':
6977         case '6':
6978         case '7':
6979         case '8':
6980         case '9':
6981                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6982                 if (num < 0 || num > shellparam.nparam)
6983                         return -1;
6984                 p = num ? shellparam.p[num - 1] : arg0;
6985                 goto value;
6986         default:
6987                 /* NB: name has form "VAR=..." */
6988                 p = lookupvar(name);
6989  value:
6990                 if (!p)
6991                         return -1;
6992
6993                 len = strtodest(p, syntax, quotes);
6994 #if ENABLE_UNICODE_SUPPORT
6995                 if (subtype == VSLENGTH && len > 0) {
6996                         reinit_unicode_for_ash();
6997                         if (unicode_status == UNICODE_ON) {
6998                                 STADJUST(-len, expdest);
6999                                 discard = 0;
7000                                 len = unicode_strlen(p);
7001                         }
7002                 }
7003 #endif
7004                 break;
7005         }
7006
7007         if (discard)
7008                 STADJUST(-len, expdest);
7009         return len;
7010 }
7011
7012 /*
7013  * Expand a variable, and return a pointer to the next character in the
7014  * input string.
7015  */
7016 static char *
7017 evalvar(char *p, int flag)
7018 {
7019         char varflags;
7020         char subtype;
7021         int quoted;
7022         char easy;
7023         char *var;
7024         int patloc;
7025         int startloc;
7026         ssize_t varlen;
7027
7028         varflags = (unsigned char) *p++;
7029         subtype = varflags & VSTYPE;
7030
7031         if (!subtype)
7032                 raise_error_syntax("bad substitution");
7033
7034         quoted = flag & EXP_QUOTED;
7035         var = p;
7036         easy = (!quoted || (*var == '@' && shellparam.nparam));
7037         startloc = expdest - (char *)stackblock();
7038         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7039
7040  again:
7041         varlen = varvalue(var, varflags, flag, &quoted);
7042         if (varflags & VSNUL)
7043                 varlen--;
7044
7045         if (subtype == VSPLUS) {
7046                 varlen = -1 - varlen;
7047                 goto vsplus;
7048         }
7049
7050         if (subtype == VSMINUS) {
7051  vsplus:
7052                 if (varlen < 0) {
7053                         argstr(
7054                                 p,
7055                                 flag | EXP_TILDE | EXP_WORD
7056                         );
7057                         goto end;
7058                 }
7059                 goto record;
7060         }
7061
7062         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7063                 if (varlen >= 0)
7064                         goto record;
7065
7066                 subevalvar(p, var, 0, subtype, startloc, varflags,
7067                            flag & ~QUOTES_ESC);
7068                 varflags &= ~VSNUL;
7069                 /*
7070                  * Remove any recorded regions beyond
7071                  * start of variable
7072                  */
7073                 removerecordregions(startloc);
7074                 goto again;
7075         }
7076
7077         if (varlen < 0 && uflag)
7078                 varunset(p, var, 0, 0);
7079
7080         if (subtype == VSLENGTH) {
7081                 cvtnum(varlen > 0 ? varlen : 0);
7082                 goto record;
7083         }
7084
7085         if (subtype == VSNORMAL) {
7086  record:
7087                 if (!easy)
7088                         goto end;
7089                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7090                 goto end;
7091         }
7092
7093 #if DEBUG
7094         switch (subtype) {
7095         case VSTRIMLEFT:
7096         case VSTRIMLEFTMAX:
7097         case VSTRIMRIGHT:
7098         case VSTRIMRIGHTMAX:
7099 #if BASH_SUBSTR
7100         case VSSUBSTR:
7101 #endif
7102 #if BASH_PATTERN_SUBST
7103         case VSREPLACE:
7104         case VSREPLACEALL:
7105 #endif
7106                 break;
7107         default:
7108                 abort();
7109         }
7110 #endif
7111
7112         if (varlen >= 0) {
7113                 /*
7114                  * Terminate the string and start recording the pattern
7115                  * right after it
7116                  */
7117                 STPUTC('\0', expdest);
7118                 patloc = expdest - (char *)stackblock();
7119                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7120                                 startloc, varflags, flag)) {
7121                         int amount = expdest - (
7122                                 (char *)stackblock() + patloc - 1
7123                         );
7124                         STADJUST(-amount, expdest);
7125                 }
7126                 /* Remove any recorded regions beyond start of variable */
7127                 removerecordregions(startloc);
7128                 goto record;
7129         }
7130
7131  end:
7132         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7133                 int nesting = 1;
7134                 for (;;) {
7135                         unsigned char c = *p++;
7136                         if (c == CTLESC)
7137                                 p++;
7138                         else if (c == CTLBACKQ) {
7139                                 if (varlen >= 0)
7140                                         argbackq = argbackq->next;
7141                         } else if (c == CTLVAR) {
7142                                 if ((*p++ & VSTYPE) != VSNORMAL)
7143                                         nesting++;
7144                         } else if (c == CTLENDVAR) {
7145                                 if (--nesting == 0)
7146                                         break;
7147                         }
7148                 }
7149         }
7150         return p;
7151 }
7152
7153 /*
7154  * Add a file name to the list.
7155  */
7156 static void
7157 addfname(const char *name)
7158 {
7159         struct strlist *sp;
7160
7161         sp = stzalloc(sizeof(*sp));
7162         sp->text = sstrdup(name);
7163         *exparg.lastp = sp;
7164         exparg.lastp = &sp->next;
7165 }
7166
7167 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7168 static int
7169 hasmeta(const char *p)
7170 {
7171         static const char chars[] ALIGN1 = {
7172                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7173         };
7174
7175         for (;;) {
7176                 p = strpbrk(p, chars);
7177                 if (!p)
7178                         break;
7179                 switch ((unsigned char) *p) {
7180                 case CTLQUOTEMARK:
7181                         for (;;) {
7182                                 p++;
7183                                 if (*p == CTLQUOTEMARK)
7184                                         break;
7185                                 if (*p == CTLESC)
7186                                         p++;
7187                                 if (*p == '\0') /* huh? */
7188                                         return 0;
7189                         }
7190                         break;
7191                 case '\\':
7192                 case CTLESC:
7193                         p++;
7194                         if (*p == '\0')
7195                                 return 0;
7196                         break;
7197                 case '[':
7198                         if (!strchr(p + 1, ']')) {
7199                                 /* It's not a properly closed [] pattern,
7200                                  * but other metas may follow. Continue checking.
7201                                  * my[file* _is_ globbed by bash
7202                                  * and matches filenames like "my[file1".
7203                                  */
7204                                 break;
7205                         }
7206                         /* fallthrough */
7207                 default:
7208                 /* case '*': */
7209                 /* case '?': */
7210                         return 1;
7211                 }
7212                 p++;
7213         }
7214
7215         return 0;
7216 }
7217
7218 /* If we want to use glob() from libc... */
7219 #if !ENABLE_ASH_INTERNAL_GLOB
7220
7221 /* Add the result of glob() to the list */
7222 static void
7223 addglob(const glob_t *pglob)
7224 {
7225         char **p = pglob->gl_pathv;
7226
7227         do {
7228                 addfname(*p);
7229         } while (*++p);
7230 }
7231 static void
7232 expandmeta(struct strlist *str /*, int flag*/)
7233 {
7234         /* TODO - EXP_REDIR */
7235
7236         while (str) {
7237                 char *p;
7238                 glob_t pglob;
7239                 int i;
7240
7241                 if (fflag)
7242                         goto nometa;
7243
7244                 if (!hasmeta(str->text))
7245                         goto nometa;
7246
7247                 INT_OFF;
7248                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7249 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7250 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7251 //
7252 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7253 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7254 // Which means you need to unescape the string, right? Not so fast:
7255 // if there _is_ a file named "file\?" (with backslash), it is returned
7256 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7257 // You DON'T KNOW by looking at the result whether you need to unescape it.
7258 //
7259 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7260 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7261 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7262 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7263 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7264 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7265                 i = glob(p, 0, NULL, &pglob);
7266                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7267                 if (p != str->text)
7268                         free(p);
7269                 switch (i) {
7270                 case 0:
7271 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7272                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7273                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7274                                 goto nometa2;
7275 #endif
7276                         addglob(&pglob);
7277                         globfree(&pglob);
7278                         INT_ON;
7279                         break;
7280                 case GLOB_NOMATCH:
7281  //nometa2:
7282                         globfree(&pglob);
7283                         INT_ON;
7284  nometa:
7285                         *exparg.lastp = str;
7286                         rmescapes(str->text, 0);
7287                         exparg.lastp = &str->next;
7288                         break;
7289                 default:        /* GLOB_NOSPACE */
7290                         globfree(&pglob);
7291                         INT_ON;
7292                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7293                 }
7294                 str = str->next;
7295         }
7296 }
7297
7298 #else
7299 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7300
7301 /*
7302  * Do metacharacter (i.e. *, ?, [...]) expansion.
7303  */
7304 static void
7305 expmeta(char *expdir, char *enddir, char *name)
7306 {
7307         char *p;
7308         const char *cp;
7309         char *start;
7310         char *endname;
7311         int metaflag;
7312         struct stat statb;
7313         DIR *dirp;
7314         struct dirent *dp;
7315         int atend;
7316         int matchdot;
7317         int esc;
7318
7319         metaflag = 0;
7320         start = name;
7321         for (p = name; esc = 0, *p; p += esc + 1) {
7322                 if (*p == '*' || *p == '?')
7323                         metaflag = 1;
7324                 else if (*p == '[') {
7325                         char *q = p + 1;
7326                         if (*q == '!')
7327                                 q++;
7328                         for (;;) {
7329                                 if (*q == '\\')
7330                                         q++;
7331                                 if (*q == '/' || *q == '\0')
7332                                         break;
7333                                 if (*++q == ']') {
7334                                         metaflag = 1;
7335                                         break;
7336                                 }
7337                         }
7338                 } else {
7339                         if (*p == '\\')
7340                                 esc++;
7341                         if (p[esc] == '/') {
7342                                 if (metaflag)
7343                                         break;
7344                                 start = p + esc + 1;
7345                         }
7346                 }
7347         }
7348         if (metaflag == 0) {    /* we've reached the end of the file name */
7349                 if (enddir != expdir)
7350                         metaflag++;
7351                 p = name;
7352                 do {
7353                         if (*p == '\\')
7354                                 p++;
7355                         *enddir++ = *p;
7356                 } while (*p++);
7357                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7358                         addfname(expdir);
7359                 return;
7360         }
7361         endname = p;
7362         if (name < start) {
7363                 p = name;
7364                 do {
7365                         if (*p == '\\')
7366                                 p++;
7367                         *enddir++ = *p++;
7368                 } while (p < start);
7369         }
7370         if (enddir == expdir) {
7371                 cp = ".";
7372         } else if (enddir == expdir + 1 && *expdir == '/') {
7373                 cp = "/";
7374         } else {
7375                 cp = expdir;
7376                 enddir[-1] = '\0';
7377         }
7378         dirp = opendir(cp);
7379         if (dirp == NULL)
7380                 return;
7381         if (enddir != expdir)
7382                 enddir[-1] = '/';
7383         if (*endname == 0) {
7384                 atend = 1;
7385         } else {
7386                 atend = 0;
7387                 *endname = '\0';
7388                 endname += esc + 1;
7389         }
7390         matchdot = 0;
7391         p = start;
7392         if (*p == '\\')
7393                 p++;
7394         if (*p == '.')
7395                 matchdot++;
7396         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7397                 if (dp->d_name[0] == '.' && !matchdot)
7398                         continue;
7399                 if (pmatch(start, dp->d_name)) {
7400                         if (atend) {
7401                                 strcpy(enddir, dp->d_name);
7402                                 addfname(expdir);
7403                         } else {
7404                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7405                                         continue;
7406                                 p[-1] = '/';
7407                                 expmeta(expdir, p, endname);
7408                         }
7409                 }
7410         }
7411         closedir(dirp);
7412         if (!atend)
7413                 endname[-esc - 1] = esc ? '\\' : '/';
7414 }
7415
7416 static struct strlist *
7417 msort(struct strlist *list, int len)
7418 {
7419         struct strlist *p, *q = NULL;
7420         struct strlist **lpp;
7421         int half;
7422         int n;
7423
7424         if (len <= 1)
7425                 return list;
7426         half = len >> 1;
7427         p = list;
7428         for (n = half; --n >= 0;) {
7429                 q = p;
7430                 p = p->next;
7431         }
7432         q->next = NULL;                 /* terminate first half of list */
7433         q = msort(list, half);          /* sort first half of list */
7434         p = msort(p, len - half);               /* sort second half */
7435         lpp = &list;
7436         for (;;) {
7437 #if ENABLE_LOCALE_SUPPORT
7438                 if (strcoll(p->text, q->text) < 0)
7439 #else
7440                 if (strcmp(p->text, q->text) < 0)
7441 #endif
7442                                                 {
7443                         *lpp = p;
7444                         lpp = &p->next;
7445                         p = *lpp;
7446                         if (p == NULL) {
7447                                 *lpp = q;
7448                                 break;
7449                         }
7450                 } else {
7451                         *lpp = q;
7452                         lpp = &q->next;
7453                         q = *lpp;
7454                         if (q == NULL) {
7455                                 *lpp = p;
7456                                 break;
7457                         }
7458                 }
7459         }
7460         return list;
7461 }
7462
7463 /*
7464  * Sort the results of file name expansion.  It calculates the number of
7465  * strings to sort and then calls msort (short for merge sort) to do the
7466  * work.
7467  */
7468 static struct strlist *
7469 expsort(struct strlist *str)
7470 {
7471         int len;
7472         struct strlist *sp;
7473
7474         len = 0;
7475         for (sp = str; sp; sp = sp->next)
7476                 len++;
7477         return msort(str, len);
7478 }
7479
7480 static void
7481 expandmeta(struct strlist *str /*, int flag*/)
7482 {
7483         /* TODO - EXP_REDIR */
7484
7485         while (str) {
7486                 char *expdir;
7487                 struct strlist **savelastp;
7488                 struct strlist *sp;
7489                 char *p;
7490
7491                 if (fflag)
7492                         goto nometa;
7493                 if (!hasmeta(str->text))
7494                         goto nometa;
7495                 savelastp = exparg.lastp;
7496
7497                 INT_OFF;
7498                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7499                 {
7500                         int i = strlen(str->text);
7501 //BUGGY estimation of how long expanded name can be
7502                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7503                 }
7504                 expmeta(expdir, expdir, p);
7505                 free(expdir);
7506                 if (p != str->text)
7507                         free(p);
7508                 INT_ON;
7509                 if (exparg.lastp == savelastp) {
7510                         /*
7511                          * no matches
7512                          */
7513  nometa:
7514                         *exparg.lastp = str;
7515                         rmescapes(str->text, 0);
7516                         exparg.lastp = &str->next;
7517                 } else {
7518                         *exparg.lastp = NULL;
7519                         *savelastp = sp = expsort(*savelastp);
7520                         while (sp->next != NULL)
7521                                 sp = sp->next;
7522                         exparg.lastp = &sp->next;
7523                 }
7524                 str = str->next;
7525         }
7526 }
7527 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7528
7529 /*
7530  * Perform variable substitution and command substitution on an argument,
7531  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7532  * perform splitting and file name expansion.  When arglist is NULL, perform
7533  * here document expansion.
7534  */
7535 static void
7536 expandarg(union node *arg, struct arglist *arglist, int flag)
7537 {
7538         struct strlist *sp;
7539         char *p;
7540
7541         argbackq = arg->narg.backquote;
7542         STARTSTACKSTR(expdest);
7543         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7544         argstr(arg->narg.text, flag);
7545         p = _STPUTC('\0', expdest);
7546         expdest = p - 1;
7547         if (arglist == NULL) {
7548                 /* here document expanded */
7549                 goto out;
7550         }
7551         p = grabstackstr(p);
7552         TRACE(("expandarg: p:'%s'\n", p));
7553         exparg.lastp = &exparg.list;
7554         /*
7555          * TODO - EXP_REDIR
7556          */
7557         if (flag & EXP_FULL) {
7558                 ifsbreakup(p, &exparg);
7559                 *exparg.lastp = NULL;
7560                 exparg.lastp = &exparg.list;
7561                 expandmeta(exparg.list /*, flag*/);
7562         } else {
7563                 sp = stzalloc(sizeof(*sp));
7564                 sp->text = p;
7565                 *exparg.lastp = sp;
7566                 exparg.lastp = &sp->next;
7567         }
7568         *exparg.lastp = NULL;
7569         if (exparg.list) {
7570                 *arglist->lastp = exparg.list;
7571                 arglist->lastp = exparg.lastp;
7572         }
7573
7574  out:
7575         ifsfree();
7576 }
7577
7578 /*
7579  * Expand shell variables and backquotes inside a here document.
7580  */
7581 static void
7582 expandhere(union node *arg, int fd)
7583 {
7584         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7585         full_write(fd, stackblock(), expdest - (char *)stackblock());
7586 }
7587
7588 /*
7589  * Returns true if the pattern matches the string.
7590  */
7591 static int
7592 patmatch(char *pattern, const char *string)
7593 {
7594         char *p = preglob(pattern, 0);
7595         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7596         return pmatch(p, string);
7597 }
7598
7599 /*
7600  * See if a pattern matches in a case statement.
7601  */
7602 static int
7603 casematch(union node *pattern, char *val)
7604 {
7605         struct stackmark smark;
7606         int result;
7607
7608         setstackmark(&smark);
7609         argbackq = pattern->narg.backquote;
7610         STARTSTACKSTR(expdest);
7611         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7612         STACKSTRNUL(expdest);
7613         ifsfree();
7614         result = patmatch(stackblock(), val);
7615         popstackmark(&smark);
7616         return result;
7617 }
7618
7619
7620 /* ============ find_command */
7621
7622 struct builtincmd {
7623         const char *name;
7624         int (*builtin)(int, char **) FAST_FUNC;
7625         /* unsigned flags; */
7626 };
7627 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7628 /* "regular" builtins always take precedence over commands,
7629  * regardless of PATH=....%builtin... position */
7630 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7631 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7632
7633 struct cmdentry {
7634         smallint cmdtype;       /* CMDxxx */
7635         union param {
7636                 int index;
7637                 /* index >= 0 for commands without path (slashes) */
7638                 /* (TODO: what exactly does the value mean? PATH position?) */
7639                 /* index == -1 for commands with slashes */
7640                 /* index == (-2 - applet_no) for NOFORK applets */
7641                 const struct builtincmd *cmd;
7642                 struct funcnode *func;
7643         } u;
7644 };
7645 /* values of cmdtype */
7646 #define CMDUNKNOWN      -1      /* no entry in table for command */
7647 #define CMDNORMAL       0       /* command is an executable program */
7648 #define CMDFUNCTION     1       /* command is a shell function */
7649 #define CMDBUILTIN      2       /* command is a shell builtin */
7650
7651 /* action to find_command() */
7652 #define DO_ERR          0x01    /* prints errors */
7653 #define DO_ABS          0x02    /* checks absolute paths */
7654 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7655 #define DO_ALTPATH      0x08    /* using alternate path */
7656 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7657
7658 static void find_command(char *, struct cmdentry *, int, const char *);
7659
7660
7661 /* ============ Hashing commands */
7662
7663 /*
7664  * When commands are first encountered, they are entered in a hash table.
7665  * This ensures that a full path search will not have to be done for them
7666  * on each invocation.
7667  *
7668  * We should investigate converting to a linear search, even though that
7669  * would make the command name "hash" a misnomer.
7670  */
7671
7672 struct tblentry {
7673         struct tblentry *next;  /* next entry in hash chain */
7674         union param param;      /* definition of builtin function */
7675         smallint cmdtype;       /* CMDxxx */
7676         char rehash;            /* if set, cd done since entry created */
7677         char cmdname[1];        /* name of command */
7678 };
7679
7680 static struct tblentry **cmdtable;
7681 #define INIT_G_cmdtable() do { \
7682         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7683 } while (0)
7684
7685 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7686
7687
7688 static void
7689 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7690 {
7691 #if ENABLE_FEATURE_SH_STANDALONE
7692         if (applet_no >= 0) {
7693                 if (APPLET_IS_NOEXEC(applet_no)) {
7694                         clearenv();
7695                         while (*envp)
7696                                 putenv(*envp++);
7697                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7698                         run_applet_no_and_exit(applet_no, cmd, argv);
7699                 }
7700                 /* re-exec ourselves with the new arguments */
7701                 execve(bb_busybox_exec_path, argv, envp);
7702                 /* If they called chroot or otherwise made the binary no longer
7703                  * executable, fall through */
7704         }
7705 #endif
7706
7707  repeat:
7708 #ifdef SYSV
7709         do {
7710                 execve(cmd, argv, envp);
7711         } while (errno == EINTR);
7712 #else
7713         execve(cmd, argv, envp);
7714 #endif
7715         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7716                 /* Run "cmd" as a shell script:
7717                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7718                  * "If the execve() function fails with ENOEXEC, the shell
7719                  * shall execute a command equivalent to having a shell invoked
7720                  * with the command name as its first operand,
7721                  * with any remaining arguments passed to the new shell"
7722                  *
7723                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7724                  * just call ourselves.
7725                  *
7726                  * Note that bash reads ~80 chars of the file, and if it sees
7727                  * a zero byte before it sees newline, it doesn't try to
7728                  * interpret it, but fails with "cannot execute binary file"
7729                  * message and exit code 126. For one, this prevents attempts
7730                  * to interpret foreign ELF binaries as shell scripts.
7731                  */
7732                 argv[0] = (char*) cmd;
7733                 cmd = bb_busybox_exec_path;
7734                 /* NB: this is only possible because all callers of shellexec()
7735                  * ensure that the argv[-1] slot exists!
7736                  */
7737                 argv--;
7738                 argv[0] = (char*) "ash";
7739                 goto repeat;
7740         }
7741 }
7742
7743 /*
7744  * Exec a program.  Never returns.  If you change this routine, you may
7745  * have to change the find_command routine as well.
7746  * argv[-1] must exist and be writable! See tryexec() for why.
7747  */
7748 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7749 static void shellexec(char *prog, char **argv, const char *path, int idx)
7750 {
7751         char *cmdname;
7752         int e;
7753         char **envp;
7754         int exerrno;
7755         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7756
7757         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7758         if (strchr(prog, '/') != NULL
7759 #if ENABLE_FEATURE_SH_STANDALONE
7760          || (applet_no = find_applet_by_name(prog)) >= 0
7761 #endif
7762         ) {
7763                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7764                 if (applet_no >= 0) {
7765                         /* We tried execing ourself, but it didn't work.
7766                          * Maybe /proc/self/exe doesn't exist?
7767                          * Try $PATH search.
7768                          */
7769                         goto try_PATH;
7770                 }
7771                 e = errno;
7772         } else {
7773  try_PATH:
7774                 e = ENOENT;
7775                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7776                         if (--idx < 0 && pathopt == NULL) {
7777                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7778                                 if (errno != ENOENT && errno != ENOTDIR)
7779                                         e = errno;
7780                         }
7781                         stunalloc(cmdname);
7782                 }
7783         }
7784
7785         /* Map to POSIX errors */
7786         switch (e) {
7787         case EACCES:
7788                 exerrno = 126;
7789                 break;
7790         case ENOENT:
7791                 exerrno = 127;
7792                 break;
7793         default:
7794                 exerrno = 2;
7795                 break;
7796         }
7797         exitstatus = exerrno;
7798         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7799                 prog, e, suppress_int));
7800         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7801         /* NOTREACHED */
7802 }
7803
7804 static void
7805 printentry(struct tblentry *cmdp)
7806 {
7807         int idx;
7808         const char *path;
7809         char *name;
7810
7811         idx = cmdp->param.index;
7812         path = pathval();
7813         do {
7814                 name = path_advance(&path, cmdp->cmdname);
7815                 stunalloc(name);
7816         } while (--idx >= 0);
7817         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7818 }
7819
7820 /*
7821  * Clear out command entries.  The argument specifies the first entry in
7822  * PATH which has changed.
7823  */
7824 static void
7825 clearcmdentry(int firstchange)
7826 {
7827         struct tblentry **tblp;
7828         struct tblentry **pp;
7829         struct tblentry *cmdp;
7830
7831         INT_OFF;
7832         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7833                 pp = tblp;
7834                 while ((cmdp = *pp) != NULL) {
7835                         if ((cmdp->cmdtype == CMDNORMAL &&
7836                              cmdp->param.index >= firstchange)
7837                          || (cmdp->cmdtype == CMDBUILTIN &&
7838                              builtinloc >= firstchange)
7839                         ) {
7840                                 *pp = cmdp->next;
7841                                 free(cmdp);
7842                         } else {
7843                                 pp = &cmdp->next;
7844                         }
7845                 }
7846         }
7847         INT_ON;
7848 }
7849
7850 /*
7851  * Locate a command in the command hash table.  If "add" is nonzero,
7852  * add the command to the table if it is not already present.  The
7853  * variable "lastcmdentry" is set to point to the address of the link
7854  * pointing to the entry, so that delete_cmd_entry can delete the
7855  * entry.
7856  *
7857  * Interrupts must be off if called with add != 0.
7858  */
7859 static struct tblentry **lastcmdentry;
7860
7861 static struct tblentry *
7862 cmdlookup(const char *name, int add)
7863 {
7864         unsigned int hashval;
7865         const char *p;
7866         struct tblentry *cmdp;
7867         struct tblentry **pp;
7868
7869         p = name;
7870         hashval = (unsigned char)*p << 4;
7871         while (*p)
7872                 hashval += (unsigned char)*p++;
7873         hashval &= 0x7FFF;
7874         pp = &cmdtable[hashval % CMDTABLESIZE];
7875         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7876                 if (strcmp(cmdp->cmdname, name) == 0)
7877                         break;
7878                 pp = &cmdp->next;
7879         }
7880         if (add && cmdp == NULL) {
7881                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7882                                 + strlen(name)
7883                                 /* + 1 - already done because
7884                                  * tblentry::cmdname is char[1] */);
7885                 /*cmdp->next = NULL; - ckzalloc did it */
7886                 cmdp->cmdtype = CMDUNKNOWN;
7887                 strcpy(cmdp->cmdname, name);
7888         }
7889         lastcmdentry = pp;
7890         return cmdp;
7891 }
7892
7893 /*
7894  * Delete the command entry returned on the last lookup.
7895  */
7896 static void
7897 delete_cmd_entry(void)
7898 {
7899         struct tblentry *cmdp;
7900
7901         INT_OFF;
7902         cmdp = *lastcmdentry;
7903         *lastcmdentry = cmdp->next;
7904         if (cmdp->cmdtype == CMDFUNCTION)
7905                 freefunc(cmdp->param.func);
7906         free(cmdp);
7907         INT_ON;
7908 }
7909
7910 /*
7911  * Add a new command entry, replacing any existing command entry for
7912  * the same name - except special builtins.
7913  */
7914 static void
7915 addcmdentry(char *name, struct cmdentry *entry)
7916 {
7917         struct tblentry *cmdp;
7918
7919         cmdp = cmdlookup(name, 1);
7920         if (cmdp->cmdtype == CMDFUNCTION) {
7921                 freefunc(cmdp->param.func);
7922         }
7923         cmdp->cmdtype = entry->cmdtype;
7924         cmdp->param = entry->u;
7925         cmdp->rehash = 0;
7926 }
7927
7928 static int FAST_FUNC
7929 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7930 {
7931         struct tblentry **pp;
7932         struct tblentry *cmdp;
7933         int c;
7934         struct cmdentry entry;
7935         char *name;
7936
7937         if (nextopt("r") != '\0') {
7938                 clearcmdentry(0);
7939                 return 0;
7940         }
7941
7942         if (*argptr == NULL) {
7943                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7944                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7945                                 if (cmdp->cmdtype == CMDNORMAL)
7946                                         printentry(cmdp);
7947                         }
7948                 }
7949                 return 0;
7950         }
7951
7952         c = 0;
7953         while ((name = *argptr) != NULL) {
7954                 cmdp = cmdlookup(name, 0);
7955                 if (cmdp != NULL
7956                  && (cmdp->cmdtype == CMDNORMAL
7957                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7958                 ) {
7959                         delete_cmd_entry();
7960                 }
7961                 find_command(name, &entry, DO_ERR, pathval());
7962                 if (entry.cmdtype == CMDUNKNOWN)
7963                         c = 1;
7964                 argptr++;
7965         }
7966         return c;
7967 }
7968
7969 /*
7970  * Called when a cd is done.  Marks all commands so the next time they
7971  * are executed they will be rehashed.
7972  */
7973 static void
7974 hashcd(void)
7975 {
7976         struct tblentry **pp;
7977         struct tblentry *cmdp;
7978
7979         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7980                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7981                         if (cmdp->cmdtype == CMDNORMAL
7982                          || (cmdp->cmdtype == CMDBUILTIN
7983                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7984                              && builtinloc > 0)
7985                         ) {
7986                                 cmdp->rehash = 1;
7987                         }
7988                 }
7989         }
7990 }
7991
7992 /*
7993  * Fix command hash table when PATH changed.
7994  * Called before PATH is changed.  The argument is the new value of PATH;
7995  * pathval() still returns the old value at this point.
7996  * Called with interrupts off.
7997  */
7998 static void FAST_FUNC
7999 changepath(const char *new)
8000 {
8001         const char *old;
8002         int firstchange;
8003         int idx;
8004         int idx_bltin;
8005
8006         old = pathval();
8007         firstchange = 9999;     /* assume no change */
8008         idx = 0;
8009         idx_bltin = -1;
8010         for (;;) {
8011                 if (*old != *new) {
8012                         firstchange = idx;
8013                         if ((*old == '\0' && *new == ':')
8014                          || (*old == ':' && *new == '\0')
8015                         ) {
8016                                 firstchange++;
8017                         }
8018                         old = new;      /* ignore subsequent differences */
8019                 }
8020                 if (*new == '\0')
8021                         break;
8022                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8023                         idx_bltin = idx;
8024                 if (*new == ':')
8025                         idx++;
8026                 new++;
8027                 old++;
8028         }
8029         if (builtinloc < 0 && idx_bltin >= 0)
8030                 builtinloc = idx_bltin;             /* zap builtins */
8031         if (builtinloc >= 0 && idx_bltin < 0)
8032                 firstchange = 0;
8033         clearcmdentry(firstchange);
8034         builtinloc = idx_bltin;
8035 }
8036 enum {
8037         TEOF,
8038         TNL,
8039         TREDIR,
8040         TWORD,
8041         TSEMI,
8042         TBACKGND,
8043         TAND,
8044         TOR,
8045         TPIPE,
8046         TLP,
8047         TRP,
8048         TENDCASE,
8049         TENDBQUOTE,
8050         TNOT,
8051         TCASE,
8052         TDO,
8053         TDONE,
8054         TELIF,
8055         TELSE,
8056         TESAC,
8057         TFI,
8058         TFOR,
8059 #if BASH_FUNCTION
8060         TFUNCTION,
8061 #endif
8062         TIF,
8063         TIN,
8064         TTHEN,
8065         TUNTIL,
8066         TWHILE,
8067         TBEGIN,
8068         TEND
8069 };
8070 typedef smallint token_id_t;
8071
8072 /* Nth bit indicates if token marks the end of a list */
8073 enum {
8074         tokendlist = 0
8075         /*  0 */ | (1u << TEOF)
8076         /*  1 */ | (0u << TNL)
8077         /*  2 */ | (0u << TREDIR)
8078         /*  3 */ | (0u << TWORD)
8079         /*  4 */ | (0u << TSEMI)
8080         /*  5 */ | (0u << TBACKGND)
8081         /*  6 */ | (0u << TAND)
8082         /*  7 */ | (0u << TOR)
8083         /*  8 */ | (0u << TPIPE)
8084         /*  9 */ | (0u << TLP)
8085         /* 10 */ | (1u << TRP)
8086         /* 11 */ | (1u << TENDCASE)
8087         /* 12 */ | (1u << TENDBQUOTE)
8088         /* 13 */ | (0u << TNOT)
8089         /* 14 */ | (0u << TCASE)
8090         /* 15 */ | (1u << TDO)
8091         /* 16 */ | (1u << TDONE)
8092         /* 17 */ | (1u << TELIF)
8093         /* 18 */ | (1u << TELSE)
8094         /* 19 */ | (1u << TESAC)
8095         /* 20 */ | (1u << TFI)
8096         /* 21 */ | (0u << TFOR)
8097 #if BASH_FUNCTION
8098         /* 22 */ | (0u << TFUNCTION)
8099 #endif
8100         /* 23 */ | (0u << TIF)
8101         /* 24 */ | (0u << TIN)
8102         /* 25 */ | (1u << TTHEN)
8103         /* 26 */ | (0u << TUNTIL)
8104         /* 27 */ | (0u << TWHILE)
8105         /* 28 */ | (0u << TBEGIN)
8106         /* 29 */ | (1u << TEND)
8107         , /* thus far 29 bits used */
8108 };
8109
8110 static const char *const tokname_array[] = {
8111         "end of file",
8112         "newline",
8113         "redirection",
8114         "word",
8115         ";",
8116         "&",
8117         "&&",
8118         "||",
8119         "|",
8120         "(",
8121         ")",
8122         ";;",
8123         "`",
8124 #define KWDOFFSET 13
8125         /* the following are keywords */
8126         "!",
8127         "case",
8128         "do",
8129         "done",
8130         "elif",
8131         "else",
8132         "esac",
8133         "fi",
8134         "for",
8135 #if BASH_FUNCTION
8136         "function",
8137 #endif
8138         "if",
8139         "in",
8140         "then",
8141         "until",
8142         "while",
8143         "{",
8144         "}",
8145 };
8146
8147 /* Wrapper around strcmp for qsort/bsearch/... */
8148 static int
8149 pstrcmp(const void *a, const void *b)
8150 {
8151         return strcmp((char*)a, *(char**)b);
8152 }
8153
8154 static const char *const *
8155 findkwd(const char *s)
8156 {
8157         return bsearch(s, tokname_array + KWDOFFSET,
8158                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8159                         sizeof(tokname_array[0]), pstrcmp);
8160 }
8161
8162 /*
8163  * Locate and print what a word is...
8164  */
8165 static int
8166 describe_command(char *command, const char *path, int describe_command_verbose)
8167 {
8168         struct cmdentry entry;
8169 #if ENABLE_ASH_ALIAS
8170         const struct alias *ap;
8171 #endif
8172
8173         path = path ? path : pathval();
8174
8175         if (describe_command_verbose) {
8176                 out1str(command);
8177         }
8178
8179         /* First look at the keywords */
8180         if (findkwd(command)) {
8181                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8182                 goto out;
8183         }
8184
8185 #if ENABLE_ASH_ALIAS
8186         /* Then look at the aliases */
8187         ap = lookupalias(command, 0);
8188         if (ap != NULL) {
8189                 if (!describe_command_verbose) {
8190                         out1str("alias ");
8191                         printalias(ap);
8192                         return 0;
8193                 }
8194                 out1fmt(" is an alias for %s", ap->val);
8195                 goto out;
8196         }
8197 #endif
8198         /* Brute force */
8199         find_command(command, &entry, DO_ABS, path);
8200
8201         switch (entry.cmdtype) {
8202         case CMDNORMAL: {
8203                 int j = entry.u.index;
8204                 char *p;
8205                 if (j < 0) {
8206                         p = command;
8207                 } else {
8208                         do {
8209                                 p = path_advance(&path, command);
8210                                 stunalloc(p);
8211                         } while (--j >= 0);
8212                 }
8213                 if (describe_command_verbose) {
8214                         out1fmt(" is %s", p);
8215                 } else {
8216                         out1str(p);
8217                 }
8218                 break;
8219         }
8220
8221         case CMDFUNCTION:
8222                 if (describe_command_verbose) {
8223                         out1str(" is a shell function");
8224                 } else {
8225                         out1str(command);
8226                 }
8227                 break;
8228
8229         case CMDBUILTIN:
8230                 if (describe_command_verbose) {
8231                         out1fmt(" is a %sshell builtin",
8232                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8233                                         "special " : nullstr
8234                         );
8235                 } else {
8236                         out1str(command);
8237                 }
8238                 break;
8239
8240         default:
8241                 if (describe_command_verbose) {
8242                         out1str(": not found\n");
8243                 }
8244                 return 127;
8245         }
8246  out:
8247         out1str("\n");
8248         return 0;
8249 }
8250
8251 static int FAST_FUNC
8252 typecmd(int argc UNUSED_PARAM, char **argv)
8253 {
8254         int i = 1;
8255         int err = 0;
8256         int verbose = 1;
8257
8258         /* type -p ... ? (we don't bother checking for 'p') */
8259         if (argv[1] && argv[1][0] == '-') {
8260                 i++;
8261                 verbose = 0;
8262         }
8263         while (argv[i]) {
8264                 err |= describe_command(argv[i++], NULL, verbose);
8265         }
8266         return err;
8267 }
8268
8269 #if ENABLE_ASH_CMDCMD
8270 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8271 static char **
8272 parse_command_args(char **argv, const char **path)
8273 {
8274         char *cp, c;
8275
8276         for (;;) {
8277                 cp = *++argv;
8278                 if (!cp)
8279                         return NULL;
8280                 if (*cp++ != '-')
8281                         break;
8282                 c = *cp++;
8283                 if (!c)
8284                         break;
8285                 if (c == '-' && !*cp) {
8286                         if (!*++argv)
8287                                 return NULL;
8288                         break;
8289                 }
8290                 do {
8291                         switch (c) {
8292                         case 'p':
8293                                 *path = bb_default_path;
8294                                 break;
8295                         default:
8296                                 /* run 'typecmd' for other options */
8297                                 return NULL;
8298                         }
8299                         c = *cp++;
8300                 } while (c);
8301         }
8302         return argv;
8303 }
8304
8305 static int FAST_FUNC
8306 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8307 {
8308         char *cmd;
8309         int c;
8310         enum {
8311                 VERIFY_BRIEF = 1,
8312                 VERIFY_VERBOSE = 2,
8313         } verify = 0;
8314         const char *path = NULL;
8315
8316         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8317          * never reaches this function.
8318          */
8319
8320         while ((c = nextopt("pvV")) != '\0')
8321                 if (c == 'V')
8322                         verify |= VERIFY_VERBOSE;
8323                 else if (c == 'v')
8324                         /*verify |= VERIFY_BRIEF*/;
8325 #if DEBUG
8326                 else if (c != 'p')
8327                         abort();
8328 #endif
8329                 else
8330                         path = bb_default_path;
8331
8332         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8333         cmd = *argptr;
8334         if (/*verify && */ cmd)
8335                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8336
8337         return 0;
8338 }
8339 #endif
8340
8341
8342 /*static int funcblocksize;     // size of structures in function */
8343 /*static int funcstringsize;    // size of strings in node */
8344 static void *funcblock;         /* block to allocate function from */
8345 static char *funcstring_end;    /* end of block to allocate strings from */
8346
8347 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8348         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8349         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8350         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8351         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8352         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8353         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8354         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8355         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8356         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8357         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8358         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8359         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8360         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8361         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8362         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8363         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8364         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8365 #if BASH_REDIR_OUTPUT
8366         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8367 #endif
8368         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8369         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8370         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8371         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8372         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8373         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8374         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8375         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8376         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8377 };
8378
8379 static int calcsize(int funcblocksize, union node *n);
8380
8381 static int
8382 sizenodelist(int funcblocksize, struct nodelist *lp)
8383 {
8384         while (lp) {
8385                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8386                 funcblocksize = calcsize(funcblocksize, lp->n);
8387                 lp = lp->next;
8388         }
8389         return funcblocksize;
8390 }
8391
8392 static int
8393 calcsize(int funcblocksize, union node *n)
8394 {
8395         if (n == NULL)
8396                 return funcblocksize;
8397         funcblocksize += nodesize[n->type];
8398         switch (n->type) {
8399         case NCMD:
8400                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8401                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8402                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8403                 break;
8404         case NPIPE:
8405                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8406                 break;
8407         case NREDIR:
8408         case NBACKGND:
8409         case NSUBSHELL:
8410                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8411                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8412                 break;
8413         case NAND:
8414         case NOR:
8415         case NSEMI:
8416         case NWHILE:
8417         case NUNTIL:
8418                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8419                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8420                 break;
8421         case NIF:
8422                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8423                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8424                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8425                 break;
8426         case NFOR:
8427                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8428                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8429                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8430                 break;
8431         case NCASE:
8432                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8433                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8434                 break;
8435         case NCLIST:
8436                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8437                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8438                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8439                 break;
8440         case NDEFUN:
8441         case NARG:
8442                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8443                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8444                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8445                 break;
8446         case NTO:
8447 #if BASH_REDIR_OUTPUT
8448         case NTO2:
8449 #endif
8450         case NCLOBBER:
8451         case NFROM:
8452         case NFROMTO:
8453         case NAPPEND:
8454                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8455                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8456                 break;
8457         case NTOFD:
8458         case NFROMFD:
8459                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8460                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8461         break;
8462         case NHERE:
8463         case NXHERE:
8464                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8465                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8466                 break;
8467         case NNOT:
8468                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8469                 break;
8470         };
8471         return funcblocksize;
8472 }
8473
8474 static char *
8475 nodeckstrdup(char *s)
8476 {
8477         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8478         return strcpy(funcstring_end, s);
8479 }
8480
8481 static union node *copynode(union node *);
8482
8483 static struct nodelist *
8484 copynodelist(struct nodelist *lp)
8485 {
8486         struct nodelist *start;
8487         struct nodelist **lpp;
8488
8489         lpp = &start;
8490         while (lp) {
8491                 *lpp = funcblock;
8492                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8493                 (*lpp)->n = copynode(lp->n);
8494                 lp = lp->next;
8495                 lpp = &(*lpp)->next;
8496         }
8497         *lpp = NULL;
8498         return start;
8499 }
8500
8501 static union node *
8502 copynode(union node *n)
8503 {
8504         union node *new;
8505
8506         if (n == NULL)
8507                 return NULL;
8508         new = funcblock;
8509         funcblock = (char *) funcblock + nodesize[n->type];
8510
8511         switch (n->type) {
8512         case NCMD:
8513                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8514                 new->ncmd.args = copynode(n->ncmd.args);
8515                 new->ncmd.assign = copynode(n->ncmd.assign);
8516                 break;
8517         case NPIPE:
8518                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8519                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8520                 break;
8521         case NREDIR:
8522         case NBACKGND:
8523         case NSUBSHELL:
8524                 new->nredir.redirect = copynode(n->nredir.redirect);
8525                 new->nredir.n = copynode(n->nredir.n);
8526                 break;
8527         case NAND:
8528         case NOR:
8529         case NSEMI:
8530         case NWHILE:
8531         case NUNTIL:
8532                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8533                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8534                 break;
8535         case NIF:
8536                 new->nif.elsepart = copynode(n->nif.elsepart);
8537                 new->nif.ifpart = copynode(n->nif.ifpart);
8538                 new->nif.test = copynode(n->nif.test);
8539                 break;
8540         case NFOR:
8541                 new->nfor.var = nodeckstrdup(n->nfor.var);
8542                 new->nfor.body = copynode(n->nfor.body);
8543                 new->nfor.args = copynode(n->nfor.args);
8544                 break;
8545         case NCASE:
8546                 new->ncase.cases = copynode(n->ncase.cases);
8547                 new->ncase.expr = copynode(n->ncase.expr);
8548                 break;
8549         case NCLIST:
8550                 new->nclist.body = copynode(n->nclist.body);
8551                 new->nclist.pattern = copynode(n->nclist.pattern);
8552                 new->nclist.next = copynode(n->nclist.next);
8553                 break;
8554         case NDEFUN:
8555         case NARG:
8556                 new->narg.backquote = copynodelist(n->narg.backquote);
8557                 new->narg.text = nodeckstrdup(n->narg.text);
8558                 new->narg.next = copynode(n->narg.next);
8559                 break;
8560         case NTO:
8561 #if BASH_REDIR_OUTPUT
8562         case NTO2:
8563 #endif
8564         case NCLOBBER:
8565         case NFROM:
8566         case NFROMTO:
8567         case NAPPEND:
8568                 new->nfile.fname = copynode(n->nfile.fname);
8569                 new->nfile.fd = n->nfile.fd;
8570                 new->nfile.next = copynode(n->nfile.next);
8571                 break;
8572         case NTOFD:
8573         case NFROMFD:
8574                 new->ndup.vname = copynode(n->ndup.vname);
8575                 new->ndup.dupfd = n->ndup.dupfd;
8576                 new->ndup.fd = n->ndup.fd;
8577                 new->ndup.next = copynode(n->ndup.next);
8578                 break;
8579         case NHERE:
8580         case NXHERE:
8581                 new->nhere.doc = copynode(n->nhere.doc);
8582                 new->nhere.fd = n->nhere.fd;
8583                 new->nhere.next = copynode(n->nhere.next);
8584                 break;
8585         case NNOT:
8586                 new->nnot.com = copynode(n->nnot.com);
8587                 break;
8588         };
8589         new->type = n->type;
8590         return new;
8591 }
8592
8593 /*
8594  * Make a copy of a parse tree.
8595  */
8596 static struct funcnode *
8597 copyfunc(union node *n)
8598 {
8599         struct funcnode *f;
8600         size_t blocksize;
8601
8602         /*funcstringsize = 0;*/
8603         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8604         f = ckzalloc(blocksize /* + funcstringsize */);
8605         funcblock = (char *) f + offsetof(struct funcnode, n);
8606         funcstring_end = (char *) f + blocksize;
8607         copynode(n);
8608         /* f->count = 0; - ckzalloc did it */
8609         return f;
8610 }
8611
8612 /*
8613  * Define a shell function.
8614  */
8615 static void
8616 defun(union node *func)
8617 {
8618         struct cmdentry entry;
8619
8620         INT_OFF;
8621         entry.cmdtype = CMDFUNCTION;
8622         entry.u.func = copyfunc(func);
8623         addcmdentry(func->narg.text, &entry);
8624         INT_ON;
8625 }
8626
8627 /* Reasons for skipping commands (see comment on breakcmd routine) */
8628 #define SKIPBREAK      (1 << 0)
8629 #define SKIPCONT       (1 << 1)
8630 #define SKIPFUNC       (1 << 2)
8631 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8632 static int skipcount;           /* number of levels to skip */
8633 static int funcnest;            /* depth of function calls */
8634 static int loopnest;            /* current loop nesting level */
8635
8636 /* Forward decl way out to parsing code - dotrap needs it */
8637 static int evalstring(char *s, int flags);
8638
8639 /* Called to execute a trap.
8640  * Single callsite - at the end of evaltree().
8641  * If we return non-zero, evaltree raises EXEXIT exception.
8642  *
8643  * Perhaps we should avoid entering new trap handlers
8644  * while we are executing a trap handler. [is it a TODO?]
8645  */
8646 static void
8647 dotrap(void)
8648 {
8649         uint8_t *g;
8650         int sig;
8651         uint8_t last_status;
8652
8653         if (!pending_sig)
8654                 return;
8655
8656         last_status = exitstatus;
8657         pending_sig = 0;
8658         barrier();
8659
8660         TRACE(("dotrap entered\n"));
8661         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8662                 char *p;
8663
8664                 if (!*g)
8665                         continue;
8666
8667                 if (evalskip) {
8668                         pending_sig = sig;
8669                         break;
8670                 }
8671
8672                 p = trap[sig];
8673                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8674                  * don't upset it by resetting gotsig[SIGINT-1] */
8675                 if (sig == SIGINT && !p)
8676                         continue;
8677
8678                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8679                 *g = 0;
8680                 if (!p)
8681                         continue;
8682                 evalstring(p, 0);
8683         }
8684         exitstatus = last_status;
8685         TRACE(("dotrap returns\n"));
8686 }
8687
8688 /* forward declarations - evaluation is fairly recursive business... */
8689 static int evalloop(union node *, int);
8690 static int evalfor(union node *, int);
8691 static int evalcase(union node *, int);
8692 static int evalsubshell(union node *, int);
8693 static void expredir(union node *);
8694 static int evalpipe(union node *, int);
8695 static int evalcommand(union node *, int);
8696 static int evalbltin(const struct builtincmd *, int, char **, int);
8697 static void prehash(union node *);
8698
8699 /*
8700  * Evaluate a parse tree.  The value is left in the global variable
8701  * exitstatus.
8702  */
8703 static int
8704 evaltree(union node *n, int flags)
8705 {
8706         int checkexit = 0;
8707         int (*evalfn)(union node *, int);
8708         int status = 0;
8709
8710         if (n == NULL) {
8711                 TRACE(("evaltree(NULL) called\n"));
8712                 goto out;
8713         }
8714         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8715
8716         dotrap();
8717
8718         switch (n->type) {
8719         default:
8720 #if DEBUG
8721                 out1fmt("Node type = %d\n", n->type);
8722                 fflush_all();
8723                 break;
8724 #endif
8725         case NNOT:
8726                 status = !evaltree(n->nnot.com, EV_TESTED);
8727                 goto setstatus;
8728         case NREDIR:
8729                 expredir(n->nredir.redirect);
8730                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8731                 if (!status) {
8732                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8733                 }
8734                 if (n->nredir.redirect)
8735                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8736                 goto setstatus;
8737         case NCMD:
8738                 evalfn = evalcommand;
8739  checkexit:
8740                 if (eflag && !(flags & EV_TESTED))
8741                         checkexit = ~0;
8742                 goto calleval;
8743         case NFOR:
8744                 evalfn = evalfor;
8745                 goto calleval;
8746         case NWHILE:
8747         case NUNTIL:
8748                 evalfn = evalloop;
8749                 goto calleval;
8750         case NSUBSHELL:
8751         case NBACKGND:
8752                 evalfn = evalsubshell;
8753                 goto checkexit;
8754         case NPIPE:
8755                 evalfn = evalpipe;
8756                 goto checkexit;
8757         case NCASE:
8758                 evalfn = evalcase;
8759                 goto calleval;
8760         case NAND:
8761         case NOR:
8762         case NSEMI: {
8763
8764 #if NAND + 1 != NOR
8765 #error NAND + 1 != NOR
8766 #endif
8767 #if NOR + 1 != NSEMI
8768 #error NOR + 1 != NSEMI
8769 #endif
8770                 unsigned is_or = n->type - NAND;
8771                 status = evaltree(
8772                         n->nbinary.ch1,
8773                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8774                 );
8775                 if ((!status) == is_or || evalskip)
8776                         break;
8777                 n = n->nbinary.ch2;
8778  evaln:
8779                 evalfn = evaltree;
8780  calleval:
8781                 status = evalfn(n, flags);
8782                 goto setstatus;
8783         }
8784         case NIF:
8785                 status = evaltree(n->nif.test, EV_TESTED);
8786                 if (evalskip)
8787                         break;
8788                 if (!status) {
8789                         n = n->nif.ifpart;
8790                         goto evaln;
8791                 }
8792                 if (n->nif.elsepart) {
8793                         n = n->nif.elsepart;
8794                         goto evaln;
8795                 }
8796                 status = 0;
8797                 goto setstatus;
8798         case NDEFUN:
8799                 defun(n);
8800                 /* Not necessary. To test it:
8801                  * "false; f() { qwerty; }; echo $?" should print 0.
8802                  */
8803                 /* status = 0; */
8804  setstatus:
8805                 exitstatus = status;
8806                 break;
8807         }
8808  out:
8809         /* Order of checks below is important:
8810          * signal handlers trigger before exit caused by "set -e".
8811          */
8812         dotrap();
8813
8814         if (checkexit & status)
8815                 raise_exception(EXEXIT);
8816         if (flags & EV_EXIT)
8817                 raise_exception(EXEXIT);
8818
8819         TRACE(("leaving evaltree (no interrupts)\n"));
8820         return exitstatus;
8821 }
8822
8823 static int
8824 skiploop(void)
8825 {
8826         int skip = evalskip;
8827
8828         switch (skip) {
8829         case 0:
8830                 break;
8831         case SKIPBREAK:
8832         case SKIPCONT:
8833                 if (--skipcount <= 0) {
8834                         evalskip = 0;
8835                         break;
8836                 }
8837                 skip = SKIPBREAK;
8838                 break;
8839         }
8840         return skip;
8841 }
8842
8843 static int
8844 evalloop(union node *n, int flags)
8845 {
8846         int skip;
8847         int status;
8848
8849         loopnest++;
8850         status = 0;
8851         flags &= EV_TESTED;
8852         do {
8853                 int i;
8854
8855                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8856                 skip = skiploop();
8857                 if (skip == SKIPFUNC)
8858                         status = i;
8859                 if (skip)
8860                         continue;
8861                 if (n->type != NWHILE)
8862                         i = !i;
8863                 if (i != 0)
8864                         break;
8865                 status = evaltree(n->nbinary.ch2, flags);
8866                 skip = skiploop();
8867         } while (!(skip & ~SKIPCONT));
8868         loopnest--;
8869
8870         return status;
8871 }
8872
8873 static int
8874 evalfor(union node *n, int flags)
8875 {
8876         struct arglist arglist;
8877         union node *argp;
8878         struct strlist *sp;
8879         struct stackmark smark;
8880         int status = 0;
8881
8882         setstackmark(&smark);
8883         arglist.list = NULL;
8884         arglist.lastp = &arglist.list;
8885         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8886                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8887         }
8888         *arglist.lastp = NULL;
8889
8890         loopnest++;
8891         flags &= EV_TESTED;
8892         for (sp = arglist.list; sp; sp = sp->next) {
8893                 setvar0(n->nfor.var, sp->text);
8894                 status = evaltree(n->nfor.body, flags);
8895                 if (skiploop() & ~SKIPCONT)
8896                         break;
8897         }
8898         loopnest--;
8899         popstackmark(&smark);
8900
8901         return status;
8902 }
8903
8904 static int
8905 evalcase(union node *n, int flags)
8906 {
8907         union node *cp;
8908         union node *patp;
8909         struct arglist arglist;
8910         struct stackmark smark;
8911         int status = 0;
8912
8913         setstackmark(&smark);
8914         arglist.list = NULL;
8915         arglist.lastp = &arglist.list;
8916         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8917         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8918                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8919                         if (casematch(patp, arglist.list->text)) {
8920                                 /* Ensure body is non-empty as otherwise
8921                                  * EV_EXIT may prevent us from setting the
8922                                  * exit status.
8923                                  */
8924                                 if (evalskip == 0 && cp->nclist.body) {
8925                                         status = evaltree(cp->nclist.body, flags);
8926                                 }
8927                                 goto out;
8928                         }
8929                 }
8930         }
8931  out:
8932         popstackmark(&smark);
8933
8934         return status;
8935 }
8936
8937 /*
8938  * Kick off a subshell to evaluate a tree.
8939  */
8940 static int
8941 evalsubshell(union node *n, int flags)
8942 {
8943         struct job *jp;
8944         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8945         int status;
8946
8947         expredir(n->nredir.redirect);
8948         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8949                 goto nofork;
8950         INT_OFF;
8951         if (backgnd == FORK_FG)
8952                 get_tty_state();
8953         jp = makejob(/*n,*/ 1);
8954         if (forkshell(jp, n, backgnd) == 0) {
8955                 /* child */
8956                 INT_ON;
8957                 flags |= EV_EXIT;
8958                 if (backgnd)
8959                         flags &= ~EV_TESTED;
8960  nofork:
8961                 redirect(n->nredir.redirect, 0);
8962                 evaltreenr(n->nredir.n, flags);
8963                 /* never returns */
8964         }
8965         /* parent */
8966         status = 0;
8967         if (backgnd == FORK_FG)
8968                 status = waitforjob(jp);
8969         INT_ON;
8970         return status;
8971 }
8972
8973 /*
8974  * Compute the names of the files in a redirection list.
8975  */
8976 static void fixredir(union node *, const char *, int);
8977 static void
8978 expredir(union node *n)
8979 {
8980         union node *redir;
8981
8982         for (redir = n; redir; redir = redir->nfile.next) {
8983                 struct arglist fn;
8984
8985                 fn.list = NULL;
8986                 fn.lastp = &fn.list;
8987                 switch (redir->type) {
8988                 case NFROMTO:
8989                 case NFROM:
8990                 case NTO:
8991 #if BASH_REDIR_OUTPUT
8992                 case NTO2:
8993 #endif
8994                 case NCLOBBER:
8995                 case NAPPEND:
8996                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8997                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
8998 #if BASH_REDIR_OUTPUT
8999  store_expfname:
9000 #endif
9001 #if 0
9002 // By the design of stack allocator, the loop of this kind:
9003 //      while true; do while true; do break; done </dev/null; done
9004 // will look like a memory leak: ash plans to free expfname's
9005 // of "/dev/null" as soon as it finishes running the loop
9006 // (in this case, never).
9007 // This "fix" is wrong:
9008                         if (redir->nfile.expfname)
9009                                 stunalloc(redir->nfile.expfname);
9010 // It results in corrupted state of stacked allocations.
9011 #endif
9012                         redir->nfile.expfname = fn.list->text;
9013                         break;
9014                 case NFROMFD:
9015                 case NTOFD: /* >& */
9016                         if (redir->ndup.vname) {
9017                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9018                                 if (fn.list == NULL)
9019                                         ash_msg_and_raise_error("redir error");
9020 #if BASH_REDIR_OUTPUT
9021 //FIXME: we used expandarg with different args!
9022                                 if (!isdigit_str9(fn.list->text)) {
9023                                         /* >&file, not >&fd */
9024                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9025                                                 ash_msg_and_raise_error("redir error");
9026                                         redir->type = NTO2;
9027                                         goto store_expfname;
9028                                 }
9029 #endif
9030                                 fixredir(redir, fn.list->text, 1);
9031                         }
9032                         break;
9033                 }
9034         }
9035 }
9036
9037 /*
9038  * Evaluate a pipeline.  All the processes in the pipeline are children
9039  * of the process creating the pipeline.  (This differs from some versions
9040  * of the shell, which make the last process in a pipeline the parent
9041  * of all the rest.)
9042  */
9043 static int
9044 evalpipe(union node *n, int flags)
9045 {
9046         struct job *jp;
9047         struct nodelist *lp;
9048         int pipelen;
9049         int prevfd;
9050         int pip[2];
9051         int status = 0;
9052
9053         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9054         pipelen = 0;
9055         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9056                 pipelen++;
9057         flags |= EV_EXIT;
9058         INT_OFF;
9059         if (n->npipe.pipe_backgnd == 0)
9060                 get_tty_state();
9061         jp = makejob(/*n,*/ pipelen);
9062         prevfd = -1;
9063         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9064                 prehash(lp->n);
9065                 pip[1] = -1;
9066                 if (lp->next) {
9067                         if (pipe(pip) < 0) {
9068                                 close(prevfd);
9069                                 ash_msg_and_raise_error("pipe call failed");
9070                         }
9071                 }
9072                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9073                         /* child */
9074                         INT_ON;
9075                         if (pip[1] >= 0) {
9076                                 close(pip[0]);
9077                         }
9078                         if (prevfd > 0) {
9079                                 dup2(prevfd, 0);
9080                                 close(prevfd);
9081                         }
9082                         if (pip[1] > 1) {
9083                                 dup2(pip[1], 1);
9084                                 close(pip[1]);
9085                         }
9086                         evaltreenr(lp->n, flags);
9087                         /* never returns */
9088                 }
9089                 /* parent */
9090                 if (prevfd >= 0)
9091                         close(prevfd);
9092                 prevfd = pip[0];
9093                 /* Don't want to trigger debugging */
9094                 if (pip[1] != -1)
9095                         close(pip[1]);
9096         }
9097         if (n->npipe.pipe_backgnd == 0) {
9098                 status = waitforjob(jp);
9099                 TRACE(("evalpipe:  job done exit status %d\n", status));
9100         }
9101         INT_ON;
9102
9103         return status;
9104 }
9105
9106 /*
9107  * Controls whether the shell is interactive or not.
9108  */
9109 static void
9110 setinteractive(int on)
9111 {
9112         static smallint is_interactive;
9113
9114         if (++on == is_interactive)
9115                 return;
9116         is_interactive = on;
9117         setsignal(SIGINT);
9118         setsignal(SIGQUIT);
9119         setsignal(SIGTERM);
9120 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9121         if (is_interactive > 1) {
9122                 /* Looks like they want an interactive shell */
9123                 static smallint did_banner;
9124
9125                 if (!did_banner) {
9126                         /* note: ash and hush share this string */
9127                         out1fmt("\n\n%s %s\n"
9128                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9129                                 "\n",
9130                                 bb_banner,
9131                                 "built-in shell (ash)"
9132                         );
9133                         did_banner = 1;
9134                 }
9135         }
9136 #endif
9137 }
9138
9139 static void
9140 optschanged(void)
9141 {
9142 #if DEBUG
9143         opentrace();
9144 #endif
9145         setinteractive(iflag);
9146         setjobctl(mflag);
9147 #if ENABLE_FEATURE_EDITING_VI
9148         if (viflag)
9149                 line_input_state->flags |= VI_MODE;
9150         else
9151                 line_input_state->flags &= ~VI_MODE;
9152 #else
9153         viflag = 0; /* forcibly keep the option off */
9154 #endif
9155 }
9156
9157 struct localvar_list {
9158         struct localvar_list *next;
9159         struct localvar *lv;
9160 };
9161
9162 static struct localvar_list *localvar_stack;
9163
9164 /*
9165  * Called after a function returns.
9166  * Interrupts must be off.
9167  */
9168 static void
9169 poplocalvars(int keep)
9170 {
9171         struct localvar_list *ll;
9172         struct localvar *lvp, *next;
9173         struct var *vp;
9174
9175         INT_OFF;
9176         ll = localvar_stack;
9177         localvar_stack = ll->next;
9178
9179         next = ll->lv;
9180         free(ll);
9181
9182         while ((lvp = next) != NULL) {
9183                 next = lvp->next;
9184                 vp = lvp->vp;
9185                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9186                 if (keep) {
9187                         int bits = VSTRFIXED;
9188
9189                         if (lvp->flags != VUNSET) {
9190                                 if (vp->var_text == lvp->text)
9191                                         bits |= VTEXTFIXED;
9192                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9193                                         free((char*)lvp->text);
9194                         }
9195
9196                         vp->flags &= ~bits;
9197                         vp->flags |= (lvp->flags & bits);
9198
9199                         if ((vp->flags &
9200                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9201                                 unsetvar(vp->var_text);
9202                 } else if (vp == NULL) {        /* $- saved */
9203                         memcpy(optlist, lvp->text, sizeof(optlist));
9204                         free((char*)lvp->text);
9205                         optschanged();
9206                 } else if (lvp->flags == VUNSET) {
9207                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9208                         unsetvar(vp->var_text);
9209                 } else {
9210                         if (vp->var_func)
9211                                 vp->var_func(var_end(lvp->text));
9212                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9213                                 free((char*)vp->var_text);
9214                         vp->flags = lvp->flags;
9215                         vp->var_text = lvp->text;
9216                 }
9217                 free(lvp);
9218         }
9219         INT_ON;
9220 }
9221
9222 /*
9223  * Create a new localvar environment.
9224  */
9225 static struct localvar_list *
9226 pushlocalvars(void)
9227 {
9228         struct localvar_list *ll;
9229
9230         INT_OFF;
9231         ll = ckzalloc(sizeof(*ll));
9232         /*ll->lv = NULL; - zalloc did it */
9233         ll->next = localvar_stack;
9234         localvar_stack = ll;
9235         INT_ON;
9236
9237         return ll->next;
9238 }
9239
9240 static void
9241 unwindlocalvars(struct localvar_list *stop)
9242 {
9243         while (localvar_stack != stop)
9244                 poplocalvars(0);
9245 }
9246
9247 static int
9248 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9249 {
9250         volatile struct shparam saveparam;
9251         struct jmploc *volatile savehandler;
9252         struct jmploc jmploc;
9253         int e;
9254
9255         saveparam = shellparam;
9256         savehandler = exception_handler;
9257         e = setjmp(jmploc.loc);
9258         if (e) {
9259                 goto funcdone;
9260         }
9261         INT_OFF;
9262         exception_handler = &jmploc;
9263         shellparam.malloced = 0;
9264         func->count++;
9265         funcnest++;
9266         INT_ON;
9267         shellparam.nparam = argc - 1;
9268         shellparam.p = argv + 1;
9269 #if ENABLE_ASH_GETOPTS
9270         shellparam.optind = 1;
9271         shellparam.optoff = -1;
9272 #endif
9273         pushlocalvars();
9274         evaltree(func->n.narg.next, flags & EV_TESTED);
9275         poplocalvars(0);
9276  funcdone:
9277         INT_OFF;
9278         funcnest--;
9279         freefunc(func);
9280         freeparam(&shellparam);
9281         shellparam = saveparam;
9282         exception_handler = savehandler;
9283         INT_ON;
9284         evalskip &= ~SKIPFUNC;
9285         return e;
9286 }
9287
9288 /*
9289  * Make a variable a local variable.  When a variable is made local, it's
9290  * value and flags are saved in a localvar structure.  The saved values
9291  * will be restored when the shell function returns.  We handle the name
9292  * "-" as a special case: it makes changes to "set +-options" local
9293  * (options will be restored on return from the function).
9294  */
9295 static void
9296 mklocal(char *name)
9297 {
9298         struct localvar *lvp;
9299         struct var **vpp;
9300         struct var *vp;
9301         char *eq = strchr(name, '=');
9302
9303         INT_OFF;
9304         /* Cater for duplicate "local". Examples:
9305          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9306          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9307          */
9308         lvp = localvar_stack->lv;
9309         while (lvp) {
9310                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9311                         if (eq)
9312                                 setvareq(name, 0);
9313                         /* else:
9314                          * it's a duplicate "local VAR" declaration, do nothing
9315                          */
9316                         goto ret;
9317                 }
9318                 lvp = lvp->next;
9319         }
9320
9321         lvp = ckzalloc(sizeof(*lvp));
9322         if (LONE_DASH(name)) {
9323                 char *p;
9324                 p = ckmalloc(sizeof(optlist));
9325                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9326                 vp = NULL;
9327         } else {
9328                 vpp = hashvar(name);
9329                 vp = *findvar(vpp, name);
9330                 if (vp == NULL) {
9331                         /* variable did not exist yet */
9332                         if (eq)
9333                                 vp = setvareq(name, VSTRFIXED);
9334                         else
9335                                 vp = setvar(name, NULL, VSTRFIXED);
9336                         lvp->flags = VUNSET;
9337                 } else {
9338                         lvp->text = vp->var_text;
9339                         lvp->flags = vp->flags;
9340                         /* make sure neither "struct var" nor string gets freed
9341                          * during (un)setting:
9342                          */
9343                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9344                         if (eq)
9345                                 setvareq(name, 0);
9346                         else
9347                                 /* "local VAR" unsets VAR: */
9348                                 setvar0(name, NULL);
9349                 }
9350         }
9351         lvp->vp = vp;
9352         lvp->next = localvar_stack->lv;
9353         localvar_stack->lv = lvp;
9354  ret:
9355         INT_ON;
9356 }
9357
9358 /*
9359  * The "local" command.
9360  */
9361 static int FAST_FUNC
9362 localcmd(int argc UNUSED_PARAM, char **argv)
9363 {
9364         char *name;
9365
9366         if (!localvar_stack)
9367                 ash_msg_and_raise_error("not in a function");
9368
9369         argv = argptr;
9370         while ((name = *argv++) != NULL) {
9371                 mklocal(name);
9372         }
9373         return 0;
9374 }
9375
9376 static int FAST_FUNC
9377 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9378 {
9379         return 1;
9380 }
9381
9382 static int FAST_FUNC
9383 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9384 {
9385         return 0;
9386 }
9387
9388 static int FAST_FUNC
9389 execcmd(int argc UNUSED_PARAM, char **argv)
9390 {
9391         optionarg = NULL;
9392         while (nextopt("a:") != '\0')
9393                 /* nextopt() sets optionarg to "-a ARGV0" */;
9394
9395         argv = argptr;
9396         if (argv[0]) {
9397                 char *prog;
9398
9399                 iflag = 0;              /* exit on error */
9400                 mflag = 0;
9401                 optschanged();
9402                 /* We should set up signals for "exec CMD"
9403                  * the same way as for "CMD" without "exec".
9404                  * But optschanged->setinteractive->setsignal
9405                  * still thought we are a root shell. Therefore, for example,
9406                  * SIGQUIT is still set to IGN. Fix it:
9407                  */
9408                 shlvl++;
9409                 setsignal(SIGQUIT);
9410                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9411                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9412                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9413
9414                 prog = argv[0];
9415                 if (optionarg)
9416                         argv[0] = optionarg;
9417                 shellexec(prog, argv, pathval(), 0);
9418                 /* NOTREACHED */
9419         }
9420         return 0;
9421 }
9422
9423 /*
9424  * The return command.
9425  */
9426 static int FAST_FUNC
9427 returncmd(int argc UNUSED_PARAM, char **argv)
9428 {
9429         /*
9430          * If called outside a function, do what ksh does;
9431          * skip the rest of the file.
9432          */
9433         evalskip = SKIPFUNC;
9434         return argv[1] ? number(argv[1]) : exitstatus;
9435 }
9436
9437 /* Forward declarations for builtintab[] */
9438 static int breakcmd(int, char **) FAST_FUNC;
9439 static int dotcmd(int, char **) FAST_FUNC;
9440 static int evalcmd(int, char **, int) FAST_FUNC;
9441 static int exitcmd(int, char **) FAST_FUNC;
9442 static int exportcmd(int, char **) FAST_FUNC;
9443 #if ENABLE_ASH_GETOPTS
9444 static int getoptscmd(int, char **) FAST_FUNC;
9445 #endif
9446 #if ENABLE_ASH_HELP
9447 static int helpcmd(int, char **) FAST_FUNC;
9448 #endif
9449 #if MAX_HISTORY
9450 static int historycmd(int, char **) FAST_FUNC;
9451 #endif
9452 #if ENABLE_FEATURE_SH_MATH
9453 static int letcmd(int, char **) FAST_FUNC;
9454 #endif
9455 static int readcmd(int, char **) FAST_FUNC;
9456 static int setcmd(int, char **) FAST_FUNC;
9457 static int shiftcmd(int, char **) FAST_FUNC;
9458 static int timescmd(int, char **) FAST_FUNC;
9459 static int trapcmd(int, char **) FAST_FUNC;
9460 static int umaskcmd(int, char **) FAST_FUNC;
9461 static int unsetcmd(int, char **) FAST_FUNC;
9462 static int ulimitcmd(int, char **) FAST_FUNC;
9463
9464 #define BUILTIN_NOSPEC          "0"
9465 #define BUILTIN_SPECIAL         "1"
9466 #define BUILTIN_REGULAR         "2"
9467 #define BUILTIN_SPEC_REG        "3"
9468 #define BUILTIN_ASSIGN          "4"
9469 #define BUILTIN_SPEC_ASSG       "5"
9470 #define BUILTIN_REG_ASSG        "6"
9471 #define BUILTIN_SPEC_REG_ASSG   "7"
9472
9473 /* Stubs for calling non-FAST_FUNC's */
9474 #if ENABLE_ASH_ECHO
9475 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9476 #endif
9477 #if ENABLE_ASH_PRINTF
9478 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9479 #endif
9480 #if ENABLE_ASH_TEST || BASH_TEST2
9481 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9482 #endif
9483
9484 /* Keep these in proper order since it is searched via bsearch() */
9485 static const struct builtincmd builtintab[] = {
9486         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9487         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9488 #if ENABLE_ASH_TEST
9489         { BUILTIN_REGULAR       "["       , testcmd    },
9490 #endif
9491 #if BASH_TEST2
9492         { BUILTIN_REGULAR       "[["      , testcmd    },
9493 #endif
9494 #if ENABLE_ASH_ALIAS
9495         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9496 #endif
9497 #if JOBS
9498         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9499 #endif
9500         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9501         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9502         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9503 #if ENABLE_ASH_CMDCMD
9504         { BUILTIN_REGULAR       "command" , commandcmd },
9505 #endif
9506         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9507 #if ENABLE_ASH_ECHO
9508         { BUILTIN_REGULAR       "echo"    , echocmd    },
9509 #endif
9510         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9511         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9512         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9513         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9514         { BUILTIN_REGULAR       "false"   , falsecmd   },
9515 #if JOBS
9516         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9517 #endif
9518 #if ENABLE_ASH_GETOPTS
9519         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9520 #endif
9521         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9522 #if ENABLE_ASH_HELP
9523         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9524 #endif
9525 #if MAX_HISTORY
9526         { BUILTIN_NOSPEC        "history" , historycmd },
9527 #endif
9528 #if JOBS
9529         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9530         { BUILTIN_REGULAR       "kill"    , killcmd    },
9531 #endif
9532 #if ENABLE_FEATURE_SH_MATH
9533         { BUILTIN_NOSPEC        "let"     , letcmd     },
9534 #endif
9535         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9536 #if ENABLE_ASH_PRINTF
9537         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9538 #endif
9539         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9540         { BUILTIN_REGULAR       "read"    , readcmd    },
9541         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9542         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9543         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9544         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9545 #if BASH_SOURCE
9546         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9547 #endif
9548 #if ENABLE_ASH_TEST
9549         { BUILTIN_REGULAR       "test"    , testcmd    },
9550 #endif
9551         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9552         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9553         { BUILTIN_REGULAR       "true"    , truecmd    },
9554         { BUILTIN_NOSPEC        "type"    , typecmd    },
9555         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9556         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9557 #if ENABLE_ASH_ALIAS
9558         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9559 #endif
9560         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9561         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9562 };
9563
9564 /* Should match the above table! */
9565 #define COMMANDCMD (builtintab + \
9566         /* . : */       2 + \
9567         /* [ */         1 * ENABLE_ASH_TEST + \
9568         /* [[ */        1 * BASH_TEST2 + \
9569         /* alias */     1 * ENABLE_ASH_ALIAS + \
9570         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9571         /* break cd cddir  */   3)
9572 #define EVALCMD (COMMANDCMD + \
9573         /* command */   1 * ENABLE_ASH_CMDCMD + \
9574         /* continue */  1 + \
9575         /* echo */      1 * ENABLE_ASH_ECHO + \
9576         0)
9577 #define EXECCMD (EVALCMD + \
9578         /* eval */      1)
9579
9580 /*
9581  * Search the table of builtin commands.
9582  */
9583 static int
9584 pstrcmp1(const void *a, const void *b)
9585 {
9586         return strcmp((char*)a, *(char**)b + 1);
9587 }
9588 static struct builtincmd *
9589 find_builtin(const char *name)
9590 {
9591         struct builtincmd *bp;
9592
9593         bp = bsearch(
9594                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9595                 pstrcmp1
9596         );
9597         return bp;
9598 }
9599
9600 /*
9601  * Execute a simple command.
9602  */
9603 static int
9604 isassignment(const char *p)
9605 {
9606         const char *q = endofname(p);
9607         if (p == q)
9608                 return 0;
9609         return *q == '=';
9610 }
9611 static int FAST_FUNC
9612 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9613 {
9614         /* Preserve exitstatus of a previous possible redirection
9615          * as POSIX mandates */
9616         return back_exitstatus;
9617 }
9618 static int
9619 evalcommand(union node *cmd, int flags)
9620 {
9621         static const struct builtincmd null_bltin = {
9622                 "\0\0", bltincmd /* why three NULs? */
9623         };
9624         struct localvar_list *localvar_stop;
9625         struct stackmark smark;
9626         union node *argp;
9627         struct arglist arglist;
9628         struct arglist varlist;
9629         char **argv;
9630         int argc;
9631         const struct strlist *sp;
9632         struct cmdentry cmdentry;
9633         struct job *jp;
9634         char *lastarg;
9635         const char *path;
9636         int spclbltin;
9637         int status;
9638         char **nargv;
9639         struct builtincmd *bcmd;
9640         smallint cmd_is_exec;
9641         smallint pseudovarflag = 0;
9642
9643         /* First expand the arguments. */
9644         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9645         setstackmark(&smark);
9646         localvar_stop = pushlocalvars();
9647         back_exitstatus = 0;
9648
9649         cmdentry.cmdtype = CMDBUILTIN;
9650         cmdentry.u.cmd = &null_bltin;
9651         varlist.lastp = &varlist.list;
9652         *varlist.lastp = NULL;
9653         arglist.lastp = &arglist.list;
9654         *arglist.lastp = NULL;
9655
9656         argc = 0;
9657         if (cmd->ncmd.args) {
9658                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9659                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9660         }
9661
9662         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9663                 struct strlist **spp;
9664
9665                 spp = arglist.lastp;
9666                 if (pseudovarflag && isassignment(argp->narg.text))
9667                         expandarg(argp, &arglist, EXP_VARTILDE);
9668                 else
9669                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9670
9671                 for (sp = *spp; sp; sp = sp->next)
9672                         argc++;
9673         }
9674
9675         /* Reserve one extra spot at the front for shellexec. */
9676         nargv = stalloc(sizeof(char *) * (argc + 2));
9677         argv = ++nargv;
9678         for (sp = arglist.list; sp; sp = sp->next) {
9679                 TRACE(("evalcommand arg: %s\n", sp->text));
9680                 *nargv++ = sp->text;
9681         }
9682         *nargv = NULL;
9683
9684         lastarg = NULL;
9685         if (iflag && funcnest == 0 && argc > 0)
9686                 lastarg = nargv[-1];
9687
9688         preverrout_fd = 2;
9689         expredir(cmd->ncmd.redirect);
9690         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9691
9692         path = vpath.var_text;
9693         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9694                 struct strlist **spp;
9695                 char *p;
9696
9697                 spp = varlist.lastp;
9698                 expandarg(argp, &varlist, EXP_VARTILDE);
9699
9700                 mklocal((*spp)->text);
9701
9702                 /*
9703                  * Modify the command lookup path, if a PATH= assignment
9704                  * is present
9705                  */
9706                 p = (*spp)->text;
9707                 if (varcmp(p, path) == 0)
9708                         path = p;
9709         }
9710
9711         /* Print the command if xflag is set. */
9712         if (xflag) {
9713                 const char *pfx = "";
9714
9715                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9716
9717                 sp = varlist.list;
9718                 while (sp) {
9719                         char *varval = sp->text;
9720                         char *eq = strchrnul(varval, '=');
9721                         if (*eq)
9722                                 eq++;
9723                         fdprintf(preverrout_fd, "%s%.*s%s",
9724                                 pfx,
9725                                 (int)(eq - varval), varval,
9726                                 maybe_single_quote(eq)
9727                         );
9728                         sp = sp->next;
9729                         pfx = " ";
9730                 }
9731
9732                 sp = arglist.list;
9733                 while (sp) {
9734                         fdprintf(preverrout_fd, "%s%s",
9735                                 pfx,
9736                                 /* always quote if matches reserved word: */
9737                                 findkwd(sp->text)
9738                                 ? single_quote(sp->text)
9739                                 : maybe_single_quote(sp->text)
9740                         );
9741                         sp = sp->next;
9742                         pfx = " ";
9743                 }
9744                 safe_write(preverrout_fd, "\n", 1);
9745         }
9746
9747         cmd_is_exec = 0;
9748         spclbltin = -1;
9749
9750         /* Now locate the command. */
9751         if (argc) {
9752                 int cmd_flag = DO_ERR;
9753 #if ENABLE_ASH_CMDCMD
9754                 const char *oldpath = path + 5;
9755 #endif
9756                 path += 5;
9757                 for (;;) {
9758                         find_command(argv[0], &cmdentry, cmd_flag, path);
9759                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9760                                 flush_stdout_stderr();
9761                                 status = 127;
9762                                 goto bail;
9763                         }
9764
9765                         /* implement bltin and command here */
9766                         if (cmdentry.cmdtype != CMDBUILTIN)
9767                                 break;
9768                         if (spclbltin < 0)
9769                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9770                         if (cmdentry.u.cmd == EXECCMD)
9771                                 cmd_is_exec = 1;
9772 #if ENABLE_ASH_CMDCMD
9773                         if (cmdentry.u.cmd == COMMANDCMD) {
9774                                 path = oldpath;
9775                                 nargv = parse_command_args(argv, &path);
9776                                 if (!nargv)
9777                                         break;
9778                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9779                                  * nargv => "PROG". path is updated if -p.
9780                                  */
9781                                 argc -= nargv - argv;
9782                                 argv = nargv;
9783                                 cmd_flag |= DO_NOFUNC;
9784                         } else
9785 #endif
9786                                 break;
9787                 }
9788         }
9789
9790         if (status) {
9791  bail:
9792                 exitstatus = status;
9793
9794                 /* We have a redirection error. */
9795                 if (spclbltin > 0)
9796                         raise_exception(EXERROR);
9797
9798                 goto out;
9799         }
9800
9801         /* Execute the command. */
9802         switch (cmdentry.cmdtype) {
9803         default: {
9804
9805 #if ENABLE_FEATURE_SH_NOFORK
9806 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9807  *     around run_nofork_applet() call.
9808  * (2) Should this check also be done in forkshell()?
9809  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9810  */
9811                 /* find_command() encodes applet_no as (-2 - applet_no) */
9812                 int applet_no = (- cmdentry.u.index - 2);
9813                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9814                         listsetvar(varlist.list, VEXPORT|VSTACK);
9815                         /* run <applet>_main() */
9816                         status = run_nofork_applet(applet_no, argv);
9817                         break;
9818                 }
9819 #endif
9820                 /* Can we avoid forking off? For example, very last command
9821                  * in a script or a subshell does not need forking,
9822                  * we can just exec it.
9823                  */
9824                 if (!(flags & EV_EXIT) || may_have_traps) {
9825                         /* No, forking off a child is necessary */
9826                         INT_OFF;
9827                         get_tty_state();
9828                         jp = makejob(/*cmd,*/ 1);
9829                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9830                                 /* parent */
9831                                 status = waitforjob(jp);
9832                                 INT_ON;
9833                                 TRACE(("forked child exited with %d\n", status));
9834                                 break;
9835                         }
9836                         /* child */
9837                         FORCE_INT_ON;
9838                         /* fall through to exec'ing external program */
9839                 }
9840                 listsetvar(varlist.list, VEXPORT|VSTACK);
9841                 shellexec(argv[0], argv, path, cmdentry.u.index);
9842                 /* NOTREACHED */
9843         } /* default */
9844         case CMDBUILTIN:
9845                 if (spclbltin > 0 || argc == 0) {
9846                         poplocalvars(1);
9847                         if (cmd_is_exec && argc > 1)
9848                                 listsetvar(varlist.list, VEXPORT);
9849                 }
9850
9851                 /* Tight loop with builtins only:
9852                  * "while kill -0 $child; do true; done"
9853                  * will never exit even if $child died, unless we do this
9854                  * to reap the zombie and make kill detect that it's gone: */
9855                 dowait(DOWAIT_NONBLOCK, NULL);
9856
9857                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9858                         if (exception_type == EXERROR && spclbltin <= 0) {
9859                                 FORCE_INT_ON;
9860                                 goto readstatus;
9861                         }
9862  raise:
9863                         longjmp(exception_handler->loc, 1);
9864                 }
9865                 goto readstatus;
9866
9867         case CMDFUNCTION:
9868                 poplocalvars(1);
9869                 /* See above for the rationale */
9870                 dowait(DOWAIT_NONBLOCK, NULL);
9871                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9872                         goto raise;
9873  readstatus:
9874                 status = exitstatus;
9875                 break;
9876         } /* switch */
9877
9878  out:
9879         if (cmd->ncmd.redirect)
9880                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9881         unwindlocalvars(localvar_stop);
9882         if (lastarg) {
9883                 /* dsl: I think this is intended to be used to support
9884                  * '_' in 'vi' command mode during line editing...
9885                  * However I implemented that within libedit itself.
9886                  */
9887                 setvar0("_", lastarg);
9888         }
9889         popstackmark(&smark);
9890
9891         return status;
9892 }
9893
9894 static int
9895 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9896 {
9897         char *volatile savecmdname;
9898         struct jmploc *volatile savehandler;
9899         struct jmploc jmploc;
9900         int status;
9901         int i;
9902
9903         savecmdname = commandname;
9904         savehandler = exception_handler;
9905         i = setjmp(jmploc.loc);
9906         if (i)
9907                 goto cmddone;
9908         exception_handler = &jmploc;
9909         commandname = argv[0];
9910         argptr = argv + 1;
9911         optptr = NULL;                  /* initialize nextopt */
9912         if (cmd == EVALCMD)
9913                 status = evalcmd(argc, argv, flags);
9914         else
9915                 status = (*cmd->builtin)(argc, argv);
9916         flush_stdout_stderr();
9917         status |= ferror(stdout);
9918         exitstatus = status;
9919  cmddone:
9920         clearerr(stdout);
9921         commandname = savecmdname;
9922         exception_handler = savehandler;
9923
9924         return i;
9925 }
9926
9927 static int
9928 goodname(const char *p)
9929 {
9930         return endofname(p)[0] == '\0';
9931 }
9932
9933
9934 /*
9935  * Search for a command.  This is called before we fork so that the
9936  * location of the command will be available in the parent as well as
9937  * the child.  The check for "goodname" is an overly conservative
9938  * check that the name will not be subject to expansion.
9939  */
9940 static void
9941 prehash(union node *n)
9942 {
9943         struct cmdentry entry;
9944
9945         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9946                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9947 }
9948
9949
9950 /* ============ Builtin commands
9951  *
9952  * Builtin commands whose functions are closely tied to evaluation
9953  * are implemented here.
9954  */
9955
9956 /*
9957  * Handle break and continue commands.  Break, continue, and return are
9958  * all handled by setting the evalskip flag.  The evaluation routines
9959  * above all check this flag, and if it is set they start skipping
9960  * commands rather than executing them.  The variable skipcount is
9961  * the number of loops to break/continue, or the number of function
9962  * levels to return.  (The latter is always 1.)  It should probably
9963  * be an error to break out of more loops than exist, but it isn't
9964  * in the standard shell so we don't make it one here.
9965  */
9966 static int FAST_FUNC
9967 breakcmd(int argc UNUSED_PARAM, char **argv)
9968 {
9969         int n = argv[1] ? number(argv[1]) : 1;
9970
9971         if (n <= 0)
9972                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9973         if (n > loopnest)
9974                 n = loopnest;
9975         if (n > 0) {
9976                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9977                 skipcount = n;
9978         }
9979         return 0;
9980 }
9981
9982
9983 /*
9984  * This implements the input routines used by the parser.
9985  */
9986
9987 enum {
9988         INPUT_PUSH_FILE = 1,
9989         INPUT_NOFILE_OK = 2,
9990 };
9991
9992 static smallint checkkwd;
9993 /* values of checkkwd variable */
9994 #define CHKALIAS        0x1
9995 #define CHKKWD          0x2
9996 #define CHKNL           0x4
9997 #define CHKEOFMARK      0x8
9998
9999 /*
10000  * Push a string back onto the input at this current parsefile level.
10001  * We handle aliases this way.
10002  */
10003 #if !ENABLE_ASH_ALIAS
10004 #define pushstring(s, ap) pushstring(s)
10005 #endif
10006 static void
10007 pushstring(char *s, struct alias *ap)
10008 {
10009         struct strpush *sp;
10010         int len;
10011
10012         len = strlen(s);
10013         INT_OFF;
10014         if (g_parsefile->strpush) {
10015                 sp = ckzalloc(sizeof(*sp));
10016                 sp->prev = g_parsefile->strpush;
10017         } else {
10018                 sp = &(g_parsefile->basestrpush);
10019         }
10020         g_parsefile->strpush = sp;
10021         sp->prev_string = g_parsefile->next_to_pgetc;
10022         sp->prev_left_in_line = g_parsefile->left_in_line;
10023         sp->unget = g_parsefile->unget;
10024         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10025 #if ENABLE_ASH_ALIAS
10026         sp->ap = ap;
10027         if (ap) {
10028                 ap->flag |= ALIASINUSE;
10029                 sp->string = s;
10030         }
10031 #endif
10032         g_parsefile->next_to_pgetc = s;
10033         g_parsefile->left_in_line = len;
10034         g_parsefile->unget = 0;
10035         INT_ON;
10036 }
10037
10038 static void
10039 popstring(void)
10040 {
10041         struct strpush *sp = g_parsefile->strpush;
10042
10043         INT_OFF;
10044 #if ENABLE_ASH_ALIAS
10045         if (sp->ap) {
10046                 if (g_parsefile->next_to_pgetc[-1] == ' '
10047                  || g_parsefile->next_to_pgetc[-1] == '\t'
10048                 ) {
10049                         checkkwd |= CHKALIAS;
10050                 }
10051                 if (sp->string != sp->ap->val) {
10052                         free(sp->string);
10053                 }
10054                 sp->ap->flag &= ~ALIASINUSE;
10055                 if (sp->ap->flag & ALIASDEAD) {
10056                         unalias(sp->ap->name);
10057                 }
10058         }
10059 #endif
10060         g_parsefile->next_to_pgetc = sp->prev_string;
10061         g_parsefile->left_in_line = sp->prev_left_in_line;
10062         g_parsefile->unget = sp->unget;
10063         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10064         g_parsefile->strpush = sp->prev;
10065         if (sp != &(g_parsefile->basestrpush))
10066                 free(sp);
10067         INT_ON;
10068 }
10069
10070 static int
10071 preadfd(void)
10072 {
10073         int nr;
10074         char *buf = g_parsefile->buf;
10075
10076         g_parsefile->next_to_pgetc = buf;
10077 #if ENABLE_FEATURE_EDITING
10078  retry:
10079         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10080                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10081         else {
10082                 int timeout = -1;
10083 # if ENABLE_ASH_IDLE_TIMEOUT
10084                 if (iflag) {
10085                         const char *tmout_var = lookupvar("TMOUT");
10086                         if (tmout_var) {
10087                                 timeout = atoi(tmout_var) * 1000;
10088                                 if (timeout <= 0)
10089                                         timeout = -1;
10090                         }
10091                 }
10092 # endif
10093 # if ENABLE_FEATURE_TAB_COMPLETION
10094                 line_input_state->path_lookup = pathval();
10095 # endif
10096                 reinit_unicode_for_ash();
10097                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10098                 if (nr == 0) {
10099                         /* ^C pressed, "convert" to SIGINT */
10100                         write(STDOUT_FILENO, "^C", 2);
10101                         if (trap[SIGINT]) {
10102                                 buf[0] = '\n';
10103                                 buf[1] = '\0';
10104                                 raise(SIGINT);
10105                                 return 1;
10106                         }
10107                         exitstatus = 128 + SIGINT;
10108                         bb_putchar('\n');
10109                         goto retry;
10110                 }
10111                 if (nr < 0) {
10112                         if (errno == 0) {
10113                                 /* Ctrl+D pressed */
10114                                 nr = 0;
10115                         }
10116 # if ENABLE_ASH_IDLE_TIMEOUT
10117                         else if (errno == EAGAIN && timeout > 0) {
10118                                 puts("\007timed out waiting for input: auto-logout");
10119                                 exitshell();
10120                         }
10121 # endif
10122                 }
10123         }
10124 #else
10125         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10126 #endif
10127
10128 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10129         if (nr < 0) {
10130                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10131                         int flags = fcntl(0, F_GETFL);
10132                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10133                                 flags &= ~O_NONBLOCK;
10134                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10135                                         out2str("sh: turning off NDELAY mode\n");
10136                                         goto retry;
10137                                 }
10138                         }
10139                 }
10140         }
10141 #endif
10142         return nr;
10143 }
10144
10145 /*
10146  * Refill the input buffer and return the next input character:
10147  *
10148  * 1) If a string was pushed back on the input, pop it;
10149  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10150  *    or we are reading from a string so we can't refill the buffer,
10151  *    return EOF.
10152  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10153  * 4) Process input up to the next newline, deleting nul characters.
10154  */
10155 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10156 #define pgetc_debug(...) ((void)0)
10157 static int pgetc(void);
10158 static int
10159 preadbuffer(void)
10160 {
10161         char *q;
10162         int more;
10163
10164         if (g_parsefile->strpush) {
10165 #if ENABLE_ASH_ALIAS
10166                 if (g_parsefile->left_in_line == -1
10167                  && g_parsefile->strpush->ap
10168                  && g_parsefile->next_to_pgetc[-1] != ' '
10169                  && g_parsefile->next_to_pgetc[-1] != '\t'
10170                 ) {
10171                         pgetc_debug("preadbuffer PEOA");
10172                         return PEOA;
10173                 }
10174 #endif
10175                 popstring();
10176                 return pgetc();
10177         }
10178         /* on both branches above g_parsefile->left_in_line < 0.
10179          * "pgetc" needs refilling.
10180          */
10181
10182         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10183          * pungetc() may increment it a few times.
10184          * Assuming it won't increment it to less than -90.
10185          */
10186         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10187                 pgetc_debug("preadbuffer PEOF1");
10188                 /* even in failure keep left_in_line and next_to_pgetc
10189                  * in lock step, for correct multi-layer pungetc.
10190                  * left_in_line was decremented before preadbuffer(),
10191                  * must inc next_to_pgetc: */
10192                 g_parsefile->next_to_pgetc++;
10193                 return PEOF;
10194         }
10195
10196         more = g_parsefile->left_in_buffer;
10197         if (more <= 0) {
10198                 flush_stdout_stderr();
10199  again:
10200                 more = preadfd();
10201                 if (more <= 0) {
10202                         /* don't try reading again */
10203                         g_parsefile->left_in_line = -99;
10204                         pgetc_debug("preadbuffer PEOF2");
10205                         g_parsefile->next_to_pgetc++;
10206                         return PEOF;
10207                 }
10208         }
10209
10210         /* Find out where's the end of line.
10211          * Set g_parsefile->left_in_line
10212          * and g_parsefile->left_in_buffer acordingly.
10213          * NUL chars are deleted.
10214          */
10215         q = g_parsefile->next_to_pgetc;
10216         for (;;) {
10217                 char c;
10218
10219                 more--;
10220
10221                 c = *q;
10222                 if (c == '\0') {
10223                         memmove(q, q + 1, more);
10224                 } else {
10225                         q++;
10226                         if (c == '\n') {
10227                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10228                                 break;
10229                         }
10230                 }
10231
10232                 if (more <= 0) {
10233                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10234                         if (g_parsefile->left_in_line < 0)
10235                                 goto again;
10236                         break;
10237                 }
10238         }
10239         g_parsefile->left_in_buffer = more;
10240
10241         if (vflag) {
10242                 char save = *q;
10243                 *q = '\0';
10244                 out2str(g_parsefile->next_to_pgetc);
10245                 *q = save;
10246         }
10247
10248         pgetc_debug("preadbuffer at %d:%p'%s'",
10249                         g_parsefile->left_in_line,
10250                         g_parsefile->next_to_pgetc,
10251                         g_parsefile->next_to_pgetc);
10252         return (unsigned char)*g_parsefile->next_to_pgetc++;
10253 }
10254
10255 static void
10256 nlprompt(void)
10257 {
10258         g_parsefile->linno++;
10259         setprompt_if(doprompt, 2);
10260 }
10261 static void
10262 nlnoprompt(void)
10263 {
10264         g_parsefile->linno++;
10265         needprompt = doprompt;
10266 }
10267
10268 static int
10269 pgetc(void)
10270 {
10271         int c;
10272
10273         pgetc_debug("pgetc at %d:%p'%s'",
10274                         g_parsefile->left_in_line,
10275                         g_parsefile->next_to_pgetc,
10276                         g_parsefile->next_to_pgetc);
10277         if (g_parsefile->unget)
10278                 return g_parsefile->lastc[--g_parsefile->unget];
10279
10280         if (--g_parsefile->left_in_line >= 0)
10281                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10282         else
10283                 c = preadbuffer();
10284
10285         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10286         g_parsefile->lastc[0] = c;
10287
10288         return c;
10289 }
10290
10291 #if ENABLE_ASH_ALIAS
10292 static int
10293 pgetc_without_PEOA(void)
10294 {
10295         int c;
10296         do {
10297                 pgetc_debug("pgetc at %d:%p'%s'",
10298                                 g_parsefile->left_in_line,
10299                                 g_parsefile->next_to_pgetc,
10300                                 g_parsefile->next_to_pgetc);
10301                 c = pgetc();
10302         } while (c == PEOA);
10303         return c;
10304 }
10305 #else
10306 # define pgetc_without_PEOA() pgetc()
10307 #endif
10308
10309 /*
10310  * Undo a call to pgetc.  Only two characters may be pushed back.
10311  * PEOF may be pushed back.
10312  */
10313 static void
10314 pungetc(void)
10315 {
10316         g_parsefile->unget++;
10317 }
10318
10319 /* This one eats backslash+newline */
10320 static int
10321 pgetc_eatbnl(void)
10322 {
10323         int c;
10324
10325         while ((c = pgetc()) == '\\') {
10326                 if (pgetc() != '\n') {
10327                         pungetc();
10328                         break;
10329                 }
10330
10331                 nlprompt();
10332         }
10333
10334         return c;
10335 }
10336
10337 /*
10338  * To handle the "." command, a stack of input files is used.  Pushfile
10339  * adds a new entry to the stack and popfile restores the previous level.
10340  */
10341 static void
10342 pushfile(void)
10343 {
10344         struct parsefile *pf;
10345
10346         pf = ckzalloc(sizeof(*pf));
10347         pf->prev = g_parsefile;
10348         pf->pf_fd = -1;
10349         /*pf->strpush = NULL; - ckzalloc did it */
10350         /*pf->basestrpush.prev = NULL;*/
10351         /*pf->unget = 0;*/
10352         g_parsefile = pf;
10353 }
10354
10355 static void
10356 popfile(void)
10357 {
10358         struct parsefile *pf = g_parsefile;
10359
10360         if (pf == &basepf)
10361                 return;
10362
10363         INT_OFF;
10364         if (pf->pf_fd >= 0)
10365                 close(pf->pf_fd);
10366         free(pf->buf);
10367         while (pf->strpush)
10368                 popstring();
10369         g_parsefile = pf->prev;
10370         free(pf);
10371         INT_ON;
10372 }
10373
10374 /*
10375  * Return to top level.
10376  */
10377 static void
10378 popallfiles(void)
10379 {
10380         while (g_parsefile != &basepf)
10381                 popfile();
10382 }
10383
10384 /*
10385  * Close the file(s) that the shell is reading commands from.  Called
10386  * after a fork is done.
10387  */
10388 static void
10389 closescript(void)
10390 {
10391         popallfiles();
10392         if (g_parsefile->pf_fd > 0) {
10393                 close(g_parsefile->pf_fd);
10394                 g_parsefile->pf_fd = 0;
10395         }
10396 }
10397
10398 /*
10399  * Like setinputfile, but takes an open file descriptor.  Call this with
10400  * interrupts off.
10401  */
10402 static void
10403 setinputfd(int fd, int push)
10404 {
10405         if (push) {
10406                 pushfile();
10407                 g_parsefile->buf = NULL;
10408         }
10409         g_parsefile->pf_fd = fd;
10410         if (g_parsefile->buf == NULL)
10411                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10412         g_parsefile->left_in_buffer = 0;
10413         g_parsefile->left_in_line = 0;
10414         g_parsefile->linno = 1;
10415 }
10416
10417 /*
10418  * Set the input to take input from a file.  If push is set, push the
10419  * old input onto the stack first.
10420  */
10421 static int
10422 setinputfile(const char *fname, int flags)
10423 {
10424         int fd;
10425
10426         INT_OFF;
10427         fd = open(fname, O_RDONLY);
10428         if (fd < 0) {
10429                 if (flags & INPUT_NOFILE_OK)
10430                         goto out;
10431                 exitstatus = 127;
10432                 ash_msg_and_raise_error("can't open '%s'", fname);
10433         }
10434         if (fd < 10)
10435                 fd = savefd(fd);
10436         else
10437                 close_on_exec_on(fd);
10438         setinputfd(fd, flags & INPUT_PUSH_FILE);
10439  out:
10440         INT_ON;
10441         return fd;
10442 }
10443
10444 /*
10445  * Like setinputfile, but takes input from a string.
10446  */
10447 static void
10448 setinputstring(char *string)
10449 {
10450         INT_OFF;
10451         pushfile();
10452         g_parsefile->next_to_pgetc = string;
10453         g_parsefile->left_in_line = strlen(string);
10454         g_parsefile->buf = NULL;
10455         g_parsefile->linno = 1;
10456         INT_ON;
10457 }
10458
10459
10460 /*
10461  * Routines to check for mail.
10462  */
10463
10464 #if ENABLE_ASH_MAIL
10465
10466 /* Hash of mtimes of mailboxes */
10467 static unsigned mailtime_hash;
10468 /* Set if MAIL or MAILPATH is changed. */
10469 static smallint mail_var_path_changed;
10470
10471 /*
10472  * Print appropriate message(s) if mail has arrived.
10473  * If mail_var_path_changed is set,
10474  * then the value of MAIL has mail_var_path_changed,
10475  * so we just update the values.
10476  */
10477 static void
10478 chkmail(void)
10479 {
10480         const char *mpath;
10481         char *p;
10482         char *q;
10483         unsigned new_hash;
10484         struct stackmark smark;
10485         struct stat statb;
10486
10487         setstackmark(&smark);
10488         mpath = mpathset() ? mpathval() : mailval();
10489         new_hash = 0;
10490         for (;;) {
10491                 p = path_advance(&mpath, nullstr);
10492                 if (p == NULL)
10493                         break;
10494                 if (*p == '\0')
10495                         continue;
10496                 for (q = p; *q; q++)
10497                         continue;
10498 #if DEBUG
10499                 if (q[-1] != '/')
10500                         abort();
10501 #endif
10502                 q[-1] = '\0';                   /* delete trailing '/' */
10503                 if (stat(p, &statb) < 0) {
10504                         continue;
10505                 }
10506                 /* Very simplistic "hash": just a sum of all mtimes */
10507                 new_hash += (unsigned)statb.st_mtime;
10508         }
10509         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10510                 if (mailtime_hash != 0)
10511                         out2str("you have mail\n");
10512                 mailtime_hash = new_hash;
10513         }
10514         mail_var_path_changed = 0;
10515         popstackmark(&smark);
10516 }
10517
10518 static void FAST_FUNC
10519 changemail(const char *val UNUSED_PARAM)
10520 {
10521         mail_var_path_changed = 1;
10522 }
10523
10524 #endif /* ASH_MAIL */
10525
10526
10527 /* ============ ??? */
10528
10529 /*
10530  * Set the shell parameters.
10531  */
10532 static void
10533 setparam(char **argv)
10534 {
10535         char **newparam;
10536         char **ap;
10537         int nparam;
10538
10539         for (nparam = 0; argv[nparam]; nparam++)
10540                 continue;
10541         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10542         while (*argv) {
10543                 *ap++ = ckstrdup(*argv++);
10544         }
10545         *ap = NULL;
10546         freeparam(&shellparam);
10547         shellparam.malloced = 1;
10548         shellparam.nparam = nparam;
10549         shellparam.p = newparam;
10550 #if ENABLE_ASH_GETOPTS
10551         shellparam.optind = 1;
10552         shellparam.optoff = -1;
10553 #endif
10554 }
10555
10556 /*
10557  * Process shell options.  The global variable argptr contains a pointer
10558  * to the argument list; we advance it past the options.
10559  *
10560  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10561  * For a non-interactive shell, an error condition encountered
10562  * by a special built-in ... shall cause the shell to write a diagnostic message
10563  * to standard error and exit as shown in the following table:
10564  * Error                                           Special Built-In
10565  * ...
10566  * Utility syntax error (option or operand error)  Shall exit
10567  * ...
10568  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10569  * we see that bash does not do that (set "finishes" with error code 1 instead,
10570  * and shell continues), and people rely on this behavior!
10571  * Testcase:
10572  * set -o barfoo 2>/dev/null
10573  * echo $?
10574  *
10575  * Oh well. Let's mimic that.
10576  */
10577 static int
10578 plus_minus_o(char *name, int val)
10579 {
10580         int i;
10581
10582         if (name) {
10583                 for (i = 0; i < NOPTS; i++) {
10584                         if (strcmp(name, optnames(i)) == 0) {
10585                                 optlist[i] = val;
10586                                 return 0;
10587                         }
10588                 }
10589                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10590                 return 1;
10591         }
10592         for (i = 0; i < NOPTS; i++) {
10593                 if (val) {
10594                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10595                 } else {
10596                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10597                 }
10598         }
10599         return 0;
10600 }
10601 static void
10602 setoption(int flag, int val)
10603 {
10604         int i;
10605
10606         for (i = 0; i < NOPTS; i++) {
10607                 if (optletters(i) == flag) {
10608                         optlist[i] = val;
10609                         return;
10610                 }
10611         }
10612         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10613         /* NOTREACHED */
10614 }
10615 static int
10616 options(int cmdline)
10617 {
10618         char *p;
10619         int val;
10620         int c;
10621
10622         if (cmdline)
10623                 minusc = NULL;
10624         while ((p = *argptr) != NULL) {
10625                 c = *p++;
10626                 if (c != '-' && c != '+')
10627                         break;
10628                 argptr++;
10629                 val = 0; /* val = 0 if c == '+' */
10630                 if (c == '-') {
10631                         val = 1;
10632                         if (p[0] == '\0' || LONE_DASH(p)) {
10633                                 if (!cmdline) {
10634                                         /* "-" means turn off -x and -v */
10635                                         if (p[0] == '\0')
10636                                                 xflag = vflag = 0;
10637                                         /* "--" means reset params */
10638                                         else if (*argptr == NULL)
10639                                                 setparam(argptr);
10640                                 }
10641                                 break;    /* "-" or "--" terminates options */
10642                         }
10643                 }
10644                 /* first char was + or - */
10645                 while ((c = *p++) != '\0') {
10646                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10647                         if (c == 'c' && cmdline) {
10648                                 minusc = p;     /* command is after shell args */
10649                         } else if (c == 'o') {
10650                                 if (plus_minus_o(*argptr, val)) {
10651                                         /* it already printed err message */
10652                                         return 1; /* error */
10653                                 }
10654                                 if (*argptr)
10655                                         argptr++;
10656                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10657                                 isloginsh = 1;
10658                         /* bash does not accept +-login, we also won't */
10659                         } else if (cmdline && val && (c == '-')) { /* long options */
10660                                 if (strcmp(p, "login") == 0)
10661                                         isloginsh = 1;
10662                                 break;
10663                         } else {
10664                                 setoption(c, val);
10665                         }
10666                 }
10667         }
10668         return 0;
10669 }
10670
10671 /*
10672  * The shift builtin command.
10673  */
10674 static int FAST_FUNC
10675 shiftcmd(int argc UNUSED_PARAM, char **argv)
10676 {
10677         int n;
10678         char **ap1, **ap2;
10679
10680         n = 1;
10681         if (argv[1])
10682                 n = number(argv[1]);
10683         if (n > shellparam.nparam)
10684                 n = 0; /* bash compat, was = shellparam.nparam; */
10685         INT_OFF;
10686         shellparam.nparam -= n;
10687         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10688                 if (shellparam.malloced)
10689                         free(*ap1);
10690         }
10691         ap2 = shellparam.p;
10692         while ((*ap2++ = *ap1++) != NULL)
10693                 continue;
10694 #if ENABLE_ASH_GETOPTS
10695         shellparam.optind = 1;
10696         shellparam.optoff = -1;
10697 #endif
10698         INT_ON;
10699         return 0;
10700 }
10701
10702 /*
10703  * POSIX requires that 'set' (but not export or readonly) output the
10704  * variables in lexicographic order - by the locale's collating order (sigh).
10705  * Maybe we could keep them in an ordered balanced binary tree
10706  * instead of hashed lists.
10707  * For now just roll 'em through qsort for printing...
10708  */
10709 static int
10710 showvars(const char *sep_prefix, int on, int off)
10711 {
10712         const char *sep;
10713         char **ep, **epend;
10714
10715         ep = listvars(on, off, &epend);
10716         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10717
10718         sep = *sep_prefix ? " " : sep_prefix;
10719
10720         for (; ep < epend; ep++) {
10721                 const char *p;
10722                 const char *q;
10723
10724                 p = strchrnul(*ep, '=');
10725                 q = nullstr;
10726                 if (*p)
10727                         q = single_quote(++p);
10728                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10729         }
10730         return 0;
10731 }
10732
10733 /*
10734  * The set command builtin.
10735  */
10736 static int FAST_FUNC
10737 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10738 {
10739         int retval;
10740
10741         if (!argv[1])
10742                 return showvars(nullstr, 0, VUNSET);
10743
10744         INT_OFF;
10745         retval = options(/*cmdline:*/ 0);
10746         if (retval == 0) { /* if no parse error... */
10747                 optschanged();
10748                 if (*argptr != NULL) {
10749                         setparam(argptr);
10750                 }
10751         }
10752         INT_ON;
10753         return retval;
10754 }
10755
10756 #if ENABLE_ASH_RANDOM_SUPPORT
10757 static void FAST_FUNC
10758 change_random(const char *value)
10759 {
10760         uint32_t t;
10761
10762         if (value == NULL) {
10763                 /* "get", generate */
10764                 t = next_random(&random_gen);
10765                 /* set without recursion */
10766                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10767                 vrandom.flags &= ~VNOFUNC;
10768         } else {
10769                 /* set/reset */
10770                 t = strtoul(value, NULL, 10);
10771                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10772         }
10773 }
10774 #endif
10775
10776 #if ENABLE_ASH_GETOPTS
10777 static int
10778 getopts(char *optstr, char *optvar, char **optfirst)
10779 {
10780         char *p, *q;
10781         char c = '?';
10782         int done = 0;
10783         char sbuf[2];
10784         char **optnext;
10785         int ind = shellparam.optind;
10786         int off = shellparam.optoff;
10787
10788         sbuf[1] = '\0';
10789
10790         shellparam.optind = -1;
10791         optnext = optfirst + ind - 1;
10792
10793         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10794                 p = NULL;
10795         else
10796                 p = optnext[-1] + off;
10797         if (p == NULL || *p == '\0') {
10798                 /* Current word is done, advance */
10799                 p = *optnext;
10800                 if (p == NULL || *p != '-' || *++p == '\0') {
10801  atend:
10802                         p = NULL;
10803                         done = 1;
10804                         goto out;
10805                 }
10806                 optnext++;
10807                 if (LONE_DASH(p))        /* check for "--" */
10808                         goto atend;
10809         }
10810
10811         c = *p++;
10812         for (q = optstr; *q != c;) {
10813                 if (*q == '\0') {
10814                         if (optstr[0] == ':') {
10815                                 sbuf[0] = c;
10816                                 /*sbuf[1] = '\0'; - already is */
10817                                 setvar0("OPTARG", sbuf);
10818                         } else {
10819                                 fprintf(stderr, "Illegal option -%c\n", c);
10820                                 unsetvar("OPTARG");
10821                         }
10822                         c = '?';
10823                         goto out;
10824                 }
10825                 if (*++q == ':')
10826                         q++;
10827         }
10828
10829         if (*++q == ':') {
10830                 if (*p == '\0' && (p = *optnext) == NULL) {
10831                         if (optstr[0] == ':') {
10832                                 sbuf[0] = c;
10833                                 /*sbuf[1] = '\0'; - already is */
10834                                 setvar0("OPTARG", sbuf);
10835                                 c = ':';
10836                         } else {
10837                                 fprintf(stderr, "No arg for -%c option\n", c);
10838                                 unsetvar("OPTARG");
10839                                 c = '?';
10840                         }
10841                         goto out;
10842                 }
10843
10844                 if (p == *optnext)
10845                         optnext++;
10846                 setvar0("OPTARG", p);
10847                 p = NULL;
10848         } else
10849                 setvar0("OPTARG", nullstr);
10850  out:
10851         ind = optnext - optfirst + 1;
10852         setvar("OPTIND", itoa(ind), VNOFUNC);
10853         sbuf[0] = c;
10854         /*sbuf[1] = '\0'; - already is */
10855         setvar0(optvar, sbuf);
10856
10857         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10858         shellparam.optind = ind;
10859
10860         return done;
10861 }
10862
10863 /*
10864  * The getopts builtin.  Shellparam.optnext points to the next argument
10865  * to be processed.  Shellparam.optptr points to the next character to
10866  * be processed in the current argument.  If shellparam.optnext is NULL,
10867  * then it's the first time getopts has been called.
10868  */
10869 static int FAST_FUNC
10870 getoptscmd(int argc, char **argv)
10871 {
10872         char **optbase;
10873
10874         if (argc < 3)
10875                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10876         if (argc == 3) {
10877                 optbase = shellparam.p;
10878                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10879                         shellparam.optind = 1;
10880                         shellparam.optoff = -1;
10881                 }
10882         } else {
10883                 optbase = &argv[3];
10884                 if ((unsigned)shellparam.optind > argc - 2) {
10885                         shellparam.optind = 1;
10886                         shellparam.optoff = -1;
10887                 }
10888         }
10889
10890         return getopts(argv[1], argv[2], optbase);
10891 }
10892 #endif /* ASH_GETOPTS */
10893
10894
10895 /* ============ Shell parser */
10896
10897 struct heredoc {
10898         struct heredoc *next;   /* next here document in list */
10899         union node *here;       /* redirection node */
10900         char *eofmark;          /* string indicating end of input */
10901         smallint striptabs;     /* if set, strip leading tabs */
10902 };
10903
10904 static smallint tokpushback;           /* last token pushed back */
10905 static smallint quoteflag;             /* set if (part of) last token was quoted */
10906 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10907 static struct heredoc *heredoclist;    /* list of here documents to read */
10908 static char *wordtext;                 /* text of last word returned by readtoken */
10909 static struct nodelist *backquotelist;
10910 static union node *redirnode;
10911 static struct heredoc *heredoc;
10912
10913 static const char *
10914 tokname(char *buf, int tok)
10915 {
10916         if (tok < TSEMI)
10917                 return tokname_array[tok];
10918         sprintf(buf, "\"%s\"", tokname_array[tok]);
10919         return buf;
10920 }
10921
10922 /* raise_error_unexpected_syntax:
10923  * Called when an unexpected token is read during the parse.  The argument
10924  * is the token that is expected, or -1 if more than one type of token can
10925  * occur at this point.
10926  */
10927 static void raise_error_unexpected_syntax(int) NORETURN;
10928 static void
10929 raise_error_unexpected_syntax(int token)
10930 {
10931         char msg[64];
10932         char buf[16];
10933         int l;
10934
10935         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10936         if (token >= 0)
10937                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10938         raise_error_syntax(msg);
10939         /* NOTREACHED */
10940 }
10941
10942 /* parsing is heavily cross-recursive, need these forward decls */
10943 static union node *andor(void);
10944 static union node *pipeline(void);
10945 static union node *parse_command(void);
10946 static void parseheredoc(void);
10947 static int peektoken(void);
10948 static int readtoken(void);
10949
10950 static union node *
10951 list(int nlflag)
10952 {
10953         union node *n1, *n2, *n3;
10954         int tok;
10955
10956         n1 = NULL;
10957         for (;;) {
10958                 switch (peektoken()) {
10959                 case TNL:
10960                         if (!(nlflag & 1))
10961                                 break;
10962                         parseheredoc();
10963                         return n1;
10964
10965                 case TEOF:
10966                         if (!n1 && (nlflag & 1))
10967                                 n1 = NODE_EOF;
10968                         parseheredoc();
10969                         return n1;
10970                 }
10971
10972                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10973                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10974                         return n1;
10975                 nlflag |= 2;
10976
10977                 n2 = andor();
10978                 tok = readtoken();
10979                 if (tok == TBACKGND) {
10980                         if (n2->type == NPIPE) {
10981                                 n2->npipe.pipe_backgnd = 1;
10982                         } else {
10983                                 if (n2->type != NREDIR) {
10984                                         n3 = stzalloc(sizeof(struct nredir));
10985                                         n3->nredir.n = n2;
10986                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10987                                         n2 = n3;
10988                                 }
10989                                 n2->type = NBACKGND;
10990                         }
10991                 }
10992                 if (n1 == NULL) {
10993                         n1 = n2;
10994                 } else {
10995                         n3 = stzalloc(sizeof(struct nbinary));
10996                         n3->type = NSEMI;
10997                         n3->nbinary.ch1 = n1;
10998                         n3->nbinary.ch2 = n2;
10999                         n1 = n3;
11000                 }
11001                 switch (tok) {
11002                 case TNL:
11003                 case TEOF:
11004                         tokpushback = 1;
11005                         /* fall through */
11006                 case TBACKGND:
11007                 case TSEMI:
11008                         break;
11009                 default:
11010                         if ((nlflag & 1))
11011                                 raise_error_unexpected_syntax(-1);
11012                         tokpushback = 1;
11013                         return n1;
11014                 }
11015         }
11016 }
11017
11018 static union node *
11019 andor(void)
11020 {
11021         union node *n1, *n2, *n3;
11022         int t;
11023
11024         n1 = pipeline();
11025         for (;;) {
11026                 t = readtoken();
11027                 if (t == TAND) {
11028                         t = NAND;
11029                 } else if (t == TOR) {
11030                         t = NOR;
11031                 } else {
11032                         tokpushback = 1;
11033                         return n1;
11034                 }
11035                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11036                 n2 = pipeline();
11037                 n3 = stzalloc(sizeof(struct nbinary));
11038                 n3->type = t;
11039                 n3->nbinary.ch1 = n1;
11040                 n3->nbinary.ch2 = n2;
11041                 n1 = n3;
11042         }
11043 }
11044
11045 static union node *
11046 pipeline(void)
11047 {
11048         union node *n1, *n2, *pipenode;
11049         struct nodelist *lp, *prev;
11050         int negate;
11051
11052         negate = 0;
11053         TRACE(("pipeline: entered\n"));
11054         if (readtoken() == TNOT) {
11055                 negate = !negate;
11056                 checkkwd = CHKKWD | CHKALIAS;
11057         } else
11058                 tokpushback = 1;
11059         n1 = parse_command();
11060         if (readtoken() == TPIPE) {
11061                 pipenode = stzalloc(sizeof(struct npipe));
11062                 pipenode->type = NPIPE;
11063                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11064                 lp = stzalloc(sizeof(struct nodelist));
11065                 pipenode->npipe.cmdlist = lp;
11066                 lp->n = n1;
11067                 do {
11068                         prev = lp;
11069                         lp = stzalloc(sizeof(struct nodelist));
11070                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11071                         lp->n = parse_command();
11072                         prev->next = lp;
11073                 } while (readtoken() == TPIPE);
11074                 lp->next = NULL;
11075                 n1 = pipenode;
11076         }
11077         tokpushback = 1;
11078         if (negate) {
11079                 n2 = stzalloc(sizeof(struct nnot));
11080                 n2->type = NNOT;
11081                 n2->nnot.com = n1;
11082                 return n2;
11083         }
11084         return n1;
11085 }
11086
11087 static union node *
11088 makename(void)
11089 {
11090         union node *n;
11091
11092         n = stzalloc(sizeof(struct narg));
11093         n->type = NARG;
11094         /*n->narg.next = NULL; - stzalloc did it */
11095         n->narg.text = wordtext;
11096         n->narg.backquote = backquotelist;
11097         return n;
11098 }
11099
11100 static void
11101 fixredir(union node *n, const char *text, int err)
11102 {
11103         int fd;
11104
11105         TRACE(("Fix redir %s %d\n", text, err));
11106         if (!err)
11107                 n->ndup.vname = NULL;
11108
11109         fd = bb_strtou(text, NULL, 10);
11110         if (!errno && fd >= 0)
11111                 n->ndup.dupfd = fd;
11112         else if (LONE_DASH(text))
11113                 n->ndup.dupfd = -1;
11114         else {
11115                 if (err)
11116                         raise_error_syntax("bad fd number");
11117                 n->ndup.vname = makename();
11118         }
11119 }
11120
11121 static void
11122 parsefname(void)
11123 {
11124         union node *n = redirnode;
11125
11126         if (n->type == NHERE)
11127                 checkkwd = CHKEOFMARK;
11128         if (readtoken() != TWORD)
11129                 raise_error_unexpected_syntax(-1);
11130         if (n->type == NHERE) {
11131                 struct heredoc *here = heredoc;
11132                 struct heredoc *p;
11133
11134                 if (quoteflag == 0)
11135                         n->type = NXHERE;
11136                 TRACE(("Here document %d\n", n->type));
11137                 rmescapes(wordtext, 0);
11138                 here->eofmark = wordtext;
11139                 here->next = NULL;
11140                 if (heredoclist == NULL)
11141                         heredoclist = here;
11142                 else {
11143                         for (p = heredoclist; p->next; p = p->next)
11144                                 continue;
11145                         p->next = here;
11146                 }
11147         } else if (n->type == NTOFD || n->type == NFROMFD) {
11148                 fixredir(n, wordtext, 0);
11149         } else {
11150                 n->nfile.fname = makename();
11151         }
11152 }
11153
11154 static union node *
11155 simplecmd(void)
11156 {
11157         union node *args, **app;
11158         union node *n = NULL;
11159         union node *vars, **vpp;
11160         union node **rpp, *redir;
11161         int savecheckkwd;
11162 #if BASH_TEST2
11163         smallint double_brackets_flag = 0;
11164 #endif
11165         IF_BASH_FUNCTION(smallint function_flag = 0;)
11166
11167         args = NULL;
11168         app = &args;
11169         vars = NULL;
11170         vpp = &vars;
11171         redir = NULL;
11172         rpp = &redir;
11173
11174         savecheckkwd = CHKALIAS;
11175         for (;;) {
11176                 int t;
11177                 checkkwd = savecheckkwd;
11178                 t = readtoken();
11179                 switch (t) {
11180 #if BASH_FUNCTION
11181                 case TFUNCTION:
11182                         if (peektoken() != TWORD)
11183                                 raise_error_unexpected_syntax(TWORD);
11184                         function_flag = 1;
11185                         break;
11186 #endif
11187 #if BASH_TEST2
11188                 case TAND: /* "&&" */
11189                 case TOR: /* "||" */
11190                         if (!double_brackets_flag) {
11191                                 tokpushback = 1;
11192                                 goto out;
11193                         }
11194                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11195 #endif
11196                 case TWORD:
11197                         n = stzalloc(sizeof(struct narg));
11198                         n->type = NARG;
11199                         /*n->narg.next = NULL; - stzalloc did it */
11200                         n->narg.text = wordtext;
11201 #if BASH_TEST2
11202                         if (strcmp("[[", wordtext) == 0)
11203                                 double_brackets_flag = 1;
11204                         else if (strcmp("]]", wordtext) == 0)
11205                                 double_brackets_flag = 0;
11206 #endif
11207                         n->narg.backquote = backquotelist;
11208                         if (savecheckkwd && isassignment(wordtext)) {
11209                                 *vpp = n;
11210                                 vpp = &n->narg.next;
11211                         } else {
11212                                 *app = n;
11213                                 app = &n->narg.next;
11214                                 savecheckkwd = 0;
11215                         }
11216 #if BASH_FUNCTION
11217                         if (function_flag) {
11218                                 checkkwd = CHKNL | CHKKWD;
11219                                 switch (peektoken()) {
11220                                 case TBEGIN:
11221                                 case TIF:
11222                                 case TCASE:
11223                                 case TUNTIL:
11224                                 case TWHILE:
11225                                 case TFOR:
11226                                         goto do_func;
11227                                 case TLP:
11228                                         function_flag = 0;
11229                                         break;
11230                                 case TWORD:
11231                                         if (strcmp("[[", wordtext) == 0)
11232                                                 goto do_func;
11233                                         /* fall through */
11234                                 default:
11235                                         raise_error_unexpected_syntax(-1);
11236                                 }
11237                         }
11238 #endif
11239                         break;
11240                 case TREDIR:
11241                         *rpp = n = redirnode;
11242                         rpp = &n->nfile.next;
11243                         parsefname();   /* read name of redirection file */
11244                         break;
11245                 case TLP:
11246  IF_BASH_FUNCTION(do_func:)
11247                         if (args && app == &args->narg.next
11248                          && !vars && !redir
11249                         ) {
11250                                 struct builtincmd *bcmd;
11251                                 const char *name;
11252
11253                                 /* We have a function */
11254                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11255                                         raise_error_unexpected_syntax(TRP);
11256                                 name = n->narg.text;
11257                                 if (!goodname(name)
11258                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11259                                 ) {
11260                                         raise_error_syntax("bad function name");
11261                                 }
11262                                 n->type = NDEFUN;
11263                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11264                                 n->narg.next = parse_command();
11265                                 return n;
11266                         }
11267                         IF_BASH_FUNCTION(function_flag = 0;)
11268                         /* fall through */
11269                 default:
11270                         tokpushback = 1;
11271                         goto out;
11272                 }
11273         }
11274  out:
11275         *app = NULL;
11276         *vpp = NULL;
11277         *rpp = NULL;
11278         n = stzalloc(sizeof(struct ncmd));
11279         n->type = NCMD;
11280         n->ncmd.args = args;
11281         n->ncmd.assign = vars;
11282         n->ncmd.redirect = redir;
11283         return n;
11284 }
11285
11286 static union node *
11287 parse_command(void)
11288 {
11289         union node *n1, *n2;
11290         union node *ap, **app;
11291         union node *cp, **cpp;
11292         union node *redir, **rpp;
11293         union node **rpp2;
11294         int t;
11295
11296         redir = NULL;
11297         rpp2 = &redir;
11298
11299         switch (readtoken()) {
11300         default:
11301                 raise_error_unexpected_syntax(-1);
11302                 /* NOTREACHED */
11303         case TIF:
11304                 n1 = stzalloc(sizeof(struct nif));
11305                 n1->type = NIF;
11306                 n1->nif.test = list(0);
11307                 if (readtoken() != TTHEN)
11308                         raise_error_unexpected_syntax(TTHEN);
11309                 n1->nif.ifpart = list(0);
11310                 n2 = n1;
11311                 while (readtoken() == TELIF) {
11312                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11313                         n2 = n2->nif.elsepart;
11314                         n2->type = NIF;
11315                         n2->nif.test = list(0);
11316                         if (readtoken() != TTHEN)
11317                                 raise_error_unexpected_syntax(TTHEN);
11318                         n2->nif.ifpart = list(0);
11319                 }
11320                 if (lasttoken == TELSE)
11321                         n2->nif.elsepart = list(0);
11322                 else {
11323                         n2->nif.elsepart = NULL;
11324                         tokpushback = 1;
11325                 }
11326                 t = TFI;
11327                 break;
11328         case TWHILE:
11329         case TUNTIL: {
11330                 int got;
11331                 n1 = stzalloc(sizeof(struct nbinary));
11332                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11333                 n1->nbinary.ch1 = list(0);
11334                 got = readtoken();
11335                 if (got != TDO) {
11336                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11337                                         got == TWORD ? wordtext : ""));
11338                         raise_error_unexpected_syntax(TDO);
11339                 }
11340                 n1->nbinary.ch2 = list(0);
11341                 t = TDONE;
11342                 break;
11343         }
11344         case TFOR:
11345                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11346                         raise_error_syntax("bad for loop variable");
11347                 n1 = stzalloc(sizeof(struct nfor));
11348                 n1->type = NFOR;
11349                 n1->nfor.var = wordtext;
11350                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11351                 if (readtoken() == TIN) {
11352                         app = &ap;
11353                         while (readtoken() == TWORD) {
11354                                 n2 = stzalloc(sizeof(struct narg));
11355                                 n2->type = NARG;
11356                                 /*n2->narg.next = NULL; - stzalloc did it */
11357                                 n2->narg.text = wordtext;
11358                                 n2->narg.backquote = backquotelist;
11359                                 *app = n2;
11360                                 app = &n2->narg.next;
11361                         }
11362                         *app = NULL;
11363                         n1->nfor.args = ap;
11364                         if (lasttoken != TNL && lasttoken != TSEMI)
11365                                 raise_error_unexpected_syntax(-1);
11366                 } else {
11367                         n2 = stzalloc(sizeof(struct narg));
11368                         n2->type = NARG;
11369                         /*n2->narg.next = NULL; - stzalloc did it */
11370                         n2->narg.text = (char *)dolatstr;
11371                         /*n2->narg.backquote = NULL;*/
11372                         n1->nfor.args = n2;
11373                         /*
11374                          * Newline or semicolon here is optional (but note
11375                          * that the original Bourne shell only allowed NL).
11376                          */
11377                         if (lasttoken != TSEMI)
11378                                 tokpushback = 1;
11379                 }
11380                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11381                 if (readtoken() != TDO)
11382                         raise_error_unexpected_syntax(TDO);
11383                 n1->nfor.body = list(0);
11384                 t = TDONE;
11385                 break;
11386         case TCASE:
11387                 n1 = stzalloc(sizeof(struct ncase));
11388                 n1->type = NCASE;
11389                 if (readtoken() != TWORD)
11390                         raise_error_unexpected_syntax(TWORD);
11391                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11392                 n2->type = NARG;
11393                 /*n2->narg.next = NULL; - stzalloc did it */
11394                 n2->narg.text = wordtext;
11395                 n2->narg.backquote = backquotelist;
11396                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11397                 if (readtoken() != TIN)
11398                         raise_error_unexpected_syntax(TIN);
11399                 cpp = &n1->ncase.cases;
11400  next_case:
11401                 checkkwd = CHKNL | CHKKWD;
11402                 t = readtoken();
11403                 while (t != TESAC) {
11404                         if (lasttoken == TLP)
11405                                 readtoken();
11406                         *cpp = cp = stzalloc(sizeof(struct nclist));
11407                         cp->type = NCLIST;
11408                         app = &cp->nclist.pattern;
11409                         for (;;) {
11410                                 *app = ap = stzalloc(sizeof(struct narg));
11411                                 ap->type = NARG;
11412                                 /*ap->narg.next = NULL; - stzalloc did it */
11413                                 ap->narg.text = wordtext;
11414                                 ap->narg.backquote = backquotelist;
11415                                 if (readtoken() != TPIPE)
11416                                         break;
11417                                 app = &ap->narg.next;
11418                                 readtoken();
11419                         }
11420                         //ap->narg.next = NULL;
11421                         if (lasttoken != TRP)
11422                                 raise_error_unexpected_syntax(TRP);
11423                         cp->nclist.body = list(2);
11424
11425                         cpp = &cp->nclist.next;
11426
11427                         checkkwd = CHKNL | CHKKWD;
11428                         t = readtoken();
11429                         if (t != TESAC) {
11430                                 if (t != TENDCASE)
11431                                         raise_error_unexpected_syntax(TENDCASE);
11432                                 goto next_case;
11433                         }
11434                 }
11435                 *cpp = NULL;
11436                 goto redir;
11437         case TLP:
11438                 n1 = stzalloc(sizeof(struct nredir));
11439                 n1->type = NSUBSHELL;
11440                 n1->nredir.n = list(0);
11441                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11442                 t = TRP;
11443                 break;
11444         case TBEGIN:
11445                 n1 = list(0);
11446                 t = TEND;
11447                 break;
11448         IF_BASH_FUNCTION(case TFUNCTION:)
11449         case TWORD:
11450         case TREDIR:
11451                 tokpushback = 1;
11452                 return simplecmd();
11453         }
11454
11455         if (readtoken() != t)
11456                 raise_error_unexpected_syntax(t);
11457
11458  redir:
11459         /* Now check for redirection which may follow command */
11460         checkkwd = CHKKWD | CHKALIAS;
11461         rpp = rpp2;
11462         while (readtoken() == TREDIR) {
11463                 *rpp = n2 = redirnode;
11464                 rpp = &n2->nfile.next;
11465                 parsefname();
11466         }
11467         tokpushback = 1;
11468         *rpp = NULL;
11469         if (redir) {
11470                 if (n1->type != NSUBSHELL) {
11471                         n2 = stzalloc(sizeof(struct nredir));
11472                         n2->type = NREDIR;
11473                         n2->nredir.n = n1;
11474                         n1 = n2;
11475                 }
11476                 n1->nredir.redirect = redir;
11477         }
11478         return n1;
11479 }
11480
11481 #if BASH_DOLLAR_SQUOTE
11482 static int
11483 decode_dollar_squote(void)
11484 {
11485         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11486         int c, cnt;
11487         char *p;
11488         char buf[4];
11489
11490         c = pgetc();
11491         p = strchr(C_escapes, c);
11492         if (p) {
11493                 buf[0] = c;
11494                 p = buf;
11495                 cnt = 3;
11496                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11497                         do {
11498                                 c = pgetc();
11499                                 *++p = c;
11500                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11501                         pungetc();
11502                 } else if (c == 'x') { /* \xHH */
11503                         do {
11504                                 c = pgetc();
11505                                 *++p = c;
11506                         } while (isxdigit(c) && --cnt);
11507                         pungetc();
11508                         if (cnt == 3) { /* \x but next char is "bad" */
11509                                 c = 'x';
11510                                 goto unrecognized;
11511                         }
11512                 } else { /* simple seq like \\ or \t */
11513                         p++;
11514                 }
11515                 *p = '\0';
11516                 p = buf;
11517                 c = bb_process_escape_sequence((void*)&p);
11518         } else { /* unrecognized "\z": print both chars unless ' or " */
11519                 if (c != '\'' && c != '"') {
11520  unrecognized:
11521                         c |= 0x100; /* "please encode \, then me" */
11522                 }
11523         }
11524         return c;
11525 }
11526 #endif
11527
11528 /* Used by expandstr to get here-doc like behaviour. */
11529 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11530
11531 static ALWAYS_INLINE int
11532 realeofmark(const char *eofmark)
11533 {
11534         return eofmark && eofmark != FAKEEOFMARK;
11535 }
11536
11537 /*
11538  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11539  * is not NULL, read a here document.  In the latter case, eofmark is the
11540  * word which marks the end of the document and striptabs is true if
11541  * leading tabs should be stripped from the document.  The argument c
11542  * is the first character of the input token or document.
11543  *
11544  * Because C does not have internal subroutines, I have simulated them
11545  * using goto's to implement the subroutine linkage.  The following macros
11546  * will run code that appears at the end of readtoken1.
11547  */
11548 #define CHECKEND()      {goto checkend; checkend_return:;}
11549 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11550 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11551 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11552 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11553 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11554 static int
11555 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11556 {
11557         /* NB: syntax parameter fits into smallint */
11558         /* c parameter is an unsigned char or PEOF or PEOA */
11559         char *out;
11560         size_t len;
11561         struct nodelist *bqlist;
11562         smallint quotef;
11563         smallint dblquote;
11564         smallint oldstyle;
11565         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11566         smallint pssyntax;   /* we are expanding a prompt string */
11567         int varnest;         /* levels of variables expansion */
11568         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11569         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11570         int dqvarnest;       /* levels of variables expansion within double quotes */
11571
11572         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11573
11574         startlinno = g_parsefile->linno;
11575         bqlist = NULL;
11576         quotef = 0;
11577         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11578         pssyntax = (syntax == PSSYNTAX);
11579         if (pssyntax)
11580                 syntax = DQSYNTAX;
11581         dblquote = (syntax == DQSYNTAX);
11582         varnest = 0;
11583         IF_FEATURE_SH_MATH(arinest = 0;)
11584         IF_FEATURE_SH_MATH(parenlevel = 0;)
11585         dqvarnest = 0;
11586
11587         STARTSTACKSTR(out);
11588  loop:
11589         /* For each line, until end of word */
11590         CHECKEND();     /* set c to PEOF if at end of here document */
11591         for (;;) {      /* until end of line or end of word */
11592                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11593                 switch (SIT(c, syntax)) {
11594                 case CNL:       /* '\n' */
11595                         if (syntax == BASESYNTAX)
11596                                 goto endword;   /* exit outer loop */
11597                         USTPUTC(c, out);
11598                         nlprompt();
11599                         c = pgetc();
11600                         goto loop;              /* continue outer loop */
11601                 case CWORD:
11602                         USTPUTC(c, out);
11603                         break;
11604                 case CCTL:
11605 #if BASH_DOLLAR_SQUOTE
11606                         if (c == '\\' && bash_dollar_squote) {
11607                                 c = decode_dollar_squote();
11608                                 if (c == '\0') {
11609                                         /* skip $'\000', $'\x00' (like bash) */
11610                                         break;
11611                                 }
11612                                 if (c & 0x100) {
11613                                         /* Unknown escape. Encode as '\z' */
11614                                         c = (unsigned char)c;
11615                                         if (eofmark == NULL || dblquote)
11616                                                 USTPUTC(CTLESC, out);
11617                                         USTPUTC('\\', out);
11618                                 }
11619                         }
11620 #endif
11621                         if (eofmark == NULL || dblquote)
11622                                 USTPUTC(CTLESC, out);
11623                         USTPUTC(c, out);
11624                         break;
11625                 case CBACK:     /* backslash */
11626                         c = pgetc_without_PEOA();
11627                         if (c == PEOF) {
11628                                 USTPUTC(CTLESC, out);
11629                                 USTPUTC('\\', out);
11630                                 pungetc();
11631                         } else if (c == '\n') {
11632                                 nlprompt();
11633                         } else {
11634                                 if (c == '$' && pssyntax) {
11635                                         USTPUTC(CTLESC, out);
11636                                         USTPUTC('\\', out);
11637                                 }
11638                                 /* Backslash is retained if we are in "str" and next char isn't special */
11639                                 if (dblquote
11640                                  && c != '\\'
11641                                  && c != '`'
11642                                  && c != '$'
11643                                  && (c != '"' || eofmark != NULL)
11644                                 ) {
11645                                         USTPUTC('\\', out);
11646                                 }
11647                                 USTPUTC(CTLESC, out);
11648                                 USTPUTC(c, out);
11649                                 quotef = 1;
11650                         }
11651                         break;
11652                 case CSQUOTE:
11653                         syntax = SQSYNTAX;
11654  quotemark:
11655                         if (eofmark == NULL) {
11656                                 USTPUTC(CTLQUOTEMARK, out);
11657                         }
11658                         break;
11659                 case CDQUOTE:
11660                         syntax = DQSYNTAX;
11661                         dblquote = 1;
11662                         goto quotemark;
11663                 case CENDQUOTE:
11664                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11665                         if (eofmark != NULL && varnest == 0) {
11666                                 USTPUTC(c, out);
11667                         } else {
11668                                 if (dqvarnest == 0) {
11669                                         syntax = BASESYNTAX;
11670                                         dblquote = 0;
11671                                 }
11672                                 quotef = 1;
11673                                 goto quotemark;
11674                         }
11675                         break;
11676                 case CVAR:      /* '$' */
11677                         PARSESUB();             /* parse substitution */
11678                         break;
11679                 case CENDVAR:   /* '}' */
11680                         if (varnest > 0) {
11681                                 varnest--;
11682                                 if (dqvarnest > 0) {
11683                                         dqvarnest--;
11684                                 }
11685                                 c = CTLENDVAR;
11686                         }
11687                         USTPUTC(c, out);
11688                         break;
11689 #if ENABLE_FEATURE_SH_MATH
11690                 case CLP:       /* '(' in arithmetic */
11691                         parenlevel++;
11692                         USTPUTC(c, out);
11693                         break;
11694                 case CRP:       /* ')' in arithmetic */
11695                         if (parenlevel > 0) {
11696                                 parenlevel--;
11697                         } else {
11698                                 if (pgetc_eatbnl() == ')') {
11699                                         c = CTLENDARI;
11700                                         if (--arinest == 0) {
11701                                                 syntax = prevsyntax;
11702                                         }
11703                                 } else {
11704                                         /*
11705                                          * unbalanced parens
11706                                          * (don't 2nd guess - no error)
11707                                          */
11708                                         pungetc();
11709                                 }
11710                         }
11711                         USTPUTC(c, out);
11712                         break;
11713 #endif
11714                 case CBQUOTE:   /* '`' */
11715                         PARSEBACKQOLD();
11716                         break;
11717                 case CENDFILE:
11718                         goto endword;           /* exit outer loop */
11719                 case CIGN:
11720                         break;
11721                 default:
11722                         if (varnest == 0) {
11723 #if BASH_REDIR_OUTPUT
11724                                 if (c == '&') {
11725 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11726                                         if (pgetc() == '>')
11727                                                 c = 0x100 + '>'; /* flag &> */
11728                                         pungetc();
11729                                 }
11730 #endif
11731                                 goto endword;   /* exit outer loop */
11732                         }
11733                         IF_ASH_ALIAS(if (c != PEOA))
11734                                 USTPUTC(c, out);
11735                 }
11736                 c = pgetc();
11737         } /* for (;;) */
11738  endword:
11739
11740 #if ENABLE_FEATURE_SH_MATH
11741         if (syntax == ARISYNTAX)
11742                 raise_error_syntax("missing '))'");
11743 #endif
11744         if (syntax != BASESYNTAX && eofmark == NULL)
11745                 raise_error_syntax("unterminated quoted string");
11746         if (varnest != 0) {
11747                 startlinno = g_parsefile->linno;
11748                 /* { */
11749                 raise_error_syntax("missing '}'");
11750         }
11751         USTPUTC('\0', out);
11752         len = out - (char *)stackblock();
11753         out = stackblock();
11754         if (eofmark == NULL) {
11755                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11756                  && quotef == 0
11757                 ) {
11758                         if (isdigit_str9(out)) {
11759                                 PARSEREDIR(); /* passed as params: out, c */
11760                                 lasttoken = TREDIR;
11761                                 return lasttoken;
11762                         }
11763                         /* else: non-number X seen, interpret it
11764                          * as "NNNX>file" = "NNNX >file" */
11765                 }
11766                 pungetc();
11767         }
11768         quoteflag = quotef;
11769         backquotelist = bqlist;
11770         grabstackblock(len);
11771         wordtext = out;
11772         lasttoken = TWORD;
11773         return lasttoken;
11774 /* end of readtoken routine */
11775
11776 /*
11777  * Check to see whether we are at the end of the here document.  When this
11778  * is called, c is set to the first character of the next input line.  If
11779  * we are at the end of the here document, this routine sets the c to PEOF.
11780  */
11781 checkend: {
11782         if (realeofmark(eofmark)) {
11783                 int markloc;
11784                 char *p;
11785
11786 #if ENABLE_ASH_ALIAS
11787                 if (c == PEOA)
11788                         c = pgetc_without_PEOA();
11789 #endif
11790                 if (striptabs) {
11791                         while (c == '\t') {
11792                                 c = pgetc_without_PEOA();
11793                         }
11794                 }
11795
11796                 markloc = out - (char *)stackblock();
11797                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11798                         if (c != *p)
11799                                 goto more_heredoc;
11800
11801                         c = pgetc_without_PEOA();
11802                 }
11803
11804                 if (c == '\n' || c == PEOF) {
11805                         c = PEOF;
11806                         g_parsefile->linno++;
11807                         needprompt = doprompt;
11808                 } else {
11809                         int len_here;
11810
11811  more_heredoc:
11812                         p = (char *)stackblock() + markloc + 1;
11813                         len_here = out - p;
11814
11815                         if (len_here) {
11816                                 len_here -= (c >= PEOF);
11817                                 c = p[-1];
11818
11819                                 if (len_here) {
11820                                         char *str;
11821
11822                                         str = alloca(len_here + 1);
11823                                         *(char *)mempcpy(str, p, len_here) = '\0';
11824
11825                                         pushstring(str, NULL);
11826                                 }
11827                         }
11828                 }
11829
11830                 STADJUST((char *)stackblock() + markloc - out, out);
11831         }
11832         goto checkend_return;
11833 }
11834
11835 /*
11836  * Parse a redirection operator.  The variable "out" points to a string
11837  * specifying the fd to be redirected.  The variable "c" contains the
11838  * first character of the redirection operator.
11839  */
11840 parseredir: {
11841         /* out is already checked to be a valid number or "" */
11842         int fd = (*out == '\0' ? -1 : atoi(out));
11843         union node *np;
11844
11845         np = stzalloc(sizeof(struct nfile));
11846         if (c == '>') {
11847                 np->nfile.fd = 1;
11848                 c = pgetc();
11849                 if (c == '>')
11850                         np->type = NAPPEND;
11851                 else if (c == '|')
11852                         np->type = NCLOBBER;
11853                 else if (c == '&')
11854                         np->type = NTOFD;
11855                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11856                 else {
11857                         np->type = NTO;
11858                         pungetc();
11859                 }
11860         }
11861 #if BASH_REDIR_OUTPUT
11862         else if (c == 0x100 + '>') { /* this flags &> redirection */
11863                 np->nfile.fd = 1;
11864                 pgetc(); /* this is '>', no need to check */
11865                 np->type = NTO2;
11866         }
11867 #endif
11868         else { /* c == '<' */
11869                 /*np->nfile.fd = 0; - stzalloc did it */
11870                 c = pgetc();
11871                 switch (c) {
11872                 case '<':
11873                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11874                                 np = stzalloc(sizeof(struct nhere));
11875                                 /*np->nfile.fd = 0; - stzalloc did it */
11876                         }
11877                         np->type = NHERE;
11878                         heredoc = stzalloc(sizeof(struct heredoc));
11879                         heredoc->here = np;
11880                         c = pgetc();
11881                         if (c == '-') {
11882                                 heredoc->striptabs = 1;
11883                         } else {
11884                                 /*heredoc->striptabs = 0; - stzalloc did it */
11885                                 pungetc();
11886                         }
11887                         break;
11888
11889                 case '&':
11890                         np->type = NFROMFD;
11891                         break;
11892
11893                 case '>':
11894                         np->type = NFROMTO;
11895                         break;
11896
11897                 default:
11898                         np->type = NFROM;
11899                         pungetc();
11900                         break;
11901                 }
11902         }
11903         if (fd >= 0)
11904                 np->nfile.fd = fd;
11905         redirnode = np;
11906         goto parseredir_return;
11907 }
11908
11909 /*
11910  * Parse a substitution.  At this point, we have read the dollar sign
11911  * and nothing else.
11912  */
11913
11914 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11915  * (assuming ascii char codes, as the original implementation did) */
11916 #define is_special(c) \
11917         (((unsigned)(c) - 33 < 32) \
11918                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11919 parsesub: {
11920         unsigned char subtype;
11921         int typeloc;
11922
11923         c = pgetc_eatbnl();
11924         if ((checkkwd & CHKEOFMARK)
11925          || c > 255 /* PEOA or PEOF */
11926          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11927         ) {
11928 #if BASH_DOLLAR_SQUOTE
11929                 if (syntax != DQSYNTAX && c == '\'')
11930                         bash_dollar_squote = 1;
11931                 else
11932 #endif
11933                         USTPUTC('$', out);
11934                 pungetc();
11935         } else if (c == '(') {
11936                 /* $(command) or $((arith)) */
11937                 if (pgetc_eatbnl() == '(') {
11938 #if ENABLE_FEATURE_SH_MATH
11939                         PARSEARITH();
11940 #else
11941                         raise_error_syntax("support for $((arith)) is disabled");
11942 #endif
11943                 } else {
11944                         pungetc();
11945                         PARSEBACKQNEW();
11946                 }
11947         } else {
11948                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11949                 USTPUTC(CTLVAR, out);
11950                 typeloc = out - (char *)stackblock();
11951                 STADJUST(1, out);
11952                 subtype = VSNORMAL;
11953                 if (c == '{') {
11954                         c = pgetc_eatbnl();
11955                         subtype = 0;
11956                 }
11957  varname:
11958                 if (is_name(c)) {
11959                         /* $[{[#]]NAME[}] */
11960                         do {
11961                                 STPUTC(c, out);
11962                                 c = pgetc_eatbnl();
11963                         } while (is_in_name(c));
11964                 } else if (isdigit(c)) {
11965                         /* $[{[#]]NUM[}] */
11966                         do {
11967                                 STPUTC(c, out);
11968                                 c = pgetc_eatbnl();
11969                         } while (isdigit(c));
11970                 } else if (is_special(c)) {
11971                         /* $[{[#]]<specialchar>[}] */
11972                         int cc = c;
11973
11974                         c = pgetc_eatbnl();
11975                         if (!subtype && cc == '#') {
11976                                 subtype = VSLENGTH;
11977                                 if (c == '_' || isalnum(c))
11978                                         goto varname;
11979                                 cc = c;
11980                                 c = pgetc_eatbnl();
11981                                 if (cc == '}' || c != '}') {
11982                                         pungetc();
11983                                         subtype = 0;
11984                                         c = cc;
11985                                         cc = '#';
11986                                 }
11987                         }
11988                         USTPUTC(cc, out);
11989                 } else {
11990                         goto badsub;
11991                 }
11992                 if (c != '}' && subtype == VSLENGTH) {
11993                         /* ${#VAR didn't end with } */
11994                         goto badsub;
11995                 }
11996
11997                 if (subtype == 0) {
11998                         static const char types[] ALIGN1 = "}-+?=";
11999                         /* ${VAR...} but not $VAR or ${#VAR} */
12000                         /* c == first char after VAR */
12001                         switch (c) {
12002                         case ':':
12003                                 c = pgetc_eatbnl();
12004 #if BASH_SUBSTR
12005                                 /* This check is only needed to not misinterpret
12006                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12007                                  * constructs.
12008                                  */
12009                                 if (!strchr(types, c)) {
12010                                         subtype = VSSUBSTR;
12011                                         pungetc();
12012                                         break; /* "goto badsub" is bigger (!) */
12013                                 }
12014 #endif
12015                                 subtype = VSNUL;
12016                                 /*FALLTHROUGH*/
12017                         default: {
12018                                 const char *p = strchr(types, c);
12019                                 if (p == NULL)
12020                                         break;
12021                                 subtype |= p - types + VSNORMAL;
12022                                 break;
12023                         }
12024                         case '%':
12025                         case '#': {
12026                                 int cc = c;
12027                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12028                                 c = pgetc_eatbnl();
12029                                 if (c != cc)
12030                                         goto badsub;
12031                                 subtype++;
12032                                 break;
12033                         }
12034 #if BASH_PATTERN_SUBST
12035                         case '/':
12036                                 /* ${v/[/]pattern/repl} */
12037 //TODO: encode pattern and repl separately.
12038 // Currently ${v/$var_with_slash/repl} is horribly broken
12039                                 subtype = VSREPLACE;
12040                                 c = pgetc_eatbnl();
12041                                 if (c != '/')
12042                                         goto badsub;
12043                                 subtype++; /* VSREPLACEALL */
12044                                 break;
12045 #endif
12046                         }
12047                 } else {
12048  badsub:
12049                         pungetc();
12050                 }
12051                 ((unsigned char *)stackblock())[typeloc] = subtype;
12052                 if (subtype != VSNORMAL) {
12053                         varnest++;
12054                         if (dblquote)
12055                                 dqvarnest++;
12056                 }
12057                 STPUTC('=', out);
12058         }
12059         goto parsesub_return;
12060 }
12061
12062 /*
12063  * Called to parse command substitutions.  Newstyle is set if the command
12064  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12065  * list of commands (passed by reference), and savelen is the number of
12066  * characters on the top of the stack which must be preserved.
12067  */
12068 parsebackq: {
12069         struct nodelist **nlpp;
12070         union node *n;
12071         char *str;
12072         size_t savelen;
12073         smallint saveprompt = 0;
12074
12075         str = NULL;
12076         savelen = out - (char *)stackblock();
12077         if (savelen > 0) {
12078                 /*
12079                  * FIXME: this can allocate very large block on stack and SEGV.
12080                  * Example:
12081                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12082                  * allocates 100kb for every command subst. With about
12083                  * a hundred command substitutions stack overflows.
12084                  * With larger prepended string, SEGV happens sooner.
12085                  */
12086                 str = alloca(savelen);
12087                 memcpy(str, stackblock(), savelen);
12088         }
12089
12090         if (oldstyle) {
12091                 /* We must read until the closing backquote, giving special
12092                  * treatment to some slashes, and then push the string and
12093                  * reread it as input, interpreting it normally.
12094                  */
12095                 char *pout;
12096                 size_t psavelen;
12097                 char *pstr;
12098
12099                 STARTSTACKSTR(pout);
12100                 for (;;) {
12101                         int pc;
12102
12103                         setprompt_if(needprompt, 2);
12104                         pc = pgetc();
12105                         switch (pc) {
12106                         case '`':
12107                                 goto done;
12108
12109                         case '\\':
12110                                 pc = pgetc();
12111                                 if (pc == '\n') {
12112                                         nlprompt();
12113                                         /*
12114                                          * If eating a newline, avoid putting
12115                                          * the newline into the new character
12116                                          * stream (via the STPUTC after the
12117                                          * switch).
12118                                          */
12119                                         continue;
12120                                 }
12121                                 if (pc != '\\' && pc != '`' && pc != '$'
12122                                  && (!dblquote || pc != '"')
12123                                 ) {
12124                                         STPUTC('\\', pout);
12125                                 }
12126                                 if (pc <= 255 /* not PEOA or PEOF */) {
12127                                         break;
12128                                 }
12129                                 /* fall through */
12130
12131                         case PEOF:
12132                         IF_ASH_ALIAS(case PEOA:)
12133                                 startlinno = g_parsefile->linno;
12134                                 raise_error_syntax("EOF in backquote substitution");
12135
12136                         case '\n':
12137                                 nlnoprompt();
12138                                 break;
12139
12140                         default:
12141                                 break;
12142                         }
12143                         STPUTC(pc, pout);
12144                 }
12145  done:
12146                 STPUTC('\0', pout);
12147                 psavelen = pout - (char *)stackblock();
12148                 if (psavelen > 0) {
12149                         pstr = grabstackstr(pout);
12150                         setinputstring(pstr);
12151                 }
12152         }
12153         nlpp = &bqlist;
12154         while (*nlpp)
12155                 nlpp = &(*nlpp)->next;
12156         *nlpp = stzalloc(sizeof(**nlpp));
12157         /* (*nlpp)->next = NULL; - stzalloc did it */
12158
12159         if (oldstyle) {
12160                 saveprompt = doprompt;
12161                 doprompt = 0;
12162         }
12163
12164         n = list(2);
12165
12166         if (oldstyle)
12167                 doprompt = saveprompt;
12168         else if (readtoken() != TRP)
12169                 raise_error_unexpected_syntax(TRP);
12170
12171         (*nlpp)->n = n;
12172         if (oldstyle) {
12173                 /*
12174                  * Start reading from old file again, ignoring any pushed back
12175                  * tokens left from the backquote parsing
12176                  */
12177                 popfile();
12178                 tokpushback = 0;
12179         }
12180         while (stackblocksize() <= savelen)
12181                 growstackblock();
12182         STARTSTACKSTR(out);
12183         if (str) {
12184                 memcpy(out, str, savelen);
12185                 STADJUST(savelen, out);
12186         }
12187         USTPUTC(CTLBACKQ, out);
12188         if (oldstyle)
12189                 goto parsebackq_oldreturn;
12190         goto parsebackq_newreturn;
12191 }
12192
12193 #if ENABLE_FEATURE_SH_MATH
12194 /*
12195  * Parse an arithmetic expansion (indicate start of one and set state)
12196  */
12197 parsearith: {
12198         if (++arinest == 1) {
12199                 prevsyntax = syntax;
12200                 syntax = ARISYNTAX;
12201         }
12202         USTPUTC(CTLARI, out);
12203         goto parsearith_return;
12204 }
12205 #endif
12206 } /* end of readtoken */
12207
12208 /*
12209  * Read the next input token.
12210  * If the token is a word, we set backquotelist to the list of cmds in
12211  *      backquotes.  We set quoteflag to true if any part of the word was
12212  *      quoted.
12213  * If the token is TREDIR, then we set redirnode to a structure containing
12214  *      the redirection.
12215  * In all cases, the variable startlinno is set to the number of the line
12216  *      on which the token starts.
12217  *
12218  * [Change comment:  here documents and internal procedures]
12219  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12220  *  word parsing code into a separate routine.  In this case, readtoken
12221  *  doesn't need to have any internal procedures, but parseword does.
12222  *  We could also make parseoperator in essence the main routine, and
12223  *  have parseword (readtoken1?) handle both words and redirection.]
12224  */
12225 #define NEW_xxreadtoken
12226 #ifdef NEW_xxreadtoken
12227 /* singles must be first! */
12228 static const char xxreadtoken_chars[7] ALIGN1 = {
12229         '\n', '(', ')', /* singles */
12230         '&', '|', ';',  /* doubles */
12231         0
12232 };
12233
12234 #define xxreadtoken_singles 3
12235 #define xxreadtoken_doubles 3
12236
12237 static const char xxreadtoken_tokens[] ALIGN1 = {
12238         TNL, TLP, TRP,          /* only single occurrence allowed */
12239         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12240         TEOF,                   /* corresponds to trailing nul */
12241         TAND, TOR, TENDCASE     /* if double occurrence */
12242 };
12243
12244 static int
12245 xxreadtoken(void)
12246 {
12247         int c;
12248
12249         if (tokpushback) {
12250                 tokpushback = 0;
12251                 return lasttoken;
12252         }
12253         setprompt_if(needprompt, 2);
12254         startlinno = g_parsefile->linno;
12255         for (;;) {                      /* until token or start of word found */
12256                 c = pgetc();
12257                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12258                         continue;
12259
12260                 if (c == '#') {
12261                         while ((c = pgetc()) != '\n' && c != PEOF)
12262                                 continue;
12263                         pungetc();
12264                 } else if (c == '\\') {
12265                         if (pgetc() != '\n') {
12266                                 pungetc();
12267                                 break; /* return readtoken1(...) */
12268                         }
12269                         nlprompt();
12270                 } else {
12271                         const char *p;
12272
12273                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12274                         if (c != PEOF) {
12275                                 if (c == '\n') {
12276                                         nlnoprompt();
12277                                 }
12278
12279                                 p = strchr(xxreadtoken_chars, c);
12280                                 if (p == NULL)
12281                                         break; /* return readtoken1(...) */
12282
12283                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12284                                         int cc = pgetc();
12285                                         if (cc == c) {    /* double occurrence? */
12286                                                 p += xxreadtoken_doubles + 1;
12287                                         } else {
12288                                                 pungetc();
12289 #if BASH_REDIR_OUTPUT
12290                                                 if (c == '&' && cc == '>') /* &> */
12291                                                         break; /* return readtoken1(...) */
12292 #endif
12293                                         }
12294                                 }
12295                         }
12296                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12297                         return lasttoken;
12298                 }
12299         } /* for (;;) */
12300
12301         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12302 }
12303 #else /* old xxreadtoken */
12304 #define RETURN(token)   return lasttoken = token
12305 static int
12306 xxreadtoken(void)
12307 {
12308         int c;
12309
12310         if (tokpushback) {
12311                 tokpushback = 0;
12312                 return lasttoken;
12313         }
12314         setprompt_if(needprompt, 2);
12315         startlinno = g_parsefile->linno;
12316         for (;;) {      /* until token or start of word found */
12317                 c = pgetc();
12318                 switch (c) {
12319                 case ' ': case '\t':
12320                 IF_ASH_ALIAS(case PEOA:)
12321                         continue;
12322                 case '#':
12323                         while ((c = pgetc()) != '\n' && c != PEOF)
12324                                 continue;
12325                         pungetc();
12326                         continue;
12327                 case '\\':
12328                         if (pgetc() == '\n') {
12329                                 nlprompt();
12330                                 continue;
12331                         }
12332                         pungetc();
12333                         goto breakloop;
12334                 case '\n':
12335                         nlnoprompt();
12336                         RETURN(TNL);
12337                 case PEOF:
12338                         RETURN(TEOF);
12339                 case '&':
12340                         if (pgetc() == '&')
12341                                 RETURN(TAND);
12342                         pungetc();
12343                         RETURN(TBACKGND);
12344                 case '|':
12345                         if (pgetc() == '|')
12346                                 RETURN(TOR);
12347                         pungetc();
12348                         RETURN(TPIPE);
12349                 case ';':
12350                         if (pgetc() == ';')
12351                                 RETURN(TENDCASE);
12352                         pungetc();
12353                         RETURN(TSEMI);
12354                 case '(':
12355                         RETURN(TLP);
12356                 case ')':
12357                         RETURN(TRP);
12358                 default:
12359                         goto breakloop;
12360                 }
12361         }
12362  breakloop:
12363         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12364 #undef RETURN
12365 }
12366 #endif /* old xxreadtoken */
12367
12368 static int
12369 readtoken(void)
12370 {
12371         int t;
12372         int kwd = checkkwd;
12373 #if DEBUG
12374         smallint alreadyseen = tokpushback;
12375 #endif
12376
12377 #if ENABLE_ASH_ALIAS
12378  top:
12379 #endif
12380
12381         t = xxreadtoken();
12382
12383         /*
12384          * eat newlines
12385          */
12386         if (kwd & CHKNL) {
12387                 while (t == TNL) {
12388                         parseheredoc();
12389                         t = xxreadtoken();
12390                 }
12391         }
12392
12393         if (t != TWORD || quoteflag) {
12394                 goto out;
12395         }
12396
12397         /*
12398          * check for keywords
12399          */
12400         if (kwd & CHKKWD) {
12401                 const char *const *pp;
12402
12403                 pp = findkwd(wordtext);
12404                 if (pp) {
12405                         lasttoken = t = pp - tokname_array;
12406                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12407                         goto out;
12408                 }
12409         }
12410
12411         if (checkkwd & CHKALIAS) {
12412 #if ENABLE_ASH_ALIAS
12413                 struct alias *ap;
12414                 ap = lookupalias(wordtext, 1);
12415                 if (ap != NULL) {
12416                         if (*ap->val) {
12417                                 pushstring(ap->val, ap);
12418                         }
12419                         goto top;
12420                 }
12421 #endif
12422         }
12423  out:
12424         checkkwd = 0;
12425 #if DEBUG
12426         if (!alreadyseen)
12427                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12428         else
12429                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12430 #endif
12431         return t;
12432 }
12433
12434 static int
12435 peektoken(void)
12436 {
12437         int t;
12438
12439         t = readtoken();
12440         tokpushback = 1;
12441         return t;
12442 }
12443
12444 /*
12445  * Read and parse a command.  Returns NODE_EOF on end of file.
12446  * (NULL is a valid parse tree indicating a blank line.)
12447  */
12448 static union node *
12449 parsecmd(int interact)
12450 {
12451         tokpushback = 0;
12452         checkkwd = 0;
12453         heredoclist = 0;
12454         doprompt = interact;
12455         setprompt_if(doprompt, doprompt);
12456         needprompt = 0;
12457         return list(1);
12458 }
12459
12460 /*
12461  * Input any here documents.
12462  */
12463 static void
12464 parseheredoc(void)
12465 {
12466         struct heredoc *here;
12467         union node *n;
12468
12469         here = heredoclist;
12470         heredoclist = NULL;
12471
12472         while (here) {
12473                 setprompt_if(needprompt, 2);
12474                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12475                                 here->eofmark, here->striptabs);
12476                 n = stzalloc(sizeof(struct narg));
12477                 n->narg.type = NARG;
12478                 /*n->narg.next = NULL; - stzalloc did it */
12479                 n->narg.text = wordtext;
12480                 n->narg.backquote = backquotelist;
12481                 here->here->nhere.doc = n;
12482                 here = here->next;
12483         }
12484 }
12485
12486
12487 static const char *
12488 expandstr(const char *ps, int syntax_type)
12489 {
12490         union node n;
12491         int saveprompt;
12492
12493         /* XXX Fix (char *) cast. */
12494         setinputstring((char *)ps);
12495
12496         saveprompt = doprompt;
12497         doprompt = 0;
12498         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12499         doprompt = saveprompt;
12500
12501         popfile();
12502
12503         n.narg.type = NARG;
12504         n.narg.next = NULL;
12505         n.narg.text = wordtext;
12506         n.narg.backquote = backquotelist;
12507
12508         expandarg(&n, NULL, EXP_QUOTED);
12509         return stackblock();
12510 }
12511
12512 static inline int
12513 parser_eof(void)
12514 {
12515         return tokpushback && lasttoken == TEOF;
12516 }
12517
12518 /*
12519  * Execute a command or commands contained in a string.
12520  */
12521 static int
12522 evalstring(char *s, int flags)
12523 {
12524         struct jmploc *volatile savehandler;
12525         struct jmploc jmploc;
12526         int ex;
12527
12528         union node *n;
12529         struct stackmark smark;
12530         int status;
12531
12532         s = sstrdup(s);
12533         setinputstring(s);
12534         setstackmark(&smark);
12535
12536         status = 0;
12537         /* On exception inside execution loop, we must popfile().
12538          * Try interactively:
12539          *      readonly a=a
12540          *      command eval "a=b"  # throws "is read only" error
12541          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12542          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12543          */
12544         savehandler = exception_handler;
12545         ex = setjmp(jmploc.loc);
12546         if (ex)
12547                 goto out;
12548         exception_handler = &jmploc;
12549
12550         while ((n = parsecmd(0)) != NODE_EOF) {
12551                 int i;
12552
12553                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12554                 if (n)
12555                         status = i;
12556                 popstackmark(&smark);
12557                 if (evalskip)
12558                         break;
12559         }
12560  out:
12561         popstackmark(&smark);
12562         popfile();
12563         stunalloc(s);
12564
12565         exception_handler = savehandler;
12566         if (ex)
12567                 longjmp(exception_handler->loc, ex);
12568
12569         return status;
12570 }
12571
12572 /*
12573  * The eval command.
12574  */
12575 static int FAST_FUNC
12576 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12577 {
12578         char *p;
12579         char *concat;
12580
12581         if (argv[1]) {
12582                 p = argv[1];
12583                 argv += 2;
12584                 if (argv[0]) {
12585                         STARTSTACKSTR(concat);
12586                         for (;;) {
12587                                 concat = stack_putstr(p, concat);
12588                                 p = *argv++;
12589                                 if (p == NULL)
12590                                         break;
12591                                 STPUTC(' ', concat);
12592                         }
12593                         STPUTC('\0', concat);
12594                         p = grabstackstr(concat);
12595                 }
12596                 return evalstring(p, flags & EV_TESTED);
12597         }
12598         return 0;
12599 }
12600
12601 /*
12602  * Read and execute commands.
12603  * "Top" is nonzero for the top level command loop;
12604  * it turns on prompting if the shell is interactive.
12605  */
12606 static int
12607 cmdloop(int top)
12608 {
12609         union node *n;
12610         struct stackmark smark;
12611         int inter;
12612         int status = 0;
12613         int numeof = 0;
12614
12615         TRACE(("cmdloop(%d) called\n", top));
12616         for (;;) {
12617                 int skip;
12618
12619                 setstackmark(&smark);
12620 #if JOBS
12621                 if (doing_jobctl)
12622                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12623 #endif
12624                 inter = 0;
12625                 if (iflag && top) {
12626                         inter++;
12627                         chkmail();
12628                 }
12629                 n = parsecmd(inter);
12630 #if DEBUG
12631                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12632                         showtree(n);
12633 #endif
12634                 if (n == NODE_EOF) {
12635                         if (!top || numeof >= 50)
12636                                 break;
12637                         if (!stoppedjobs()) {
12638                                 if (!Iflag)
12639                                         break;
12640                                 out2str("\nUse \"exit\" to leave shell.\n");
12641                         }
12642                         numeof++;
12643                 } else if (nflag == 0) {
12644                         int i;
12645
12646                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12647                         job_warning >>= 1;
12648                         numeof = 0;
12649                         i = evaltree(n, 0);
12650                         if (n)
12651                                 status = i;
12652                 }
12653                 popstackmark(&smark);
12654                 skip = evalskip;
12655
12656                 if (skip) {
12657                         evalskip &= ~SKIPFUNC;
12658                         break;
12659                 }
12660         }
12661         return status;
12662 }
12663
12664 /*
12665  * Take commands from a file.  To be compatible we should do a path
12666  * search for the file, which is necessary to find sub-commands.
12667  */
12668 static char *
12669 find_dot_file(char *name)
12670 {
12671         char *fullname;
12672         const char *path = pathval();
12673         struct stat statb;
12674
12675         /* don't try this for absolute or relative paths */
12676         if (strchr(name, '/'))
12677                 return name;
12678
12679         while ((fullname = path_advance(&path, name)) != NULL) {
12680                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12681                         /*
12682                          * Don't bother freeing here, since it will
12683                          * be freed by the caller.
12684                          */
12685                         return fullname;
12686                 }
12687                 if (fullname != name)
12688                         stunalloc(fullname);
12689         }
12690
12691         /* not found in the PATH */
12692         ash_msg_and_raise_error("%s: not found", name);
12693         /* NOTREACHED */
12694 }
12695
12696 static int FAST_FUNC
12697 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12698 {
12699         /* "false; . empty_file; echo $?" should print 0, not 1: */
12700         int status = 0;
12701         char *fullname;
12702         char **argv;
12703         char *args_need_save;
12704         volatile struct shparam saveparam;
12705
12706 //???
12707 //      struct strlist *sp;
12708 //      for (sp = cmdenviron; sp; sp = sp->next)
12709 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12710
12711         nextopt(nullstr); /* handle possible "--" */
12712         argv = argptr;
12713
12714         if (!argv[0]) {
12715                 /* bash says: "bash: .: filename argument required" */
12716                 return 2; /* bash compat */
12717         }
12718
12719         /* This aborts if file isn't found, which is POSIXly correct.
12720          * bash returns exitcode 1 instead.
12721          */
12722         fullname = find_dot_file(argv[0]);
12723         argv++;
12724         args_need_save = argv[0];
12725         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12726                 int argc;
12727                 saveparam = shellparam;
12728                 shellparam.malloced = 0;
12729                 argc = 1;
12730                 while (argv[argc])
12731                         argc++;
12732                 shellparam.nparam = argc;
12733                 shellparam.p = argv;
12734         };
12735
12736         /* This aborts if file can't be opened, which is POSIXly correct.
12737          * bash returns exitcode 1 instead.
12738          */
12739         setinputfile(fullname, INPUT_PUSH_FILE);
12740         commandname = fullname;
12741         status = cmdloop(0);
12742         popfile();
12743
12744         if (args_need_save) {
12745                 freeparam(&shellparam);
12746                 shellparam = saveparam;
12747         };
12748
12749         return status;
12750 }
12751
12752 static int FAST_FUNC
12753 exitcmd(int argc UNUSED_PARAM, char **argv)
12754 {
12755         if (stoppedjobs())
12756                 return 0;
12757         if (argv[1])
12758                 exitstatus = number(argv[1]);
12759         raise_exception(EXEXIT);
12760         /* NOTREACHED */
12761 }
12762
12763 /*
12764  * Read a file containing shell functions.
12765  */
12766 static void
12767 readcmdfile(char *name)
12768 {
12769         setinputfile(name, INPUT_PUSH_FILE);
12770         cmdloop(0);
12771         popfile();
12772 }
12773
12774
12775 /* ============ find_command inplementation */
12776
12777 /*
12778  * Resolve a command name.  If you change this routine, you may have to
12779  * change the shellexec routine as well.
12780  */
12781 static void
12782 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12783 {
12784         struct tblentry *cmdp;
12785         int idx;
12786         int prev;
12787         char *fullname;
12788         struct stat statb;
12789         int e;
12790         int updatetbl;
12791         struct builtincmd *bcmd;
12792
12793         /* If name contains a slash, don't use PATH or hash table */
12794         if (strchr(name, '/') != NULL) {
12795                 entry->u.index = -1;
12796                 if (act & DO_ABS) {
12797                         while (stat(name, &statb) < 0) {
12798 #ifdef SYSV
12799                                 if (errno == EINTR)
12800                                         continue;
12801 #endif
12802                                 entry->cmdtype = CMDUNKNOWN;
12803                                 return;
12804                         }
12805                 }
12806                 entry->cmdtype = CMDNORMAL;
12807                 return;
12808         }
12809
12810 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12811
12812         updatetbl = (path == pathval());
12813         if (!updatetbl) {
12814                 act |= DO_ALTPATH;
12815                 if (strstr(path, "%builtin") != NULL)
12816                         act |= DO_ALTBLTIN;
12817         }
12818
12819         /* If name is in the table, check answer will be ok */
12820         cmdp = cmdlookup(name, 0);
12821         if (cmdp != NULL) {
12822                 int bit;
12823
12824                 switch (cmdp->cmdtype) {
12825                 default:
12826 #if DEBUG
12827                         abort();
12828 #endif
12829                 case CMDNORMAL:
12830                         bit = DO_ALTPATH;
12831                         break;
12832                 case CMDFUNCTION:
12833                         bit = DO_NOFUNC;
12834                         break;
12835                 case CMDBUILTIN:
12836                         bit = DO_ALTBLTIN;
12837                         break;
12838                 }
12839                 if (act & bit) {
12840                         updatetbl = 0;
12841                         cmdp = NULL;
12842                 } else if (cmdp->rehash == 0)
12843                         /* if not invalidated by cd, we're done */
12844                         goto success;
12845         }
12846
12847         /* If %builtin not in path, check for builtin next */
12848         bcmd = find_builtin(name);
12849         if (bcmd) {
12850                 if (IS_BUILTIN_REGULAR(bcmd))
12851                         goto builtin_success;
12852                 if (act & DO_ALTPATH) {
12853                         if (!(act & DO_ALTBLTIN))
12854                                 goto builtin_success;
12855                 } else if (builtinloc <= 0) {
12856                         goto builtin_success;
12857                 }
12858         }
12859
12860 #if ENABLE_FEATURE_SH_STANDALONE
12861         {
12862                 int applet_no = find_applet_by_name(name);
12863                 if (applet_no >= 0) {
12864                         entry->cmdtype = CMDNORMAL;
12865                         entry->u.index = -2 - applet_no;
12866                         return;
12867                 }
12868         }
12869 #endif
12870
12871         /* We have to search path. */
12872         prev = -1;              /* where to start */
12873         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12874                 if (cmdp->cmdtype == CMDBUILTIN)
12875                         prev = builtinloc;
12876                 else
12877                         prev = cmdp->param.index;
12878         }
12879
12880         e = ENOENT;
12881         idx = -1;
12882  loop:
12883         while ((fullname = path_advance(&path, name)) != NULL) {
12884                 stunalloc(fullname);
12885                 /* NB: code below will still use fullname
12886                  * despite it being "unallocated" */
12887                 idx++;
12888                 if (pathopt) {
12889                         if (prefix(pathopt, "builtin")) {
12890                                 if (bcmd)
12891                                         goto builtin_success;
12892                                 continue;
12893                         }
12894                         if ((act & DO_NOFUNC)
12895                          || !prefix(pathopt, "func")
12896                         ) {     /* ignore unimplemented options */
12897                                 continue;
12898                         }
12899                 }
12900                 /* if rehash, don't redo absolute path names */
12901                 if (fullname[0] == '/' && idx <= prev) {
12902                         if (idx < prev)
12903                                 continue;
12904                         TRACE(("searchexec \"%s\": no change\n", name));
12905                         goto success;
12906                 }
12907                 while (stat(fullname, &statb) < 0) {
12908 #ifdef SYSV
12909                         if (errno == EINTR)
12910                                 continue;
12911 #endif
12912                         if (errno != ENOENT && errno != ENOTDIR)
12913                                 e = errno;
12914                         goto loop;
12915                 }
12916                 e = EACCES;     /* if we fail, this will be the error */
12917                 if (!S_ISREG(statb.st_mode))
12918                         continue;
12919                 if (pathopt) {          /* this is a %func directory */
12920                         stalloc(strlen(fullname) + 1);
12921                         /* NB: stalloc will return space pointed by fullname
12922                          * (because we don't have any intervening allocations
12923                          * between stunalloc above and this stalloc) */
12924                         readcmdfile(fullname);
12925                         cmdp = cmdlookup(name, 0);
12926                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12927                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12928                         stunalloc(fullname);
12929                         goto success;
12930                 }
12931                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12932                 if (!updatetbl) {
12933                         entry->cmdtype = CMDNORMAL;
12934                         entry->u.index = idx;
12935                         return;
12936                 }
12937                 INT_OFF;
12938                 cmdp = cmdlookup(name, 1);
12939                 cmdp->cmdtype = CMDNORMAL;
12940                 cmdp->param.index = idx;
12941                 INT_ON;
12942                 goto success;
12943         }
12944
12945         /* We failed.  If there was an entry for this command, delete it */
12946         if (cmdp && updatetbl)
12947                 delete_cmd_entry();
12948         if (act & DO_ERR)
12949                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12950         entry->cmdtype = CMDUNKNOWN;
12951         return;
12952
12953  builtin_success:
12954         if (!updatetbl) {
12955                 entry->cmdtype = CMDBUILTIN;
12956                 entry->u.cmd = bcmd;
12957                 return;
12958         }
12959         INT_OFF;
12960         cmdp = cmdlookup(name, 1);
12961         cmdp->cmdtype = CMDBUILTIN;
12962         cmdp->param.cmd = bcmd;
12963         INT_ON;
12964  success:
12965         cmdp->rehash = 0;
12966         entry->cmdtype = cmdp->cmdtype;
12967         entry->u = cmdp->param;
12968 }
12969
12970
12971 /*
12972  * The trap builtin.
12973  */
12974 static int FAST_FUNC
12975 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12976 {
12977         char *action;
12978         char **ap;
12979         int signo, exitcode;
12980
12981         nextopt(nullstr);
12982         ap = argptr;
12983         if (!*ap) {
12984                 for (signo = 0; signo < NSIG; signo++) {
12985                         char *tr = trap_ptr[signo];
12986                         if (tr) {
12987                                 /* note: bash adds "SIG", but only if invoked
12988                                  * as "bash". If called as "sh", or if set -o posix,
12989                                  * then it prints short signal names.
12990                                  * We are printing short names: */
12991                                 out1fmt("trap -- %s %s\n",
12992                                                 single_quote(tr),
12993                                                 get_signame(signo));
12994                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12995                  * In this case, we will exit very soon, no need to free(). */
12996                                 /* if (trap_ptr != trap && tp[0]) */
12997                                 /*      free(tr); */
12998                         }
12999                 }
13000                 /*
13001                 if (trap_ptr != trap) {
13002                         free(trap_ptr);
13003                         trap_ptr = trap;
13004                 }
13005                 */
13006                 return 0;
13007         }
13008
13009         /* Why the second check?
13010          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13011          * In this case, NUM is signal no, not an action.
13012          */
13013         action = NULL;
13014         if (ap[1] && !is_number(ap[0]))
13015                 action = *ap++;
13016
13017         exitcode = 0;
13018         while (*ap) {
13019                 signo = get_signum(*ap);
13020                 if (signo < 0) {
13021                         /* Mimic bash message exactly */
13022                         ash_msg("%s: invalid signal specification", *ap);
13023                         exitcode = 1;
13024                         goto next;
13025                 }
13026                 INT_OFF;
13027                 if (action) {
13028                         if (LONE_DASH(action))
13029                                 action = NULL;
13030                         else {
13031                                 if (action[0]) /* not NULL and not "" and not "-" */
13032                                         may_have_traps = 1;
13033                                 action = ckstrdup(action);
13034                         }
13035                 }
13036                 free(trap[signo]);
13037                 trap[signo] = action;
13038                 if (signo != 0)
13039                         setsignal(signo);
13040                 INT_ON;
13041  next:
13042                 ap++;
13043         }
13044         return exitcode;
13045 }
13046
13047
13048 /* ============ Builtins */
13049
13050 #if ENABLE_ASH_HELP
13051 static int FAST_FUNC
13052 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13053 {
13054         unsigned col;
13055         unsigned i;
13056
13057         out1fmt(
13058                 "Built-in commands:\n"
13059                 "------------------\n");
13060         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13061                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13062                                         builtintab[i].name + 1);
13063                 if (col > 60) {
13064                         out1fmt("\n");
13065                         col = 0;
13066                 }
13067         }
13068 # if ENABLE_FEATURE_SH_STANDALONE
13069         {
13070                 const char *a = applet_names;
13071                 while (*a) {
13072                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13073                         if (col > 60) {
13074                                 out1fmt("\n");
13075                                 col = 0;
13076                         }
13077                         while (*a++ != '\0')
13078                                 continue;
13079                 }
13080         }
13081 # endif
13082         newline_and_flush(stdout);
13083         return EXIT_SUCCESS;
13084 }
13085 #endif
13086
13087 #if MAX_HISTORY
13088 static int FAST_FUNC
13089 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13090 {
13091         show_history(line_input_state);
13092         return EXIT_SUCCESS;
13093 }
13094 #endif
13095
13096 /*
13097  * The export and readonly commands.
13098  */
13099 static int FAST_FUNC
13100 exportcmd(int argc UNUSED_PARAM, char **argv)
13101 {
13102         struct var *vp;
13103         char *name;
13104         const char *p;
13105         char **aptr;
13106         char opt;
13107         int flag;
13108         int flag_off;
13109
13110         /* "readonly" in bash accepts, but ignores -n.
13111          * We do the same: it saves a conditional in nextopt's param.
13112          */
13113         flag_off = 0;
13114         while ((opt = nextopt("np")) != '\0') {
13115                 if (opt == 'n')
13116                         flag_off = VEXPORT;
13117         }
13118         flag = VEXPORT;
13119         if (argv[0][0] == 'r') {
13120                 flag = VREADONLY;
13121                 flag_off = 0; /* readonly ignores -n */
13122         }
13123         flag_off = ~flag_off;
13124
13125         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13126         {
13127                 aptr = argptr;
13128                 name = *aptr;
13129                 if (name) {
13130                         do {
13131                                 p = strchr(name, '=');
13132                                 if (p != NULL) {
13133                                         p++;
13134                                 } else {
13135                                         vp = *findvar(hashvar(name), name);
13136                                         if (vp) {
13137                                                 vp->flags = ((vp->flags | flag) & flag_off);
13138                                                 continue;
13139                                         }
13140                                 }
13141                                 setvar(name, p, (flag & flag_off));
13142                         } while ((name = *++aptr) != NULL);
13143                         return 0;
13144                 }
13145         }
13146
13147         /* No arguments. Show the list of exported or readonly vars.
13148          * -n is ignored.
13149          */
13150         showvars(argv[0], flag, 0);
13151         return 0;
13152 }
13153
13154 /*
13155  * Delete a function if it exists.
13156  */
13157 static void
13158 unsetfunc(const char *name)
13159 {
13160         struct tblentry *cmdp;
13161
13162         cmdp = cmdlookup(name, 0);
13163         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13164                 delete_cmd_entry();
13165 }
13166
13167 /*
13168  * The unset builtin command.  We unset the function before we unset the
13169  * variable to allow a function to be unset when there is a readonly variable
13170  * with the same name.
13171  */
13172 static int FAST_FUNC
13173 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13174 {
13175         char **ap;
13176         int i;
13177         int flag = 0;
13178
13179         while ((i = nextopt("vf")) != 0) {
13180                 flag = i;
13181         }
13182
13183         for (ap = argptr; *ap; ap++) {
13184                 if (flag != 'f') {
13185                         unsetvar(*ap);
13186                         continue;
13187                 }
13188                 if (flag != 'v')
13189                         unsetfunc(*ap);
13190         }
13191         return 0;
13192 }
13193
13194 static const unsigned char timescmd_str[] ALIGN1 = {
13195         ' ',  offsetof(struct tms, tms_utime),
13196         '\n', offsetof(struct tms, tms_stime),
13197         ' ',  offsetof(struct tms, tms_cutime),
13198         '\n', offsetof(struct tms, tms_cstime),
13199         0
13200 };
13201 static int FAST_FUNC
13202 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13203 {
13204         unsigned long clk_tck, s, t;
13205         const unsigned char *p;
13206         struct tms buf;
13207
13208         clk_tck = bb_clk_tck();
13209         times(&buf);
13210
13211         p = timescmd_str;
13212         do {
13213                 t = *(clock_t *)(((char *) &buf) + p[1]);
13214                 s = t / clk_tck;
13215                 t = t % clk_tck;
13216                 out1fmt("%lum%lu.%03lus%c",
13217                         s / 60, s % 60,
13218                         (t * 1000) / clk_tck,
13219                         p[0]);
13220                 p += 2;
13221         } while (*p);
13222
13223         return 0;
13224 }
13225
13226 #if ENABLE_FEATURE_SH_MATH
13227 /*
13228  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13229  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13230  *
13231  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13232  */
13233 static int FAST_FUNC
13234 letcmd(int argc UNUSED_PARAM, char **argv)
13235 {
13236         arith_t i;
13237
13238         argv++;
13239         if (!*argv)
13240                 ash_msg_and_raise_error("expression expected");
13241         do {
13242                 i = ash_arith(*argv);
13243         } while (*++argv);
13244
13245         return !i;
13246 }
13247 #endif
13248
13249 /*
13250  * The read builtin. Options:
13251  *      -r              Do not interpret '\' specially
13252  *      -s              Turn off echo (tty only)
13253  *      -n NCHARS       Read NCHARS max
13254  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13255  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13256  *      -u FD           Read from given FD instead of fd 0
13257  * This uses unbuffered input, which may be avoidable in some cases.
13258  * TODO: bash also has:
13259  *      -a ARRAY        Read into array[0],[1],etc
13260  *      -d DELIM        End on DELIM char, not newline
13261  *      -e              Use line editing (tty only)
13262  */
13263 static int FAST_FUNC
13264 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13265 {
13266         char *opt_n = NULL;
13267         char *opt_p = NULL;
13268         char *opt_t = NULL;
13269         char *opt_u = NULL;
13270         int read_flags = 0;
13271         const char *r;
13272         int i;
13273
13274         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13275                 switch (i) {
13276                 case 'p':
13277                         opt_p = optionarg;
13278                         break;
13279                 case 'n':
13280                         opt_n = optionarg;
13281                         break;
13282                 case 's':
13283                         read_flags |= BUILTIN_READ_SILENT;
13284                         break;
13285                 case 't':
13286                         opt_t = optionarg;
13287                         break;
13288                 case 'r':
13289                         read_flags |= BUILTIN_READ_RAW;
13290                         break;
13291                 case 'u':
13292                         opt_u = optionarg;
13293                         break;
13294                 default:
13295                         break;
13296                 }
13297         }
13298
13299         /* "read -s" needs to save/restore termios, can't allow ^C
13300          * to jump out of it.
13301          */
13302  again:
13303         INT_OFF;
13304         r = shell_builtin_read(setvar0,
13305                 argptr,
13306                 bltinlookup("IFS"), /* can be NULL */
13307                 read_flags,
13308                 opt_n,
13309                 opt_p,
13310                 opt_t,
13311                 opt_u
13312         );
13313         INT_ON;
13314
13315         if ((uintptr_t)r == 1 && errno == EINTR) {
13316                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13317                 if (pending_sig == 0)
13318                         goto again;
13319         }
13320
13321         if ((uintptr_t)r > 1)
13322                 ash_msg_and_raise_error(r);
13323
13324         return (uintptr_t)r;
13325 }
13326
13327 static int FAST_FUNC
13328 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13329 {
13330         static const char permuser[3] ALIGN1 = "ogu";
13331
13332         mode_t mask;
13333         int symbolic_mode = 0;
13334
13335         while (nextopt("S") != '\0') {
13336                 symbolic_mode = 1;
13337         }
13338
13339         INT_OFF;
13340         mask = umask(0);
13341         umask(mask);
13342         INT_ON;
13343
13344         if (*argptr == NULL) {
13345                 if (symbolic_mode) {
13346                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13347                         char *p = buf;
13348                         int i;
13349
13350                         i = 2;
13351                         for (;;) {
13352                                 *p++ = ',';
13353                                 *p++ = permuser[i];
13354                                 *p++ = '=';
13355                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13356                                 if (!(mask & 0400)) *p++ = 'r';
13357                                 if (!(mask & 0200)) *p++ = 'w';
13358                                 if (!(mask & 0100)) *p++ = 'x';
13359                                 mask <<= 3;
13360                                 if (--i < 0)
13361                                         break;
13362                         }
13363                         *p = '\0';
13364                         puts(buf + 1);
13365                 } else {
13366                         out1fmt("%04o\n", mask);
13367                 }
13368         } else {
13369                 char *modestr = *argptr;
13370                 /* numeric umasks are taken as-is */
13371                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13372                 if (!isdigit(modestr[0]))
13373                         mask ^= 0777;
13374                 mask = bb_parse_mode(modestr, mask);
13375                 if ((unsigned)mask > 0777) {
13376                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13377                 }
13378                 if (!isdigit(modestr[0]))
13379                         mask ^= 0777;
13380                 umask(mask);
13381         }
13382         return 0;
13383 }
13384
13385 static int FAST_FUNC
13386 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13387 {
13388         return shell_builtin_ulimit(argv);
13389 }
13390
13391 /* ============ main() and helpers */
13392
13393 /*
13394  * Called to exit the shell.
13395  */
13396 static void
13397 exitshell(void)
13398 {
13399         struct jmploc loc;
13400         char *p;
13401         int status;
13402
13403 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13404         save_history(line_input_state);
13405 #endif
13406         status = exitstatus;
13407         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13408         if (setjmp(loc.loc)) {
13409                 if (exception_type == EXEXIT)
13410                         status = exitstatus;
13411                 goto out;
13412         }
13413         exception_handler = &loc;
13414         p = trap[0];
13415         if (p) {
13416                 trap[0] = NULL;
13417                 evalskip = 0;
13418                 evalstring(p, 0);
13419                 /*free(p); - we'll exit soon */
13420         }
13421  out:
13422         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13423          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13424          */
13425         setjobctl(0);
13426         flush_stdout_stderr();
13427         _exit(status);
13428         /* NOTREACHED */
13429 }
13430
13431 static void
13432 init(void)
13433 {
13434         /* we will never free this */
13435         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13436
13437         sigmode[SIGCHLD - 1] = S_DFL;
13438         setsignal(SIGCHLD);
13439
13440         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13441          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13442          */
13443         signal(SIGHUP, SIG_DFL);
13444
13445         {
13446                 char **envp;
13447                 const char *p;
13448                 struct stat st1, st2;
13449
13450                 initvar();
13451                 for (envp = environ; envp && *envp; envp++) {
13452                         p = endofname(*envp);
13453                         if (p != *envp && *p == '=') {
13454                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13455                         }
13456                 }
13457
13458                 setvareq((char*)defoptindvar, VTEXTFIXED);
13459
13460                 setvar0("PPID", utoa(getppid()));
13461 #if BASH_SHLVL_VAR
13462                 p = lookupvar("SHLVL");
13463                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13464 #endif
13465 #if BASH_HOSTNAME_VAR
13466                 if (!lookupvar("HOSTNAME")) {
13467                         struct utsname uts;
13468                         uname(&uts);
13469                         setvar0("HOSTNAME", uts.nodename);
13470                 }
13471 #endif
13472                 p = lookupvar("PWD");
13473                 if (p) {
13474                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13475                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13476                         ) {
13477                                 p = NULL;
13478                         }
13479                 }
13480                 setpwd(p, 0);
13481         }
13482 }
13483
13484
13485 //usage:#define ash_trivial_usage
13486 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13487 //usage:#define ash_full_usage "\n\n"
13488 //usage:        "Unix shell interpreter"
13489
13490 /*
13491  * Process the shell command line arguments.
13492  */
13493 static void
13494 procargs(char **argv)
13495 {
13496         int i;
13497         const char *xminusc;
13498         char **xargv;
13499
13500         xargv = argv;
13501         arg0 = xargv[0];
13502         /* if (xargv[0]) - mmm, this is always true! */
13503                 xargv++;
13504         for (i = 0; i < NOPTS; i++)
13505                 optlist[i] = 2;
13506         argptr = xargv;
13507         if (options(/*cmdline:*/ 1)) {
13508                 /* it already printed err message */
13509                 raise_exception(EXERROR);
13510         }
13511         xargv = argptr;
13512         xminusc = minusc;
13513         if (*xargv == NULL) {
13514                 if (xminusc)
13515                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13516                 sflag = 1;
13517         }
13518         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13519                 iflag = 1;
13520         if (mflag == 2)
13521                 mflag = iflag;
13522         for (i = 0; i < NOPTS; i++)
13523                 if (optlist[i] == 2)
13524                         optlist[i] = 0;
13525 #if DEBUG == 2
13526         debug = 1;
13527 #endif
13528         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13529         if (xminusc) {
13530                 minusc = *xargv++;
13531                 if (*xargv)
13532                         goto setarg0;
13533         } else if (!sflag) {
13534                 setinputfile(*xargv, 0);
13535  setarg0:
13536                 arg0 = *xargv++;
13537                 commandname = arg0;
13538         }
13539
13540         shellparam.p = xargv;
13541 #if ENABLE_ASH_GETOPTS
13542         shellparam.optind = 1;
13543         shellparam.optoff = -1;
13544 #endif
13545         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13546         while (*xargv) {
13547                 shellparam.nparam++;
13548                 xargv++;
13549         }
13550         optschanged();
13551 }
13552
13553 /*
13554  * Read /etc/profile, ~/.profile, $ENV.
13555  */
13556 static void
13557 read_profile(const char *name)
13558 {
13559         name = expandstr(name, DQSYNTAX);
13560         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13561                 return;
13562         cmdloop(0);
13563         popfile();
13564 }
13565
13566 /*
13567  * This routine is called when an error or an interrupt occurs in an
13568  * interactive shell and control is returned to the main command loop.
13569  * (In dash, this function is auto-generated by build machinery).
13570  */
13571 static void
13572 reset(void)
13573 {
13574         /* from eval.c: */
13575         evalskip = 0;
13576         loopnest = 0;
13577
13578         /* from expand.c: */
13579         ifsfree();
13580
13581         /* from input.c: */
13582         g_parsefile->left_in_buffer = 0;
13583         g_parsefile->left_in_line = 0;      /* clear input buffer */
13584         popallfiles();
13585
13586         /* from redir.c: */
13587         while (redirlist)
13588                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13589
13590         /* from var.c: */
13591         unwindlocalvars(NULL);
13592 }
13593
13594 #if PROFILE
13595 static short profile_buf[16384];
13596 extern int etext();
13597 #endif
13598
13599 /*
13600  * Main routine.  We initialize things, parse the arguments, execute
13601  * profiles if we're a login shell, and then call cmdloop to execute
13602  * commands.  The setjmp call sets up the location to jump to when an
13603  * exception occurs.  When an exception occurs the variable "state"
13604  * is used to figure out how far we had gotten.
13605  */
13606 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13607 int ash_main(int argc UNUSED_PARAM, char **argv)
13608 {
13609         volatile smallint state;
13610         struct jmploc jmploc;
13611         struct stackmark smark;
13612
13613         /* Initialize global data */
13614         INIT_G_misc();
13615         INIT_G_memstack();
13616         INIT_G_var();
13617 #if ENABLE_ASH_ALIAS
13618         INIT_G_alias();
13619 #endif
13620         INIT_G_cmdtable();
13621
13622 #if PROFILE
13623         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13624 #endif
13625
13626 #if ENABLE_FEATURE_EDITING
13627         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13628 #endif
13629         state = 0;
13630         if (setjmp(jmploc.loc)) {
13631                 smallint e;
13632                 smallint s;
13633
13634                 reset();
13635
13636                 e = exception_type;
13637                 s = state;
13638                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13639                         exitshell();
13640                 }
13641                 if (e == EXINT) {
13642                         newline_and_flush(stderr);
13643                 }
13644
13645                 popstackmark(&smark);
13646                 FORCE_INT_ON; /* enable interrupts */
13647                 if (s == 1)
13648                         goto state1;
13649                 if (s == 2)
13650                         goto state2;
13651                 if (s == 3)
13652                         goto state3;
13653                 goto state4;
13654         }
13655         exception_handler = &jmploc;
13656         rootpid = getpid();
13657
13658         init();
13659         setstackmark(&smark);
13660         procargs(argv);
13661 #if DEBUG
13662         TRACE(("Shell args: "));
13663         trace_puts_args(argv);
13664 #endif
13665
13666         if (argv[0] && argv[0][0] == '-')
13667                 isloginsh = 1;
13668         if (isloginsh) {
13669                 const char *hp;
13670
13671                 state = 1;
13672                 read_profile("/etc/profile");
13673  state1:
13674                 state = 2;
13675                 hp = lookupvar("HOME");
13676                 if (hp)
13677                         read_profile("$HOME/.profile");
13678         }
13679  state2:
13680         state = 3;
13681         if (
13682 #ifndef linux
13683          getuid() == geteuid() && getgid() == getegid() &&
13684 #endif
13685          iflag
13686         ) {
13687                 const char *shinit = lookupvar("ENV");
13688                 if (shinit != NULL && *shinit != '\0')
13689                         read_profile(shinit);
13690         }
13691         popstackmark(&smark);
13692  state3:
13693         state = 4;
13694         if (minusc) {
13695                 /* evalstring pushes parsefile stack.
13696                  * Ensure we don't falsely claim that 0 (stdin)
13697                  * is one of stacked source fds.
13698                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13699                 // if (!sflag) g_parsefile->pf_fd = -1;
13700                 // ^^ not necessary since now we special-case fd 0
13701                 // in is_hidden_fd() to not be considered "hidden fd"
13702                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13703         }
13704
13705         if (sflag || minusc == NULL) {
13706 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13707                 if (iflag) {
13708                         const char *hp = lookupvar("HISTFILE");
13709                         if (!hp) {
13710                                 hp = lookupvar("HOME");
13711                                 if (hp) {
13712                                         INT_OFF;
13713                                         hp = concat_path_file(hp, ".ash_history");
13714                                         setvar0("HISTFILE", hp);
13715                                         free((char*)hp);
13716                                         INT_ON;
13717                                         hp = lookupvar("HISTFILE");
13718                                 }
13719                         }
13720                         if (hp)
13721                                 line_input_state->hist_file = hp;
13722 # if ENABLE_FEATURE_SH_HISTFILESIZE
13723                         hp = lookupvar("HISTFILESIZE");
13724                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13725 # endif
13726                 }
13727 #endif
13728  state4: /* XXX ??? - why isn't this before the "if" statement */
13729                 cmdloop(1);
13730         }
13731 #if PROFILE
13732         monitor(0);
13733 #endif
13734 #ifdef GPROF
13735         {
13736                 extern void _mcleanup(void);
13737                 _mcleanup();
13738         }
13739 #endif
13740         TRACE(("End of main reached\n"));
13741         exitshell();
13742         /* NOTREACHED */
13743 }
13744
13745
13746 /*-
13747  * Copyright (c) 1989, 1991, 1993, 1994
13748  *      The Regents of the University of California.  All rights reserved.
13749  *
13750  * This code is derived from software contributed to Berkeley by
13751  * Kenneth Almquist.
13752  *
13753  * Redistribution and use in source and binary forms, with or without
13754  * modification, are permitted provided that the following conditions
13755  * are met:
13756  * 1. Redistributions of source code must retain the above copyright
13757  *    notice, this list of conditions and the following disclaimer.
13758  * 2. Redistributions in binary form must reproduce the above copyright
13759  *    notice, this list of conditions and the following disclaimer in the
13760  *    documentation and/or other materials provided with the distribution.
13761  * 3. Neither the name of the University nor the names of its contributors
13762  *    may be used to endorse or promote products derived from this software
13763  *    without specific prior written permission.
13764  *
13765  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13766  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13767  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13768  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13769  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13770  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13771  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13772  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13773  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13774  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13775  * SUCH DAMAGE.
13776  */