ash: sync up with dash with respect to redirection escaping
[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 #endif
218 #if ENABLE_ASH_RANDOM_SUPPORT
219 # include "random.h"
220 #else
221 # define CLEAR_RANDOM_T(rnd) ((void)0)
222 #endif
223
224 #include "NUM_APPLETS.h"
225 #if NUM_APPLETS == 1
226 /* STANDALONE does not make sense, and won't compile */
227 # undef CONFIG_FEATURE_SH_STANDALONE
228 # undef ENABLE_FEATURE_SH_STANDALONE
229 # undef IF_FEATURE_SH_STANDALONE
230 # undef IF_NOT_FEATURE_SH_STANDALONE
231 # define ENABLE_FEATURE_SH_STANDALONE 0
232 # define IF_FEATURE_SH_STANDALONE(...)
233 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
234 #endif
235
236 #ifndef PIPE_BUF
237 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
238 #endif
239
240 #if !BB_MMU
241 # error "Do not even bother, ash will not run on NOMMU machine"
242 #endif
243
244
245 /* ============ Hash table sizes. Configurable. */
246
247 #define VTABSIZE 39
248 #define ATABSIZE 39
249 #define CMDTABLESIZE 31         /* should be prime */
250
251
252 /* ============ Shell options */
253
254 static const char *const optletters_optnames[] = {
255         "e"   "errexit",
256         "f"   "noglob",
257         "I"   "ignoreeof",
258         "i"   "interactive",
259         "m"   "monitor",
260         "n"   "noexec",
261         "s"   "stdin",
262         "x"   "xtrace",
263         "v"   "verbose",
264         "C"   "noclobber",
265         "a"   "allexport",
266         "b"   "notify",
267         "u"   "nounset",
268         "\0"  "vi"
269 #if BASH_PIPEFAIL
270         ,"\0"  "pipefail"
271 #endif
272 #if DEBUG
273         ,"\0"  "nolog"
274         ,"\0"  "debug"
275 #endif
276 };
277
278 #define optletters(n)  optletters_optnames[n][0]
279 #define optnames(n)   (optletters_optnames[n] + 1)
280
281 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
282
283
284 /* ============ Misc data */
285
286 #define msg_illnum "Illegal number: %s"
287
288 /*
289  * We enclose jmp_buf in a structure so that we can declare pointers to
290  * jump locations.  The global variable handler contains the location to
291  * jump to when an exception occurs, and the global variable exception_type
292  * contains a code identifying the exception.  To implement nested
293  * exception handlers, the user should save the value of handler on entry
294  * to an inner scope, set handler to point to a jmploc structure for the
295  * inner scope, and restore handler on exit from the scope.
296  */
297 struct jmploc {
298         jmp_buf loc;
299 };
300
301 struct globals_misc {
302         uint8_t exitstatus;     /* exit status of last command */
303         uint8_t back_exitstatus;/* exit status of backquoted command */
304         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
305         int rootpid;            /* pid of main shell */
306         /* shell level: 0 for the main shell, 1 for its children, and so on */
307         int shlvl;
308 #define rootshell (!shlvl)
309         char *minusc;  /* argument to -c option */
310
311         char *curdir; // = nullstr;     /* current working directory */
312         char *physdir; // = nullstr;    /* physical working directory */
313
314         char *arg0; /* value of $0 */
315
316         struct jmploc *exception_handler;
317
318         volatile int suppress_int; /* counter */
319         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
320         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
321         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
322         smallint exception_type; /* kind of exception (0..5) */
323         /* exceptions */
324 #define EXINT 0         /* SIGINT received */
325 #define EXERROR 1       /* a generic error */
326 #define EXEXIT 4        /* exit the shell */
327
328         smallint isloginsh;
329         char nullstr[1];        /* zero length string */
330
331         char optlist[NOPTS];
332 #define eflag optlist[0]
333 #define fflag optlist[1]
334 #define Iflag optlist[2]
335 #define iflag optlist[3]
336 #define mflag optlist[4]
337 #define nflag optlist[5]
338 #define sflag optlist[6]
339 #define xflag optlist[7]
340 #define vflag optlist[8]
341 #define Cflag optlist[9]
342 #define aflag optlist[10]
343 #define bflag optlist[11]
344 #define uflag optlist[12]
345 #define viflag optlist[13]
346 #if BASH_PIPEFAIL
347 # define pipefail optlist[14]
348 #else
349 # define pipefail 0
350 #endif
351 #if DEBUG
352 # define nolog optlist[14 + BASH_PIPEFAIL]
353 # define debug optlist[15 + BASH_PIPEFAIL]
354 #endif
355
356         /* trap handler commands */
357         /*
358          * Sigmode records the current value of the signal handlers for the various
359          * modes.  A value of zero means that the current handler is not known.
360          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
361          */
362         char sigmode[NSIG - 1];
363 #define S_DFL      1            /* default signal handling (SIG_DFL) */
364 #define S_CATCH    2            /* signal is caught */
365 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
366 #define S_HARD_IGN 4            /* signal is ignored permanently */
367
368         /* indicates specified signal received */
369         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
370         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
371         char *trap[NSIG];
372         char **trap_ptr;        /* used only by "trap hack" */
373
374         /* Rarely referenced stuff */
375 #if ENABLE_ASH_RANDOM_SUPPORT
376         random_t random_gen;
377 #endif
378         pid_t backgndpid;        /* pid of last background process */
379 };
380 extern struct globals_misc *const ash_ptr_to_globals_misc;
381 #define G_misc (*ash_ptr_to_globals_misc)
382 #define exitstatus        (G_misc.exitstatus )
383 #define back_exitstatus   (G_misc.back_exitstatus )
384 #define job_warning       (G_misc.job_warning)
385 #define rootpid     (G_misc.rootpid    )
386 #define shlvl       (G_misc.shlvl      )
387 #define minusc      (G_misc.minusc     )
388 #define curdir      (G_misc.curdir     )
389 #define physdir     (G_misc.physdir    )
390 #define arg0        (G_misc.arg0       )
391 #define exception_handler (G_misc.exception_handler)
392 #define exception_type    (G_misc.exception_type   )
393 #define suppress_int      (G_misc.suppress_int     )
394 #define pending_int       (G_misc.pending_int      )
395 #define got_sigchld       (G_misc.got_sigchld      )
396 #define pending_sig       (G_misc.pending_sig      )
397 #define isloginsh   (G_misc.isloginsh  )
398 #define nullstr     (G_misc.nullstr    )
399 #define optlist     (G_misc.optlist    )
400 #define sigmode     (G_misc.sigmode    )
401 #define gotsig      (G_misc.gotsig     )
402 #define may_have_traps    (G_misc.may_have_traps   )
403 #define trap        (G_misc.trap       )
404 #define trap_ptr    (G_misc.trap_ptr   )
405 #define random_gen  (G_misc.random_gen )
406 #define backgndpid  (G_misc.backgndpid )
407 #define INIT_G_misc() do { \
408         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
409         barrier(); \
410         curdir = nullstr; \
411         physdir = nullstr; \
412         trap_ptr = trap; \
413 } while (0)
414
415
416 /* ============ DEBUG */
417 #if DEBUG
418 static void trace_printf(const char *fmt, ...);
419 static void trace_vprintf(const char *fmt, va_list va);
420 # define TRACE(param)    trace_printf param
421 # define TRACEV(param)   trace_vprintf param
422 # define close(fd) do { \
423         int dfd = (fd); \
424         if (close(dfd) < 0) \
425                 bb_error_msg("bug on %d: closing %d(0x%x)", \
426                         __LINE__, dfd, dfd); \
427 } while (0)
428 #else
429 # define TRACE(param)
430 # define TRACEV(param)
431 #endif
432
433
434 /* ============ Utility functions */
435 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
436 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
437
438 static int
439 isdigit_str9(const char *str)
440 {
441         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
442         while (--maxlen && isdigit(*str))
443                 str++;
444         return (*str == '\0');
445 }
446
447 static const char *
448 var_end(const char *var)
449 {
450         while (*var)
451                 if (*var++ == '=')
452                         break;
453         return var;
454 }
455
456
457 /* ============ Interrupts / exceptions */
458
459 static void exitshell(void) NORETURN;
460
461 /*
462  * These macros allow the user to suspend the handling of interrupt signals
463  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
464  * much more efficient and portable.  (But hacking the kernel is so much
465  * more fun than worrying about efficiency and portability. :-))
466  */
467 #if DEBUG_INTONOFF
468 # define INT_OFF do { \
469         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
470         suppress_int++; \
471         barrier(); \
472 } while (0)
473 #else
474 # define INT_OFF do { \
475         suppress_int++; \
476         barrier(); \
477 } while (0)
478 #endif
479
480 /*
481  * Called to raise an exception.  Since C doesn't include exceptions, we
482  * just do a longjmp to the exception handler.  The type of exception is
483  * stored in the global variable "exception_type".
484  */
485 static void raise_exception(int) NORETURN;
486 static void
487 raise_exception(int e)
488 {
489 #if DEBUG
490         if (exception_handler == NULL)
491                 abort();
492 #endif
493         INT_OFF;
494         exception_type = e;
495         longjmp(exception_handler->loc, 1);
496 }
497 #if DEBUG
498 #define raise_exception(e) do { \
499         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
500         raise_exception(e); \
501 } while (0)
502 #endif
503
504 /*
505  * Called when a SIGINT is received.  (If the user specifies
506  * that SIGINT is to be trapped or ignored using the trap builtin, then
507  * this routine is not called.)  Suppressint is nonzero when interrupts
508  * are held using the INT_OFF macro.  (The test for iflag is just
509  * defensive programming.)
510  */
511 static void raise_interrupt(void) NORETURN;
512 static void
513 raise_interrupt(void)
514 {
515         pending_int = 0;
516         /* Signal is not automatically unmasked after it is raised,
517          * do it ourself - unmask all signals */
518         sigprocmask_allsigs(SIG_UNBLOCK);
519         /* pending_sig = 0; - now done in signal_handler() */
520
521         if (!(rootshell && iflag)) {
522                 /* Kill ourself with SIGINT */
523                 signal(SIGINT, SIG_DFL);
524                 raise(SIGINT);
525         }
526         /* bash: ^C even on empty command line sets $? */
527         exitstatus = SIGINT + 128;
528         raise_exception(EXINT);
529         /* NOTREACHED */
530 }
531 #if DEBUG
532 #define raise_interrupt() do { \
533         TRACE(("raising interrupt on line %d\n", __LINE__)); \
534         raise_interrupt(); \
535 } while (0)
536 #endif
537
538 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
539 int_on(void)
540 {
541         barrier();
542         if (--suppress_int == 0 && pending_int) {
543                 raise_interrupt();
544         }
545 }
546 #if DEBUG_INTONOFF
547 # define INT_ON do { \
548         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
549         int_on(); \
550 } while (0)
551 #else
552 # define INT_ON int_on()
553 #endif
554 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
555 force_int_on(void)
556 {
557         barrier();
558         suppress_int = 0;
559         if (pending_int)
560                 raise_interrupt();
561 }
562 #define FORCE_INT_ON force_int_on()
563
564 #define SAVE_INT(v) ((v) = suppress_int)
565
566 #define RESTORE_INT(v) do { \
567         barrier(); \
568         suppress_int = (v); \
569         if (suppress_int == 0 && pending_int) \
570                 raise_interrupt(); \
571 } while (0)
572
573
574 /* ============ Stdout/stderr output */
575
576 static void
577 outstr(const char *p, FILE *file)
578 {
579         INT_OFF;
580         fputs(p, file);
581         INT_ON;
582 }
583
584 static void
585 flush_stdout_stderr(void)
586 {
587         INT_OFF;
588         fflush_all();
589         INT_ON;
590 }
591
592 /* Was called outcslow(c,FILE*), but c was always '\n' */
593 static void
594 newline_and_flush(FILE *dest)
595 {
596         INT_OFF;
597         putc('\n', dest);
598         fflush(dest);
599         INT_ON;
600 }
601
602 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
603 static int
604 out1fmt(const char *fmt, ...)
605 {
606         va_list ap;
607         int r;
608
609         INT_OFF;
610         va_start(ap, fmt);
611         r = vprintf(fmt, ap);
612         va_end(ap);
613         INT_ON;
614         return r;
615 }
616
617 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
618 static int
619 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
620 {
621         va_list ap;
622         int ret;
623
624         va_start(ap, fmt);
625         INT_OFF;
626         ret = vsnprintf(outbuf, length, fmt, ap);
627         va_end(ap);
628         INT_ON;
629         return ret;
630 }
631
632 static void
633 out1str(const char *p)
634 {
635         outstr(p, stdout);
636 }
637
638 static void
639 out2str(const char *p)
640 {
641         outstr(p, stderr);
642         flush_stdout_stderr();
643 }
644
645
646 /* ============ Parser structures */
647
648 /* control characters in argument strings */
649 #define CTL_FIRST CTLESC
650 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
651 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
652 #define CTLENDVAR    ((unsigned char)'\203')
653 #define CTLBACKQ     ((unsigned char)'\204')
654 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
655 #define CTLENDARI    ((unsigned char)'\207')
656 #define CTLQUOTEMARK ((unsigned char)'\210')
657 #define CTL_LAST CTLQUOTEMARK
658
659 /* variable substitution byte (follows CTLVAR) */
660 #define VSTYPE  0x0f            /* type of variable substitution */
661 #define VSNUL   0x10            /* colon--treat the empty string as unset */
662
663 /* values of VSTYPE field */
664 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
665 #define VSMINUS         0x2     /* ${var-text} */
666 #define VSPLUS          0x3     /* ${var+text} */
667 #define VSQUESTION      0x4     /* ${var?message} */
668 #define VSASSIGN        0x5     /* ${var=text} */
669 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
670 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
671 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
672 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
673 #define VSLENGTH        0xa     /* ${#var} */
674 #if BASH_SUBSTR
675 #define VSSUBSTR        0xc     /* ${var:position:length} */
676 #endif
677 #if BASH_PATTERN_SUBST
678 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
679 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
680 #endif
681
682 static const char dolatstr[] ALIGN1 = {
683         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
684 };
685 #define DOLATSTRLEN 6
686
687 #define NCMD      0
688 #define NPIPE     1
689 #define NREDIR    2
690 #define NBACKGND  3
691 #define NSUBSHELL 4
692 #define NAND      5
693 #define NOR       6
694 #define NSEMI     7
695 #define NIF       8
696 #define NWHILE    9
697 #define NUNTIL   10
698 #define NFOR     11
699 #define NCASE    12
700 #define NCLIST   13
701 #define NDEFUN   14
702 #define NARG     15
703 #define NTO      16
704 #if BASH_REDIR_OUTPUT
705 #define NTO2     17
706 #endif
707 #define NCLOBBER 18
708 #define NFROM    19
709 #define NFROMTO  20
710 #define NAPPEND  21
711 #define NTOFD    22
712 #define NFROMFD  23
713 #define NHERE    24
714 #define NXHERE   25
715 #define NNOT     26
716 #define N_NUMBER 27
717
718 union node;
719
720 struct ncmd {
721         smallint type; /* Nxxxx */
722         union node *assign;
723         union node *args;
724         union node *redirect;
725 };
726
727 struct npipe {
728         smallint type;
729         smallint pipe_backgnd;
730         struct nodelist *cmdlist;
731 };
732
733 struct nredir {
734         smallint type;
735         union node *n;
736         union node *redirect;
737 };
738
739 struct nbinary {
740         smallint type;
741         union node *ch1;
742         union node *ch2;
743 };
744
745 struct nif {
746         smallint type;
747         union node *test;
748         union node *ifpart;
749         union node *elsepart;
750 };
751
752 struct nfor {
753         smallint type;
754         union node *args;
755         union node *body;
756         char *var;
757 };
758
759 struct ncase {
760         smallint type;
761         union node *expr;
762         union node *cases;
763 };
764
765 struct nclist {
766         smallint type;
767         union node *next;
768         union node *pattern;
769         union node *body;
770 };
771
772 struct narg {
773         smallint type;
774         union node *next;
775         char *text;
776         struct nodelist *backquote;
777 };
778
779 /* nfile and ndup layout must match!
780  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
781  * that it is actually NTO2 (>&file), and change its type.
782  */
783 struct nfile {
784         smallint type;
785         union node *next;
786         int fd;
787         int _unused_dupfd;
788         union node *fname;
789         char *expfname;
790 };
791
792 struct ndup {
793         smallint type;
794         union node *next;
795         int fd;
796         int dupfd;
797         union node *vname;
798         char *_unused_expfname;
799 };
800
801 struct nhere {
802         smallint type;
803         union node *next;
804         int fd;
805         union node *doc;
806 };
807
808 struct nnot {
809         smallint type;
810         union node *com;
811 };
812
813 union node {
814         smallint type;
815         struct ncmd ncmd;
816         struct npipe npipe;
817         struct nredir nredir;
818         struct nbinary nbinary;
819         struct nif nif;
820         struct nfor nfor;
821         struct ncase ncase;
822         struct nclist nclist;
823         struct narg narg;
824         struct nfile nfile;
825         struct ndup ndup;
826         struct nhere nhere;
827         struct nnot nnot;
828 };
829
830 /*
831  * NODE_EOF is returned by parsecmd when it encounters an end of file.
832  * It must be distinct from NULL.
833  */
834 #define NODE_EOF ((union node *) -1L)
835
836 struct nodelist {
837         struct nodelist *next;
838         union node *n;
839 };
840
841 struct funcnode {
842         int count;
843         union node n;
844 };
845
846 /*
847  * Free a parse tree.
848  */
849 static void
850 freefunc(struct funcnode *f)
851 {
852         if (f && --f->count < 0)
853                 free(f);
854 }
855
856
857 /* ============ Debugging output */
858
859 #if DEBUG
860
861 static FILE *tracefile;
862
863 static void
864 trace_printf(const char *fmt, ...)
865 {
866         va_list va;
867
868         if (debug != 1)
869                 return;
870         if (DEBUG_TIME)
871                 fprintf(tracefile, "%u ", (int) time(NULL));
872         if (DEBUG_PID)
873                 fprintf(tracefile, "[%u] ", (int) getpid());
874         if (DEBUG_SIG)
875                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
876         va_start(va, fmt);
877         vfprintf(tracefile, fmt, va);
878         va_end(va);
879 }
880
881 static void
882 trace_vprintf(const char *fmt, va_list va)
883 {
884         if (debug != 1)
885                 return;
886         vfprintf(tracefile, fmt, va);
887         fprintf(tracefile, "\n");
888 }
889
890 static void
891 trace_puts(const char *s)
892 {
893         if (debug != 1)
894                 return;
895         fputs(s, tracefile);
896 }
897
898 static void
899 trace_puts_quoted(char *s)
900 {
901         char *p;
902         char c;
903
904         if (debug != 1)
905                 return;
906         putc('"', tracefile);
907         for (p = s; *p; p++) {
908                 switch ((unsigned char)*p) {
909                 case '\n': c = 'n'; goto backslash;
910                 case '\t': c = 't'; goto backslash;
911                 case '\r': c = 'r'; goto backslash;
912                 case '\"': c = '\"'; goto backslash;
913                 case '\\': c = '\\'; goto backslash;
914                 case CTLESC: c = 'e'; goto backslash;
915                 case CTLVAR: c = 'v'; goto backslash;
916                 case CTLBACKQ: c = 'q'; goto backslash;
917  backslash:
918                         putc('\\', tracefile);
919                         putc(c, tracefile);
920                         break;
921                 default:
922                         if (*p >= ' ' && *p <= '~')
923                                 putc(*p, tracefile);
924                         else {
925                                 putc('\\', tracefile);
926                                 putc((*p >> 6) & 03, tracefile);
927                                 putc((*p >> 3) & 07, tracefile);
928                                 putc(*p & 07, tracefile);
929                         }
930                         break;
931                 }
932         }
933         putc('"', tracefile);
934 }
935
936 static void
937 trace_puts_args(char **ap)
938 {
939         if (debug != 1)
940                 return;
941         if (!*ap)
942                 return;
943         while (1) {
944                 trace_puts_quoted(*ap);
945                 if (!*++ap) {
946                         putc('\n', tracefile);
947                         break;
948                 }
949                 putc(' ', tracefile);
950         }
951 }
952
953 static void
954 opentrace(void)
955 {
956         char s[100];
957 #ifdef O_APPEND
958         int flags;
959 #endif
960
961         if (debug != 1) {
962                 if (tracefile)
963                         fflush(tracefile);
964                 /* leave open because libedit might be using it */
965                 return;
966         }
967         strcpy(s, "./trace");
968         if (tracefile) {
969                 if (!freopen(s, "a", tracefile)) {
970                         fprintf(stderr, "Can't re-open %s\n", s);
971                         debug = 0;
972                         return;
973                 }
974         } else {
975                 tracefile = fopen(s, "a");
976                 if (tracefile == NULL) {
977                         fprintf(stderr, "Can't open %s\n", s);
978                         debug = 0;
979                         return;
980                 }
981         }
982 #ifdef O_APPEND
983         flags = fcntl(fileno(tracefile), F_GETFL);
984         if (flags >= 0)
985                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
986 #endif
987         setlinebuf(tracefile);
988         fputs("\nTracing started.\n", tracefile);
989 }
990
991 static void
992 indent(int amount, char *pfx, FILE *fp)
993 {
994         int i;
995
996         for (i = 0; i < amount; i++) {
997                 if (pfx && i == amount - 1)
998                         fputs(pfx, fp);
999                 putc('\t', fp);
1000         }
1001 }
1002
1003 /* little circular references here... */
1004 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1005
1006 static void
1007 sharg(union node *arg, FILE *fp)
1008 {
1009         char *p;
1010         struct nodelist *bqlist;
1011         unsigned char subtype;
1012
1013         if (arg->type != NARG) {
1014                 out1fmt("<node type %d>\n", arg->type);
1015                 abort();
1016         }
1017         bqlist = arg->narg.backquote;
1018         for (p = arg->narg.text; *p; p++) {
1019                 switch ((unsigned char)*p) {
1020                 case CTLESC:
1021                         p++;
1022                         putc(*p, fp);
1023                         break;
1024                 case CTLVAR:
1025                         putc('$', fp);
1026                         putc('{', fp);
1027                         subtype = *++p;
1028                         if (subtype == VSLENGTH)
1029                                 putc('#', fp);
1030
1031                         while (*p != '=') {
1032                                 putc(*p, fp);
1033                                 p++;
1034                         }
1035
1036                         if (subtype & VSNUL)
1037                                 putc(':', fp);
1038
1039                         switch (subtype & VSTYPE) {
1040                         case VSNORMAL:
1041                                 putc('}', fp);
1042                                 break;
1043                         case VSMINUS:
1044                                 putc('-', fp);
1045                                 break;
1046                         case VSPLUS:
1047                                 putc('+', fp);
1048                                 break;
1049                         case VSQUESTION:
1050                                 putc('?', fp);
1051                                 break;
1052                         case VSASSIGN:
1053                                 putc('=', fp);
1054                                 break;
1055                         case VSTRIMLEFT:
1056                                 putc('#', fp);
1057                                 break;
1058                         case VSTRIMLEFTMAX:
1059                                 putc('#', fp);
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMRIGHT:
1063                                 putc('%', fp);
1064                                 break;
1065                         case VSTRIMRIGHTMAX:
1066                                 putc('%', fp);
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSLENGTH:
1070                                 break;
1071                         default:
1072                                 out1fmt("<subtype %d>", subtype);
1073                         }
1074                         break;
1075                 case CTLENDVAR:
1076                         putc('}', fp);
1077                         break;
1078                 case CTLBACKQ:
1079                         putc('$', fp);
1080                         putc('(', fp);
1081                         shtree(bqlist->n, -1, NULL, fp);
1082                         putc(')', fp);
1083                         break;
1084                 default:
1085                         putc(*p, fp);
1086                         break;
1087                 }
1088         }
1089 }
1090
1091 static void
1092 shcmd(union node *cmd, FILE *fp)
1093 {
1094         union node *np;
1095         int first;
1096         const char *s;
1097         int dftfd;
1098
1099         first = 1;
1100         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1101                 if (!first)
1102                         putc(' ', fp);
1103                 sharg(np, fp);
1104                 first = 0;
1105         }
1106         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1107                 if (!first)
1108                         putc(' ', fp);
1109                 dftfd = 0;
1110                 switch (np->nfile.type) {
1111                 case NTO:      s = ">>"+1; dftfd = 1; break;
1112                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1113                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1114 #if BASH_REDIR_OUTPUT
1115                 case NTO2:
1116 #endif
1117                 case NTOFD:    s = ">&"; dftfd = 1; break;
1118                 case NFROM:    s = "<"; break;
1119                 case NFROMFD:  s = "<&"; break;
1120                 case NFROMTO:  s = "<>"; break;
1121                 default:       s = "*error*"; break;
1122                 }
1123                 if (np->nfile.fd != dftfd)
1124                         fprintf(fp, "%d", np->nfile.fd);
1125                 fputs(s, fp);
1126                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1127                         fprintf(fp, "%d", np->ndup.dupfd);
1128                 } else {
1129                         sharg(np->nfile.fname, fp);
1130                 }
1131                 first = 0;
1132         }
1133 }
1134
1135 static void
1136 shtree(union node *n, int ind, char *pfx, FILE *fp)
1137 {
1138         struct nodelist *lp;
1139         const char *s;
1140
1141         if (n == NULL)
1142                 return;
1143
1144         indent(ind, pfx, fp);
1145
1146         if (n == NODE_EOF) {
1147                 fputs("<EOF>", fp);
1148                 return;
1149         }
1150
1151         switch (n->type) {
1152         case NSEMI:
1153                 s = "; ";
1154                 goto binop;
1155         case NAND:
1156                 s = " && ";
1157                 goto binop;
1158         case NOR:
1159                 s = " || ";
1160  binop:
1161                 shtree(n->nbinary.ch1, ind, NULL, fp);
1162                 /* if (ind < 0) */
1163                         fputs(s, fp);
1164                 shtree(n->nbinary.ch2, ind, NULL, fp);
1165                 break;
1166         case NCMD:
1167                 shcmd(n, fp);
1168                 if (ind >= 0)
1169                         putc('\n', fp);
1170                 break;
1171         case NPIPE:
1172                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1173                         shtree(lp->n, 0, NULL, fp);
1174                         if (lp->next)
1175                                 fputs(" | ", fp);
1176                 }
1177                 if (n->npipe.pipe_backgnd)
1178                         fputs(" &", fp);
1179                 if (ind >= 0)
1180                         putc('\n', fp);
1181                 break;
1182         default:
1183                 fprintf(fp, "<node type %d>", n->type);
1184                 if (ind >= 0)
1185                         putc('\n', fp);
1186                 break;
1187         }
1188 }
1189
1190 static void
1191 showtree(union node *n)
1192 {
1193         trace_puts("showtree called\n");
1194         shtree(n, 1, NULL, stderr);
1195 }
1196
1197 #endif /* DEBUG */
1198
1199
1200 /* ============ Parser data */
1201
1202 /*
1203  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1204  */
1205 struct strlist {
1206         struct strlist *next;
1207         char *text;
1208 };
1209
1210 struct alias;
1211
1212 struct strpush {
1213         struct strpush *prev;   /* preceding string on stack */
1214         char *prev_string;
1215         int prev_left_in_line;
1216 #if ENABLE_ASH_ALIAS
1217         struct alias *ap;       /* if push was associated with an alias */
1218 #endif
1219         char *string;           /* remember the string since it may change */
1220
1221         /* Remember last two characters for pungetc. */
1222         int lastc[2];
1223
1224         /* Number of outstanding calls to pungetc. */
1225         int unget;
1226 };
1227
1228 struct parsefile {
1229         struct parsefile *prev; /* preceding file on stack */
1230         int linno;              /* current line */
1231         int pf_fd;              /* file descriptor (or -1 if string) */
1232         int left_in_line;       /* number of chars left in this line */
1233         int left_in_buffer;     /* number of chars left in this buffer past the line */
1234         char *next_to_pgetc;    /* next char in buffer */
1235         char *buf;              /* input buffer */
1236         struct strpush *strpush; /* for pushing strings at this level */
1237         struct strpush basestrpush; /* so pushing one is fast */
1238
1239         /* Remember last two characters for pungetc. */
1240         int lastc[2];
1241
1242         /* Number of outstanding calls to pungetc. */
1243         int unget;
1244 };
1245
1246 static struct parsefile basepf;        /* top level input file */
1247 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1248 static int startlinno;                 /* line # where last token started */
1249 static char *commandname;              /* currently executing command */
1250 static struct strlist *cmdenviron;     /* environment for builtin command */
1251
1252
1253 /* ============ Message printing */
1254
1255 static void
1256 ash_vmsg(const char *msg, va_list ap)
1257 {
1258         fprintf(stderr, "%s: ", arg0);
1259         if (commandname) {
1260                 if (strcmp(arg0, commandname))
1261                         fprintf(stderr, "%s: ", commandname);
1262                 if (!iflag || g_parsefile->pf_fd > 0)
1263                         fprintf(stderr, "line %d: ", startlinno);
1264         }
1265         vfprintf(stderr, msg, ap);
1266         newline_and_flush(stderr);
1267 }
1268
1269 /*
1270  * Exverror is called to raise the error exception.  If the second argument
1271  * is not NULL then error prints an error message using printf style
1272  * formatting.  It then raises the error exception.
1273  */
1274 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1275 static void
1276 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1277 {
1278 #if DEBUG
1279         if (msg) {
1280                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1281                 TRACEV((msg, ap));
1282         } else
1283                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1284         if (msg)
1285 #endif
1286                 ash_vmsg(msg, ap);
1287
1288         flush_stdout_stderr();
1289         raise_exception(cond);
1290         /* NOTREACHED */
1291 }
1292
1293 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1294 static void
1295 ash_msg_and_raise_error(const char *msg, ...)
1296 {
1297         va_list ap;
1298
1299         exitstatus = 2;
1300
1301         va_start(ap, msg);
1302         ash_vmsg_and_raise(EXERROR, msg, ap);
1303         /* NOTREACHED */
1304         va_end(ap);
1305 }
1306
1307 static void raise_error_syntax(const char *) NORETURN;
1308 static void
1309 raise_error_syntax(const char *msg)
1310 {
1311         ash_msg_and_raise_error("syntax error: %s", msg);
1312         /* NOTREACHED */
1313 }
1314
1315 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1316 static void
1317 ash_msg_and_raise(int cond, const char *msg, ...)
1318 {
1319         va_list ap;
1320
1321         va_start(ap, msg);
1322         ash_vmsg_and_raise(cond, msg, ap);
1323         /* NOTREACHED */
1324         va_end(ap);
1325 }
1326
1327 /*
1328  * error/warning routines for external builtins
1329  */
1330 static void
1331 ash_msg(const char *fmt, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, fmt);
1336         ash_vmsg(fmt, ap);
1337         va_end(ap);
1338 }
1339
1340 /*
1341  * Return a string describing an error.  The returned string may be a
1342  * pointer to a static buffer that will be overwritten on the next call.
1343  * Action describes the operation that got the error.
1344  */
1345 static const char *
1346 errmsg(int e, const char *em)
1347 {
1348         if (e == ENOENT || e == ENOTDIR) {
1349                 return em;
1350         }
1351         return strerror(e);
1352 }
1353
1354
1355 /* ============ Memory allocation */
1356
1357 #if 0
1358 /* I consider these wrappers nearly useless:
1359  * ok, they return you to nearest exception handler, but
1360  * how much memory do you leak in the process, making
1361  * memory starvation worse?
1362  */
1363 static void *
1364 ckrealloc(void * p, size_t nbytes)
1365 {
1366         p = realloc(p, nbytes);
1367         if (!p)
1368                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1369         return p;
1370 }
1371
1372 static void *
1373 ckmalloc(size_t nbytes)
1374 {
1375         return ckrealloc(NULL, nbytes);
1376 }
1377
1378 static void *
1379 ckzalloc(size_t nbytes)
1380 {
1381         return memset(ckmalloc(nbytes), 0, nbytes);
1382 }
1383
1384 static char *
1385 ckstrdup(const char *s)
1386 {
1387         char *p = strdup(s);
1388         if (!p)
1389                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1390         return p;
1391 }
1392 #else
1393 /* Using bbox equivalents. They exit if out of memory */
1394 # define ckrealloc xrealloc
1395 # define ckmalloc  xmalloc
1396 # define ckzalloc  xzalloc
1397 # define ckstrdup  xstrdup
1398 #endif
1399
1400 /*
1401  * It appears that grabstackstr() will barf with such alignments
1402  * because stalloc() will return a string allocated in a new stackblock.
1403  */
1404 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1405 enum {
1406         /* Most machines require the value returned from malloc to be aligned
1407          * in some way.  The following macro will get this right
1408          * on many machines.  */
1409         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1410         /* Minimum size of a block */
1411         MINSIZE = SHELL_ALIGN(504),
1412 };
1413
1414 struct stack_block {
1415         struct stack_block *prev;
1416         char space[MINSIZE];
1417 };
1418
1419 struct stackmark {
1420         struct stack_block *stackp;
1421         char *stacknxt;
1422         size_t stacknleft;
1423 };
1424
1425
1426 struct globals_memstack {
1427         struct stack_block *g_stackp; // = &stackbase;
1428         char *g_stacknxt; // = stackbase.space;
1429         char *sstrend; // = stackbase.space + MINSIZE;
1430         size_t g_stacknleft; // = MINSIZE;
1431         struct stack_block stackbase;
1432 };
1433 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1434 #define G_memstack (*ash_ptr_to_globals_memstack)
1435 #define g_stackp     (G_memstack.g_stackp    )
1436 #define g_stacknxt   (G_memstack.g_stacknxt  )
1437 #define sstrend      (G_memstack.sstrend     )
1438 #define g_stacknleft (G_memstack.g_stacknleft)
1439 #define stackbase    (G_memstack.stackbase   )
1440 #define INIT_G_memstack() do { \
1441         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1442         barrier(); \
1443         g_stackp = &stackbase; \
1444         g_stacknxt = stackbase.space; \
1445         g_stacknleft = MINSIZE; \
1446         sstrend = stackbase.space + MINSIZE; \
1447 } while (0)
1448
1449
1450 #define stackblock()     ((void *)g_stacknxt)
1451 #define stackblocksize() g_stacknleft
1452
1453 /*
1454  * Parse trees for commands are allocated in lifo order, so we use a stack
1455  * to make this more efficient, and also to avoid all sorts of exception
1456  * handling code to handle interrupts in the middle of a parse.
1457  *
1458  * The size 504 was chosen because the Ultrix malloc handles that size
1459  * well.
1460  */
1461 static void *
1462 stalloc(size_t nbytes)
1463 {
1464         char *p;
1465         size_t aligned;
1466
1467         aligned = SHELL_ALIGN(nbytes);
1468         if (aligned > g_stacknleft) {
1469                 size_t len;
1470                 size_t blocksize;
1471                 struct stack_block *sp;
1472
1473                 blocksize = aligned;
1474                 if (blocksize < MINSIZE)
1475                         blocksize = MINSIZE;
1476                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1477                 if (len < blocksize)
1478                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1479                 INT_OFF;
1480                 sp = ckmalloc(len);
1481                 sp->prev = g_stackp;
1482                 g_stacknxt = sp->space;
1483                 g_stacknleft = blocksize;
1484                 sstrend = g_stacknxt + blocksize;
1485                 g_stackp = sp;
1486                 INT_ON;
1487         }
1488         p = g_stacknxt;
1489         g_stacknxt += aligned;
1490         g_stacknleft -= aligned;
1491         return p;
1492 }
1493
1494 static void *
1495 stzalloc(size_t nbytes)
1496 {
1497         return memset(stalloc(nbytes), 0, nbytes);
1498 }
1499
1500 static void
1501 stunalloc(void *p)
1502 {
1503 #if DEBUG
1504         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1505                 write(STDERR_FILENO, "stunalloc\n", 10);
1506                 abort();
1507         }
1508 #endif
1509         g_stacknleft += g_stacknxt - (char *)p;
1510         g_stacknxt = p;
1511 }
1512
1513 /*
1514  * Like strdup but works with the ash stack.
1515  */
1516 static char *
1517 sstrdup(const char *p)
1518 {
1519         size_t len = strlen(p) + 1;
1520         return memcpy(stalloc(len), p, len);
1521 }
1522
1523 static inline void
1524 grabstackblock(size_t len)
1525 {
1526         stalloc(len);
1527 }
1528
1529 static void
1530 pushstackmark(struct stackmark *mark, size_t len)
1531 {
1532         mark->stackp = g_stackp;
1533         mark->stacknxt = g_stacknxt;
1534         mark->stacknleft = g_stacknleft;
1535         grabstackblock(len);
1536 }
1537
1538 static void
1539 setstackmark(struct stackmark *mark)
1540 {
1541         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1542 }
1543
1544 static void
1545 popstackmark(struct stackmark *mark)
1546 {
1547         struct stack_block *sp;
1548
1549         if (!mark->stackp)
1550                 return;
1551
1552         INT_OFF;
1553         while (g_stackp != mark->stackp) {
1554                 sp = g_stackp;
1555                 g_stackp = sp->prev;
1556                 free(sp);
1557         }
1558         g_stacknxt = mark->stacknxt;
1559         g_stacknleft = mark->stacknleft;
1560         sstrend = mark->stacknxt + mark->stacknleft;
1561         INT_ON;
1562 }
1563
1564 /*
1565  * When the parser reads in a string, it wants to stick the string on the
1566  * stack and only adjust the stack pointer when it knows how big the
1567  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1568  * of space on top of the stack and stackblocklen returns the length of
1569  * this block.  Growstackblock will grow this space by at least one byte,
1570  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1571  * part of the block that has been used.
1572  */
1573 static void
1574 growstackblock(void)
1575 {
1576         size_t newlen;
1577
1578         newlen = g_stacknleft * 2;
1579         if (newlen < g_stacknleft)
1580                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1581         if (newlen < 128)
1582                 newlen += 128;
1583
1584         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1585                 struct stack_block *sp;
1586                 struct stack_block *prevstackp;
1587                 size_t grosslen;
1588
1589                 INT_OFF;
1590                 sp = g_stackp;
1591                 prevstackp = sp->prev;
1592                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1593                 sp = ckrealloc(sp, grosslen);
1594                 sp->prev = prevstackp;
1595                 g_stackp = sp;
1596                 g_stacknxt = sp->space;
1597                 g_stacknleft = newlen;
1598                 sstrend = sp->space + newlen;
1599                 INT_ON;
1600         } else {
1601                 char *oldspace = g_stacknxt;
1602                 size_t oldlen = g_stacknleft;
1603                 char *p = stalloc(newlen);
1604
1605                 /* free the space we just allocated */
1606                 g_stacknxt = memcpy(p, oldspace, oldlen);
1607                 g_stacknleft += newlen;
1608         }
1609 }
1610
1611 /*
1612  * The following routines are somewhat easier to use than the above.
1613  * The user declares a variable of type STACKSTR, which may be declared
1614  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1615  * the user uses the macro STPUTC to add characters to the string.  In
1616  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1617  * grown as necessary.  When the user is done, she can just leave the
1618  * string there and refer to it using stackblock().  Or she can allocate
1619  * the space for it using grabstackstr().  If it is necessary to allow
1620  * someone else to use the stack temporarily and then continue to grow
1621  * the string, the user should use grabstack to allocate the space, and
1622  * then call ungrabstr(p) to return to the previous mode of operation.
1623  *
1624  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1625  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1626  * is space for at least one character.
1627  */
1628 static void *
1629 growstackstr(void)
1630 {
1631         size_t len = stackblocksize();
1632         growstackblock();
1633         return (char *)stackblock() + len;
1634 }
1635
1636 /*
1637  * Called from CHECKSTRSPACE.
1638  */
1639 static char *
1640 makestrspace(size_t newlen, char *p)
1641 {
1642         size_t len = p - g_stacknxt;
1643         size_t size;
1644
1645         for (;;) {
1646                 size_t nleft;
1647
1648                 size = stackblocksize();
1649                 nleft = size - len;
1650                 if (nleft >= newlen)
1651                         break;
1652                 growstackblock();
1653         }
1654         return (char *)stackblock() + len;
1655 }
1656
1657 static char *
1658 stack_nputstr(const char *s, size_t n, char *p)
1659 {
1660         p = makestrspace(n, p);
1661         p = (char *)mempcpy(p, s, n);
1662         return p;
1663 }
1664
1665 static char *
1666 stack_putstr(const char *s, char *p)
1667 {
1668         return stack_nputstr(s, strlen(s), p);
1669 }
1670
1671 static char *
1672 _STPUTC(int c, char *p)
1673 {
1674         if (p == sstrend)
1675                 p = growstackstr();
1676         *p++ = c;
1677         return p;
1678 }
1679
1680 #define STARTSTACKSTR(p)        ((p) = stackblock())
1681 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1682 #define CHECKSTRSPACE(n, p) do { \
1683         char *q = (p); \
1684         size_t l = (n); \
1685         size_t m = sstrend - q; \
1686         if (l > m) \
1687                 (p) = makestrspace(l, q); \
1688 } while (0)
1689 #define USTPUTC(c, p)           (*(p)++ = (c))
1690 #define STACKSTRNUL(p) do { \
1691         if ((p) == sstrend) \
1692                 (p) = growstackstr(); \
1693         *(p) = '\0'; \
1694 } while (0)
1695 #define STUNPUTC(p)             (--(p))
1696 #define STTOPC(p)               ((p)[-1])
1697 #define STADJUST(amount, p)     ((p) += (amount))
1698
1699 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1700 #define ungrabstackstr(s, p)    stunalloc(s)
1701 #define stackstrend()           ((void *)sstrend)
1702
1703
1704 /* ============ String helpers */
1705
1706 /*
1707  * prefix -- see if pfx is a prefix of string.
1708  */
1709 static char *
1710 prefix(const char *string, const char *pfx)
1711 {
1712         while (*pfx) {
1713                 if (*pfx++ != *string++)
1714                         return NULL;
1715         }
1716         return (char *) string;
1717 }
1718
1719 /*
1720  * Check for a valid number.  This should be elsewhere.
1721  */
1722 static int
1723 is_number(const char *p)
1724 {
1725         do {
1726                 if (!isdigit(*p))
1727                         return 0;
1728         } while (*++p != '\0');
1729         return 1;
1730 }
1731
1732 /*
1733  * Convert a string of digits to an integer, printing an error message on
1734  * failure.
1735  */
1736 static int
1737 number(const char *s)
1738 {
1739         if (!is_number(s))
1740                 ash_msg_and_raise_error(msg_illnum, s);
1741         return atoi(s);
1742 }
1743
1744 /*
1745  * Produce a single quoted string suitable as input to the shell.
1746  * The return string is allocated on the stack.
1747  */
1748 static char *
1749 single_quote(const char *s)
1750 {
1751         char *p;
1752
1753         STARTSTACKSTR(p);
1754
1755         do {
1756                 char *q;
1757                 size_t len;
1758
1759                 len = strchrnul(s, '\'') - s;
1760
1761                 q = p = makestrspace(len + 3, p);
1762
1763                 *q++ = '\'';
1764                 q = (char *)mempcpy(q, s, len);
1765                 *q++ = '\'';
1766                 s += len;
1767
1768                 STADJUST(q - p, p);
1769
1770                 if (*s != '\'')
1771                         break;
1772                 len = 0;
1773                 do len++; while (*++s == '\'');
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '"';
1778                 q = (char *)mempcpy(q, s - len, len);
1779                 *q++ = '"';
1780
1781                 STADJUST(q - p, p);
1782         } while (*s);
1783
1784         USTPUTC('\0', p);
1785
1786         return stackblock();
1787 }
1788
1789 /*
1790  * Produce a possibly single quoted string suitable as input to the shell.
1791  * If quoting was done, the return string is allocated on the stack,
1792  * otherwise a pointer to the original string is returned.
1793  */
1794 static const char *
1795 maybe_single_quote(const char *s)
1796 {
1797         const char *p = s;
1798
1799         while (*p) {
1800                 /* Assuming ACSII */
1801                 /* quote ctrl_chars space !"#$%&'()* */
1802                 if (*p < '+')
1803                         goto need_quoting;
1804                 /* quote ;<=>? */
1805                 if (*p >= ';' && *p <= '?')
1806                         goto need_quoting;
1807                 /* quote `[\ */
1808                 if (*p == '`')
1809                         goto need_quoting;
1810                 if (*p == '[')
1811                         goto need_quoting;
1812                 if (*p == '\\')
1813                         goto need_quoting;
1814                 /* quote {|}~ DEL and high bytes */
1815                 if (*p > 'z')
1816                         goto need_quoting;
1817                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1818                 /* TODO: maybe avoid quoting % */
1819                 p++;
1820         }
1821         return s;
1822
1823  need_quoting:
1824         return single_quote(s);
1825 }
1826
1827
1828 /* ============ nextopt */
1829
1830 static char **argptr;                  /* argument list for builtin commands */
1831 static char *optionarg;                /* set by nextopt (like getopt) */
1832 static char *optptr;                   /* used by nextopt */
1833
1834 /*
1835  * XXX - should get rid of. Have all builtins use getopt(3).
1836  * The library getopt must have the BSD extension static variable
1837  * "optreset", otherwise it can't be used within the shell safely.
1838  *
1839  * Standard option processing (a la getopt) for builtin routines.
1840  * The only argument that is passed to nextopt is the option string;
1841  * the other arguments are unnecessary. It returns the character,
1842  * or '\0' on end of input.
1843  */
1844 static int
1845 nextopt(const char *optstring)
1846 {
1847         char *p;
1848         const char *q;
1849         char c;
1850
1851         p = optptr;
1852         if (p == NULL || *p == '\0') {
1853                 /* We ate entire "-param", take next one */
1854                 p = *argptr;
1855                 if (p == NULL)
1856                         return '\0';
1857                 if (*p != '-')
1858                         return '\0';
1859                 if (*++p == '\0') /* just "-" ? */
1860                         return '\0';
1861                 argptr++;
1862                 if (LONE_DASH(p)) /* "--" ? */
1863                         return '\0';
1864                 /* p => next "-param" */
1865         }
1866         /* p => some option char in the middle of a "-param" */
1867         c = *p++;
1868         for (q = optstring; *q != c;) {
1869                 if (*q == '\0')
1870                         ash_msg_and_raise_error("illegal option -%c", c);
1871                 if (*++q == ':')
1872                         q++;
1873         }
1874         if (*++q == ':') {
1875                 if (*p == '\0') {
1876                         p = *argptr++;
1877                         if (p == NULL)
1878                                 ash_msg_and_raise_error("no arg for -%c option", c);
1879                 }
1880                 optionarg = p;
1881                 p = NULL;
1882         }
1883         optptr = p;
1884         return c;
1885 }
1886
1887
1888 /* ============ Shell variables */
1889
1890 /*
1891  * The parsefile structure pointed to by the global variable parsefile
1892  * contains information about the current file being read.
1893  */
1894 struct shparam {
1895         int nparam;             /* # of positional parameters (without $0) */
1896 #if ENABLE_ASH_GETOPTS
1897         int optind;             /* next parameter to be processed by getopts */
1898         int optoff;             /* used by getopts */
1899 #endif
1900         unsigned char malloced; /* if parameter list dynamically allocated */
1901         char **p;               /* parameter list */
1902 };
1903
1904 /*
1905  * Free the list of positional parameters.
1906  */
1907 static void
1908 freeparam(volatile struct shparam *param)
1909 {
1910         if (param->malloced) {
1911                 char **ap, **ap1;
1912                 ap = ap1 = param->p;
1913                 while (*ap)
1914                         free(*ap++);
1915                 free(ap1);
1916         }
1917 }
1918
1919 #if ENABLE_ASH_GETOPTS
1920 static void FAST_FUNC getoptsreset(const char *value);
1921 #endif
1922
1923 struct var {
1924         struct var *next;               /* next entry in hash list */
1925         int flags;                      /* flags are defined above */
1926         const char *var_text;           /* name=value */
1927         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1928                                         /* the variable gets set/unset */
1929 };
1930
1931 struct localvar {
1932         struct localvar *next;          /* next local variable in list */
1933         struct var *vp;                 /* the variable that was made local */
1934         int flags;                      /* saved flags */
1935         const char *text;               /* saved text */
1936 };
1937
1938 /* flags */
1939 #define VEXPORT         0x01    /* variable is exported */
1940 #define VREADONLY       0x02    /* variable cannot be modified */
1941 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1942 #define VTEXTFIXED      0x08    /* text is statically allocated */
1943 #define VSTACK          0x10    /* text is allocated on the stack */
1944 #define VUNSET          0x20    /* the variable is not set */
1945 #define VNOFUNC         0x40    /* don't call the callback function */
1946 #define VNOSET          0x80    /* do not set variable - just readonly test */
1947 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1948 #if ENABLE_ASH_RANDOM_SUPPORT
1949 # define VDYNAMIC       0x200   /* dynamic variable */
1950 #else
1951 # define VDYNAMIC       0
1952 #endif
1953
1954
1955 /* Need to be before varinit_data[] */
1956 #if ENABLE_LOCALE_SUPPORT
1957 static void FAST_FUNC
1958 change_lc_all(const char *value)
1959 {
1960         if (value && *value != '\0')
1961                 setlocale(LC_ALL, value);
1962 }
1963 static void FAST_FUNC
1964 change_lc_ctype(const char *value)
1965 {
1966         if (value && *value != '\0')
1967                 setlocale(LC_CTYPE, value);
1968 }
1969 #endif
1970 #if ENABLE_ASH_MAIL
1971 static void chkmail(void);
1972 static void changemail(const char *var_value) FAST_FUNC;
1973 #else
1974 # define chkmail()  ((void)0)
1975 #endif
1976 static void changepath(const char *) FAST_FUNC;
1977 #if ENABLE_ASH_RANDOM_SUPPORT
1978 static void change_random(const char *) FAST_FUNC;
1979 #endif
1980
1981 static const struct {
1982         int flags;
1983         const char *var_text;
1984         void (*var_func)(const char *) FAST_FUNC;
1985 } varinit_data[] = {
1986         /*
1987          * Note: VEXPORT would not work correctly here for NOFORK applets:
1988          * some environment strings may be constant.
1989          */
1990         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1991 #if ENABLE_ASH_MAIL
1992         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1993         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1994 #endif
1995         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1996         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1997         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1998         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1999 #if ENABLE_ASH_GETOPTS
2000         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2001 #endif
2002 #if ENABLE_ASH_RANDOM_SUPPORT
2003         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2004 #endif
2005 #if ENABLE_LOCALE_SUPPORT
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2008 #endif
2009 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2010         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2011 #endif
2012 };
2013
2014 struct redirtab;
2015
2016 struct globals_var {
2017         struct shparam shellparam;      /* $@ current positional parameters */
2018         struct redirtab *redirlist;
2019         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2020         struct var *vartab[VTABSIZE];
2021         struct var varinit[ARRAY_SIZE(varinit_data)];
2022 };
2023 extern struct globals_var *const ash_ptr_to_globals_var;
2024 #define G_var (*ash_ptr_to_globals_var)
2025 #define shellparam    (G_var.shellparam   )
2026 //#define redirlist     (G_var.redirlist    )
2027 #define preverrout_fd (G_var.preverrout_fd)
2028 #define vartab        (G_var.vartab       )
2029 #define varinit       (G_var.varinit      )
2030 #define INIT_G_var() do { \
2031         unsigned i; \
2032         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2033         barrier(); \
2034         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2035                 varinit[i].flags    = varinit_data[i].flags; \
2036                 varinit[i].var_text = varinit_data[i].var_text; \
2037                 varinit[i].var_func = varinit_data[i].var_func; \
2038         } \
2039 } while (0)
2040
2041 #define vifs      varinit[0]
2042 #if ENABLE_ASH_MAIL
2043 # define vmail    (&vifs)[1]
2044 # define vmpath   (&vmail)[1]
2045 # define vpath    (&vmpath)[1]
2046 #else
2047 # define vpath    (&vifs)[1]
2048 #endif
2049 #define vps1      (&vpath)[1]
2050 #define vps2      (&vps1)[1]
2051 #define vps4      (&vps2)[1]
2052 #if ENABLE_ASH_GETOPTS
2053 # define voptind  (&vps4)[1]
2054 # if ENABLE_ASH_RANDOM_SUPPORT
2055 #  define vrandom (&voptind)[1]
2056 # endif
2057 #else
2058 # if ENABLE_ASH_RANDOM_SUPPORT
2059 #  define vrandom (&vps4)[1]
2060 # endif
2061 #endif
2062
2063 /*
2064  * The following macros access the values of the above variables.
2065  * They have to skip over the name.  They return the null string
2066  * for unset variables.
2067  */
2068 #define ifsval()        (vifs.var_text + 4)
2069 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2070 #if ENABLE_ASH_MAIL
2071 # define mailval()      (vmail.var_text + 5)
2072 # define mpathval()     (vmpath.var_text + 9)
2073 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2074 #endif
2075 #define pathval()       (vpath.var_text + 5)
2076 #define ps1val()        (vps1.var_text + 4)
2077 #define ps2val()        (vps2.var_text + 4)
2078 #define ps4val()        (vps4.var_text + 4)
2079 #if ENABLE_ASH_GETOPTS
2080 # define optindval()    (voptind.var_text + 7)
2081 #endif
2082
2083 #if ENABLE_ASH_GETOPTS
2084 static void FAST_FUNC
2085 getoptsreset(const char *value)
2086 {
2087         shellparam.optind = number(value) ?: 1;
2088         shellparam.optoff = -1;
2089 }
2090 #endif
2091
2092 /*
2093  * Compares two strings up to the first = or '\0'.  The first
2094  * string must be terminated by '='; the second may be terminated by
2095  * either '=' or '\0'.
2096  */
2097 static int
2098 varcmp(const char *p, const char *q)
2099 {
2100         int c, d;
2101
2102         while ((c = *p) == (d = *q)) {
2103                 if (c == '\0' || c == '=')
2104                         goto out;
2105                 p++;
2106                 q++;
2107         }
2108         if (c == '=')
2109                 c = '\0';
2110         if (d == '=')
2111                 d = '\0';
2112  out:
2113         return c - d;
2114 }
2115
2116 /*
2117  * Find the appropriate entry in the hash table from the name.
2118  */
2119 static struct var **
2120 hashvar(const char *p)
2121 {
2122         unsigned hashval;
2123
2124         hashval = ((unsigned char) *p) << 4;
2125         while (*p && *p != '=')
2126                 hashval += (unsigned char) *p++;
2127         return &vartab[hashval % VTABSIZE];
2128 }
2129
2130 static int
2131 vpcmp(const void *a, const void *b)
2132 {
2133         return varcmp(*(const char **)a, *(const char **)b);
2134 }
2135
2136 /*
2137  * This routine initializes the builtin variables.
2138  */
2139 static void
2140 initvar(void)
2141 {
2142         struct var *vp;
2143         struct var *end;
2144         struct var **vpp;
2145
2146         /*
2147          * PS1 depends on uid
2148          */
2149 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2150         vps1.var_text = "PS1=\\w \\$ ";
2151 #else
2152         if (!geteuid())
2153                 vps1.var_text = "PS1=# ";
2154 #endif
2155         vp = varinit;
2156         end = vp + ARRAY_SIZE(varinit);
2157         do {
2158                 vpp = hashvar(vp->var_text);
2159                 vp->next = *vpp;
2160                 *vpp = vp;
2161         } while (++vp < end);
2162 }
2163
2164 static struct var **
2165 findvar(struct var **vpp, const char *name)
2166 {
2167         for (; *vpp; vpp = &(*vpp)->next) {
2168                 if (varcmp((*vpp)->var_text, name) == 0) {
2169                         break;
2170                 }
2171         }
2172         return vpp;
2173 }
2174
2175 /*
2176  * Find the value of a variable.  Returns NULL if not set.
2177  */
2178 static const char* FAST_FUNC
2179 lookupvar(const char *name)
2180 {
2181         struct var *v;
2182
2183         v = *findvar(hashvar(name), name);
2184         if (v) {
2185 #if ENABLE_ASH_RANDOM_SUPPORT
2186         /*
2187          * Dynamic variables are implemented roughly the same way they are
2188          * in bash. Namely, they're "special" so long as they aren't unset.
2189          * As soon as they're unset, they're no longer dynamic, and dynamic
2190          * lookup will no longer happen at that point. -- PFM.
2191          */
2192                 if (v->flags & VDYNAMIC)
2193                         v->var_func(NULL);
2194 #endif
2195                 if (!(v->flags & VUNSET))
2196                         return var_end(v->var_text);
2197         }
2198         return NULL;
2199 }
2200
2201 #if ENABLE_UNICODE_SUPPORT
2202 static void
2203 reinit_unicode_for_ash(void)
2204 {
2205         /* Unicode support should be activated even if LANG is set
2206          * _during_ shell execution, not only if it was set when
2207          * shell was started. Therefore, re-check LANG every time:
2208          */
2209         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2210          || ENABLE_UNICODE_USING_LOCALE
2211         ) {
2212                 const char *s = lookupvar("LC_ALL");
2213                 if (!s) s = lookupvar("LC_CTYPE");
2214                 if (!s) s = lookupvar("LANG");
2215                 reinit_unicode(s);
2216         }
2217 }
2218 #else
2219 # define reinit_unicode_for_ash() ((void)0)
2220 #endif
2221
2222 /*
2223  * Search the environment of a builtin command.
2224  */
2225 static const char *
2226 bltinlookup(const char *name)
2227 {
2228         struct strlist *sp;
2229
2230         for (sp = cmdenviron; sp; sp = sp->next) {
2231                 if (varcmp(sp->text, name) == 0)
2232                         return var_end(sp->text);
2233         }
2234         return lookupvar(name);
2235 }
2236
2237 /*
2238  * Same as setvar except that the variable and value are passed in
2239  * the first argument as name=value.  Since the first argument will
2240  * be actually stored in the table, it should not be a string that
2241  * will go away.
2242  * Called with interrupts off.
2243  */
2244 static void
2245 setvareq(char *s, int flags)
2246 {
2247         struct var *vp, **vpp;
2248
2249         vpp = hashvar(s);
2250         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2251         vp = *findvar(vpp, s);
2252         if (vp) {
2253                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2254                         const char *n;
2255
2256                         if (flags & VNOSAVE)
2257                                 free(s);
2258                         n = vp->var_text;
2259                         exitstatus = 1;
2260                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2261                 }
2262
2263                 if (flags & VNOSET)
2264                         return;
2265
2266                 if (vp->var_func && !(flags & VNOFUNC))
2267                         vp->var_func(var_end(s));
2268
2269                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2270                         free((char*)vp->var_text);
2271
2272                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2273                         *vpp = vp->next;
2274                         free(vp);
2275  out_free:
2276                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2277                                 free(s);
2278                         return;
2279                 }
2280
2281                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2282         } else {
2283                 /* variable s is not found */
2284                 if (flags & VNOSET)
2285                         return;
2286                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2287                         goto out_free;
2288                 vp = ckzalloc(sizeof(*vp));
2289                 vp->next = *vpp;
2290                 /*vp->func = NULL; - ckzalloc did it */
2291                 *vpp = vp;
2292         }
2293         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2294                 s = ckstrdup(s);
2295         vp->var_text = s;
2296         vp->flags = flags;
2297 }
2298
2299 /*
2300  * Set the value of a variable.  The flags argument is ored with the
2301  * flags of the variable.  If val is NULL, the variable is unset.
2302  */
2303 static void
2304 setvar(const char *name, const char *val, int flags)
2305 {
2306         const char *q;
2307         char *p;
2308         char *nameeq;
2309         size_t namelen;
2310         size_t vallen;
2311
2312         q = endofname(name);
2313         p = strchrnul(q, '=');
2314         namelen = p - name;
2315         if (!namelen || p != q)
2316                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2317         vallen = 0;
2318         if (val == NULL) {
2319                 flags |= VUNSET;
2320         } else {
2321                 vallen = strlen(val);
2322         }
2323
2324         INT_OFF;
2325         nameeq = ckmalloc(namelen + vallen + 2);
2326         p = mempcpy(nameeq, name, namelen);
2327         if (val) {
2328                 *p++ = '=';
2329                 p = mempcpy(p, val, vallen);
2330         }
2331         *p = '\0';
2332         setvareq(nameeq, flags | VNOSAVE);
2333         INT_ON;
2334 }
2335
2336 static void FAST_FUNC
2337 setvar0(const char *name, const char *val)
2338 {
2339         setvar(name, val, 0);
2340 }
2341
2342 /*
2343  * Unset the specified variable.
2344  */
2345 static void
2346 unsetvar(const char *s)
2347 {
2348         setvar0(s, NULL);
2349 }
2350
2351 /*
2352  * Process a linked list of variable assignments.
2353  */
2354 static void
2355 listsetvar(struct strlist *list_set_var, int flags)
2356 {
2357         struct strlist *lp = list_set_var;
2358
2359         if (!lp)
2360                 return;
2361         INT_OFF;
2362         do {
2363                 setvareq(lp->text, flags);
2364                 lp = lp->next;
2365         } while (lp);
2366         INT_ON;
2367 }
2368
2369 /*
2370  * Generate a list of variables satisfying the given conditions.
2371  */
2372 static char **
2373 listvars(int on, int off, char ***end)
2374 {
2375         struct var **vpp;
2376         struct var *vp;
2377         char **ep;
2378         int mask;
2379
2380         STARTSTACKSTR(ep);
2381         vpp = vartab;
2382         mask = on | off;
2383         do {
2384                 for (vp = *vpp; vp; vp = vp->next) {
2385                         if ((vp->flags & mask) == on) {
2386                                 if (ep == stackstrend())
2387                                         ep = growstackstr();
2388                                 *ep++ = (char*)vp->var_text;
2389                         }
2390                 }
2391         } while (++vpp < vartab + VTABSIZE);
2392         if (ep == stackstrend())
2393                 ep = growstackstr();
2394         if (end)
2395                 *end = ep;
2396         *ep++ = NULL;
2397         return grabstackstr(ep);
2398 }
2399
2400
2401 /* ============ Path search helper
2402  *
2403  * The variable path (passed by reference) should be set to the start
2404  * of the path before the first call; path_advance will update
2405  * this value as it proceeds.  Successive calls to path_advance will return
2406  * the possible path expansions in sequence.  If an option (indicated by
2407  * a percent sign) appears in the path entry then the global variable
2408  * pathopt will be set to point to it; otherwise pathopt will be set to
2409  * NULL.
2410  */
2411 static const char *pathopt;     /* set by path_advance */
2412
2413 static char *
2414 path_advance(const char **path, const char *name)
2415 {
2416         const char *p;
2417         char *q;
2418         const char *start;
2419         size_t len;
2420
2421         if (*path == NULL)
2422                 return NULL;
2423         start = *path;
2424         for (p = start; *p && *p != ':' && *p != '%'; p++)
2425                 continue;
2426         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2427         while (stackblocksize() < len)
2428                 growstackblock();
2429         q = stackblock();
2430         if (p != start) {
2431                 q = mempcpy(q, start, p - start);
2432                 *q++ = '/';
2433         }
2434         strcpy(q, name);
2435         pathopt = NULL;
2436         if (*p == '%') {
2437                 pathopt = ++p;
2438                 while (*p && *p != ':')
2439                         p++;
2440         }
2441         if (*p == ':')
2442                 *path = p + 1;
2443         else
2444                 *path = NULL;
2445         return stalloc(len);
2446 }
2447
2448
2449 /* ============ Prompt */
2450
2451 static smallint doprompt;                   /* if set, prompt the user */
2452 static smallint needprompt;                 /* true if interactive and at start of line */
2453
2454 #if ENABLE_FEATURE_EDITING
2455 static line_input_t *line_input_state;
2456 static const char *cmdedit_prompt;
2457 static void
2458 putprompt(const char *s)
2459 {
2460         if (ENABLE_ASH_EXPAND_PRMT) {
2461                 free((char*)cmdedit_prompt);
2462                 cmdedit_prompt = ckstrdup(s);
2463                 return;
2464         }
2465         cmdedit_prompt = s;
2466 }
2467 #else
2468 static void
2469 putprompt(const char *s)
2470 {
2471         out2str(s);
2472 }
2473 #endif
2474
2475 /* expandstr() needs parsing machinery, so it is far away ahead... */
2476 static const char *expandstr(const char *ps);
2477
2478 static void
2479 setprompt_if(smallint do_set, int whichprompt)
2480 {
2481         const char *prompt;
2482         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2483
2484         if (!do_set)
2485                 return;
2486
2487         needprompt = 0;
2488
2489         switch (whichprompt) {
2490         case 1:
2491                 prompt = ps1val();
2492                 break;
2493         case 2:
2494                 prompt = ps2val();
2495                 break;
2496         default:                        /* 0 */
2497                 prompt = nullstr;
2498         }
2499 #if ENABLE_ASH_EXPAND_PRMT
2500         pushstackmark(&smark, stackblocksize());
2501         putprompt(expandstr(prompt));
2502         popstackmark(&smark);
2503 #else
2504         putprompt(prompt);
2505 #endif
2506 }
2507
2508
2509 /* ============ The cd and pwd commands */
2510
2511 #define CD_PHYSICAL 1
2512 #define CD_PRINT 2
2513
2514 static int
2515 cdopt(void)
2516 {
2517         int flags = 0;
2518         int i, j;
2519
2520         j = 'L';
2521         while ((i = nextopt("LP")) != '\0') {
2522                 if (i != j) {
2523                         flags ^= CD_PHYSICAL;
2524                         j = i;
2525                 }
2526         }
2527
2528         return flags;
2529 }
2530
2531 /*
2532  * Update curdir (the name of the current directory) in response to a
2533  * cd command.
2534  */
2535 static const char *
2536 updatepwd(const char *dir)
2537 {
2538         char *new;
2539         char *p;
2540         char *cdcomppath;
2541         const char *lim;
2542
2543         cdcomppath = sstrdup(dir);
2544         STARTSTACKSTR(new);
2545         if (*dir != '/') {
2546                 if (curdir == nullstr)
2547                         return 0;
2548                 new = stack_putstr(curdir, new);
2549         }
2550         new = makestrspace(strlen(dir) + 2, new);
2551         lim = (char *)stackblock() + 1;
2552         if (*dir != '/') {
2553                 if (new[-1] != '/')
2554                         USTPUTC('/', new);
2555                 if (new > lim && *lim == '/')
2556                         lim++;
2557         } else {
2558                 USTPUTC('/', new);
2559                 cdcomppath++;
2560                 if (dir[1] == '/' && dir[2] != '/') {
2561                         USTPUTC('/', new);
2562                         cdcomppath++;
2563                         lim++;
2564                 }
2565         }
2566         p = strtok(cdcomppath, "/");
2567         while (p) {
2568                 switch (*p) {
2569                 case '.':
2570                         if (p[1] == '.' && p[2] == '\0') {
2571                                 while (new > lim) {
2572                                         STUNPUTC(new);
2573                                         if (new[-1] == '/')
2574                                                 break;
2575                                 }
2576                                 break;
2577                         }
2578                         if (p[1] == '\0')
2579                                 break;
2580                         /* fall through */
2581                 default:
2582                         new = stack_putstr(p, new);
2583                         USTPUTC('/', new);
2584                 }
2585                 p = strtok(NULL, "/");
2586         }
2587         if (new > lim)
2588                 STUNPUTC(new);
2589         *new = 0;
2590         return stackblock();
2591 }
2592
2593 /*
2594  * Find out what the current directory is. If we already know the current
2595  * directory, this routine returns immediately.
2596  */
2597 static char *
2598 getpwd(void)
2599 {
2600         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2601         return dir ? dir : nullstr;
2602 }
2603
2604 static void
2605 setpwd(const char *val, int setold)
2606 {
2607         char *oldcur, *dir;
2608
2609         oldcur = dir = curdir;
2610
2611         if (setold) {
2612                 setvar("OLDPWD", oldcur, VEXPORT);
2613         }
2614         INT_OFF;
2615         if (physdir != nullstr) {
2616                 if (physdir != oldcur)
2617                         free(physdir);
2618                 physdir = nullstr;
2619         }
2620         if (oldcur == val || !val) {
2621                 char *s = getpwd();
2622                 physdir = s;
2623                 if (!val)
2624                         dir = s;
2625         } else
2626                 dir = ckstrdup(val);
2627         if (oldcur != dir && oldcur != nullstr) {
2628                 free(oldcur);
2629         }
2630         curdir = dir;
2631         INT_ON;
2632         setvar("PWD", dir, VEXPORT);
2633 }
2634
2635 static void hashcd(void);
2636
2637 /*
2638  * Actually do the chdir.  We also call hashcd to let other routines
2639  * know that the current directory has changed.
2640  */
2641 static int
2642 docd(const char *dest, int flags)
2643 {
2644         const char *dir = NULL;
2645         int err;
2646
2647         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2648
2649         INT_OFF;
2650         if (!(flags & CD_PHYSICAL)) {
2651                 dir = updatepwd(dest);
2652                 if (dir)
2653                         dest = dir;
2654         }
2655         err = chdir(dest);
2656         if (err)
2657                 goto out;
2658         setpwd(dir, 1);
2659         hashcd();
2660  out:
2661         INT_ON;
2662         return err;
2663 }
2664
2665 static int FAST_FUNC
2666 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2667 {
2668         const char *dest;
2669         const char *path;
2670         const char *p;
2671         char c;
2672         struct stat statb;
2673         int flags;
2674
2675         flags = cdopt();
2676         dest = *argptr;
2677         if (!dest)
2678                 dest = bltinlookup("HOME");
2679         else if (LONE_DASH(dest)) {
2680                 dest = bltinlookup("OLDPWD");
2681                 flags |= CD_PRINT;
2682         }
2683         if (!dest)
2684                 dest = nullstr;
2685         if (*dest == '/')
2686                 goto step6;
2687         if (*dest == '.') {
2688                 c = dest[1];
2689  dotdot:
2690                 switch (c) {
2691                 case '\0':
2692                 case '/':
2693                         goto step6;
2694                 case '.':
2695                         c = dest[2];
2696                         if (c != '.')
2697                                 goto dotdot;
2698                 }
2699         }
2700         if (!*dest)
2701                 dest = ".";
2702         path = bltinlookup("CDPATH");
2703         while (path) {
2704                 c = *path;
2705                 p = path_advance(&path, dest);
2706                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2707                         if (c && c != ':')
2708                                 flags |= CD_PRINT;
2709  docd:
2710                         if (!docd(p, flags))
2711                                 goto out;
2712                         goto err;
2713                 }
2714         }
2715
2716  step6:
2717         p = dest;
2718         goto docd;
2719
2720  err:
2721         ash_msg_and_raise_error("can't cd to %s", dest);
2722         /* NOTREACHED */
2723  out:
2724         if (flags & CD_PRINT)
2725                 out1fmt("%s\n", curdir);
2726         return 0;
2727 }
2728
2729 static int FAST_FUNC
2730 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2731 {
2732         int flags;
2733         const char *dir = curdir;
2734
2735         flags = cdopt();
2736         if (flags) {
2737                 if (physdir == nullstr)
2738                         setpwd(dir, 0);
2739                 dir = physdir;
2740         }
2741         out1fmt("%s\n", dir);
2742         return 0;
2743 }
2744
2745
2746 /* ============ ... */
2747
2748
2749 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2750
2751 /* Syntax classes */
2752 #define CWORD     0             /* character is nothing special */
2753 #define CNL       1             /* newline character */
2754 #define CBACK     2             /* a backslash character */
2755 #define CSQUOTE   3             /* single quote */
2756 #define CDQUOTE   4             /* double quote */
2757 #define CENDQUOTE 5             /* a terminating quote */
2758 #define CBQUOTE   6             /* backwards single quote */
2759 #define CVAR      7             /* a dollar sign */
2760 #define CENDVAR   8             /* a '}' character */
2761 #define CLP       9             /* a left paren in arithmetic */
2762 #define CRP      10             /* a right paren in arithmetic */
2763 #define CENDFILE 11             /* end of file */
2764 #define CCTL     12             /* like CWORD, except it must be escaped */
2765 #define CSPCL    13             /* these terminate a word */
2766 #define CIGN     14             /* character should be ignored */
2767
2768 #define PEOF     256
2769 #if ENABLE_ASH_ALIAS
2770 # define PEOA    257
2771 #endif
2772
2773 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2774
2775 #if ENABLE_FEATURE_SH_MATH
2776 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2777 #else
2778 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2779 #endif
2780 static const uint16_t S_I_T[] ALIGN2 = {
2781 #if ENABLE_ASH_ALIAS
2782         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2783 #endif
2784         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2785         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2786         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2787         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2788         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2789         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2790         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2791         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2792         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2793         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2794         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2795 #if !USE_SIT_FUNCTION
2796         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2797         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2798         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2799 #endif
2800 #undef SIT_ITEM
2801 };
2802 /* Constants below must match table above */
2803 enum {
2804 #if ENABLE_ASH_ALIAS
2805         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2806 #endif
2807         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2808         CNL_CNL_CNL_CNL                    , /*  2 */
2809         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2810         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2811         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2812         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2813         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2814         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2815         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2816         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2817         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2818         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2819         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2820         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2821 };
2822
2823 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2824  * caller must ensure proper cast on it if c is *char_ptr!
2825  */
2826 /* Values for syntax param */
2827 #define BASESYNTAX 0    /* not in quotes */
2828 #define DQSYNTAX   1    /* in double quotes */
2829 #define SQSYNTAX   2    /* in single quotes */
2830 #define ARISYNTAX  3    /* in arithmetic */
2831 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2832
2833 #if USE_SIT_FUNCTION
2834
2835 static int
2836 SIT(int c, int syntax)
2837 {
2838         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2839         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2840         /*
2841          * This causes '/' to be prepended with CTLESC in dquoted string,
2842          * making "./file"* treated incorrectly because we feed
2843          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2844          * The "homegrown" glob implementation is okay with that,
2845          * but glibc one isn't. With '/' always treated as CWORD,
2846          * both work fine.
2847          */
2848 # if ENABLE_ASH_ALIAS
2849         static const uint8_t syntax_index_table[] ALIGN1 = {
2850                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2851                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2852                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2853                 11, 3                           /* "}~" */
2854         };
2855 # else
2856         static const uint8_t syntax_index_table[] ALIGN1 = {
2857                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2858                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2859                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2860                 10, 2                           /* "}~" */
2861         };
2862 # endif
2863         const char *s;
2864         int indx;
2865
2866         if (c == PEOF)
2867                 return CENDFILE;
2868 # if ENABLE_ASH_ALIAS
2869         if (c == PEOA)
2870                 indx = 0;
2871         else
2872 # endif
2873         {
2874                 /* Cast is purely for paranoia here,
2875                  * just in case someone passed signed char to us */
2876                 if ((unsigned char)c >= CTL_FIRST
2877                  && (unsigned char)c <= CTL_LAST
2878                 ) {
2879                         return CCTL;
2880                 }
2881                 s = strchrnul(spec_symbls, c);
2882                 if (*s == '\0')
2883                         return CWORD;
2884                 indx = syntax_index_table[s - spec_symbls];
2885         }
2886         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2887 }
2888
2889 #else   /* !USE_SIT_FUNCTION */
2890
2891 static const uint8_t syntax_index_table[] ALIGN1 = {
2892         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2893         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2894         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2895         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2896         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2897         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2898         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2899         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2900         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2901         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2902         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2903         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2904         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2912         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2913         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2914         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2915         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2916         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2917         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2918         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2919         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2920         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2921         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2922         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2926         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2927         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2928         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2930         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2932         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2933         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2934         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2935         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2936         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2938         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2939         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2940 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2941         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2943         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2953         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2954         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2955         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2956         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2957         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2958         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2986         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2987         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2988         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2991         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3019         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3020         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3021         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3022         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3023         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3024         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3025         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3026         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3027         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3028         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3029         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3030         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3031         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3150         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3151 # if ENABLE_ASH_ALIAS
3152         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3153 # endif
3154 };
3155
3156 #if 1
3157 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3158 #else /* debug version, caught one signed char bug */
3159 # define SIT(c, syntax) \
3160         ({ \
3161                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3162                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3163                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3164                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3165                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3166         })
3167 #endif
3168
3169 #endif  /* !USE_SIT_FUNCTION */
3170
3171
3172 /* ============ Alias handling */
3173
3174 #if ENABLE_ASH_ALIAS
3175
3176 #define ALIASINUSE 1
3177 #define ALIASDEAD  2
3178
3179 struct alias {
3180         struct alias *next;
3181         char *name;
3182         char *val;
3183         int flag;
3184 };
3185
3186
3187 static struct alias **atab; // [ATABSIZE];
3188 #define INIT_G_alias() do { \
3189         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3190 } while (0)
3191
3192
3193 static struct alias **
3194 __lookupalias(const char *name)
3195 {
3196         unsigned int hashval;
3197         struct alias **app;
3198         const char *p;
3199         unsigned int ch;
3200
3201         p = name;
3202
3203         ch = (unsigned char)*p;
3204         hashval = ch << 4;
3205         while (ch) {
3206                 hashval += ch;
3207                 ch = (unsigned char)*++p;
3208         }
3209         app = &atab[hashval % ATABSIZE];
3210
3211         for (; *app; app = &(*app)->next) {
3212                 if (strcmp(name, (*app)->name) == 0) {
3213                         break;
3214                 }
3215         }
3216
3217         return app;
3218 }
3219
3220 static struct alias *
3221 lookupalias(const char *name, int check)
3222 {
3223         struct alias *ap = *__lookupalias(name);
3224
3225         if (check && ap && (ap->flag & ALIASINUSE))
3226                 return NULL;
3227         return ap;
3228 }
3229
3230 static struct alias *
3231 freealias(struct alias *ap)
3232 {
3233         struct alias *next;
3234
3235         if (ap->flag & ALIASINUSE) {
3236                 ap->flag |= ALIASDEAD;
3237                 return ap;
3238         }
3239
3240         next = ap->next;
3241         free(ap->name);
3242         free(ap->val);
3243         free(ap);
3244         return next;
3245 }
3246
3247 static void
3248 setalias(const char *name, const char *val)
3249 {
3250         struct alias *ap, **app;
3251
3252         app = __lookupalias(name);
3253         ap = *app;
3254         INT_OFF;
3255         if (ap) {
3256                 if (!(ap->flag & ALIASINUSE)) {
3257                         free(ap->val);
3258                 }
3259                 ap->val = ckstrdup(val);
3260                 ap->flag &= ~ALIASDEAD;
3261         } else {
3262                 /* not found */
3263                 ap = ckzalloc(sizeof(struct alias));
3264                 ap->name = ckstrdup(name);
3265                 ap->val = ckstrdup(val);
3266                 /*ap->flag = 0; - ckzalloc did it */
3267                 /*ap->next = NULL;*/
3268                 *app = ap;
3269         }
3270         INT_ON;
3271 }
3272
3273 static int
3274 unalias(const char *name)
3275 {
3276         struct alias **app;
3277
3278         app = __lookupalias(name);
3279
3280         if (*app) {
3281                 INT_OFF;
3282                 *app = freealias(*app);
3283                 INT_ON;
3284                 return 0;
3285         }
3286
3287         return 1;
3288 }
3289
3290 static void
3291 rmaliases(void)
3292 {
3293         struct alias *ap, **app;
3294         int i;
3295
3296         INT_OFF;
3297         for (i = 0; i < ATABSIZE; i++) {
3298                 app = &atab[i];
3299                 for (ap = *app; ap; ap = *app) {
3300                         *app = freealias(*app);
3301                         if (ap == *app) {
3302                                 app = &ap->next;
3303                         }
3304                 }
3305         }
3306         INT_ON;
3307 }
3308
3309 static void
3310 printalias(const struct alias *ap)
3311 {
3312         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3313 }
3314
3315 /*
3316  * TODO - sort output
3317  */
3318 static int FAST_FUNC
3319 aliascmd(int argc UNUSED_PARAM, char **argv)
3320 {
3321         char *n, *v;
3322         int ret = 0;
3323         struct alias *ap;
3324
3325         if (!argv[1]) {
3326                 int i;
3327
3328                 for (i = 0; i < ATABSIZE; i++) {
3329                         for (ap = atab[i]; ap; ap = ap->next) {
3330                                 printalias(ap);
3331                         }
3332                 }
3333                 return 0;
3334         }
3335         while ((n = *++argv) != NULL) {
3336                 v = strchr(n+1, '=');
3337                 if (v == NULL) { /* n+1: funny ksh stuff */
3338                         ap = *__lookupalias(n);
3339                         if (ap == NULL) {
3340                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3341                                 ret = 1;
3342                         } else
3343                                 printalias(ap);
3344                 } else {
3345                         *v++ = '\0';
3346                         setalias(n, v);
3347                 }
3348         }
3349
3350         return ret;
3351 }
3352
3353 static int FAST_FUNC
3354 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3355 {
3356         int i;
3357
3358         while (nextopt("a") != '\0') {
3359                 rmaliases();
3360                 return 0;
3361         }
3362         for (i = 0; *argptr; argptr++) {
3363                 if (unalias(*argptr)) {
3364                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3365                         i = 1;
3366                 }
3367         }
3368
3369         return i;
3370 }
3371
3372 #endif /* ASH_ALIAS */
3373
3374
3375 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3376 #define FORK_FG    0
3377 #define FORK_BG    1
3378 #define FORK_NOJOB 2
3379
3380 /* mode flags for showjob(s) */
3381 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3382 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3383 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3384 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3385
3386 /*
3387  * A job structure contains information about a job.  A job is either a
3388  * single process or a set of processes contained in a pipeline.  In the
3389  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3390  * array of pids.
3391  */
3392 struct procstat {
3393         pid_t   ps_pid;         /* process id */
3394         int     ps_status;      /* last process status from wait() */
3395         char    *ps_cmd;        /* text of command being run */
3396 };
3397
3398 struct job {
3399         struct procstat ps0;    /* status of process */
3400         struct procstat *ps;    /* status or processes when more than one */
3401 #if JOBS
3402         int stopstatus;         /* status of a stopped job */
3403 #endif
3404         unsigned nprocs;        /* number of processes */
3405
3406 #define JOBRUNNING      0       /* at least one proc running */
3407 #define JOBSTOPPED      1       /* all procs are stopped */
3408 #define JOBDONE         2       /* all procs are completed */
3409         unsigned
3410                 state: 8,
3411 #if JOBS
3412                 sigint: 1,      /* job was killed by SIGINT */
3413                 jobctl: 1,      /* job running under job control */
3414 #endif
3415                 waited: 1,      /* true if this entry has been waited for */
3416                 used: 1,        /* true if this entry is in used */
3417                 changed: 1;     /* true if status has changed */
3418         struct job *prev_job;   /* previous job */
3419 };
3420
3421 static struct job *makejob(/*union node *,*/ int);
3422 static int forkshell(struct job *, union node *, int);
3423 static int waitforjob(struct job *);
3424
3425 #if !JOBS
3426 enum { doing_jobctl = 0 };
3427 #define setjobctl(on) do {} while (0)
3428 #else
3429 static smallint doing_jobctl; //references:8
3430 static void setjobctl(int);
3431 #endif
3432
3433 /*
3434  * Ignore a signal.
3435  */
3436 static void
3437 ignoresig(int signo)
3438 {
3439         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3440         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3441                 /* No, need to do it */
3442                 signal(signo, SIG_IGN);
3443         }
3444         sigmode[signo - 1] = S_HARD_IGN;
3445 }
3446
3447 /*
3448  * Only one usage site - in setsignal()
3449  */
3450 static void
3451 signal_handler(int signo)
3452 {
3453         if (signo == SIGCHLD) {
3454                 got_sigchld = 1;
3455                 if (!trap[SIGCHLD])
3456                         return;
3457         }
3458
3459         gotsig[signo - 1] = 1;
3460         pending_sig = signo;
3461
3462         if (signo == SIGINT && !trap[SIGINT]) {
3463                 if (!suppress_int) {
3464                         pending_sig = 0;
3465                         raise_interrupt(); /* does not return */
3466                 }
3467                 pending_int = 1;
3468         }
3469 }
3470
3471 /*
3472  * Set the signal handler for the specified signal.  The routine figures
3473  * out what it should be set to.
3474  */
3475 static void
3476 setsignal(int signo)
3477 {
3478         char *t;
3479         char cur_act, new_act;
3480         struct sigaction act;
3481
3482         t = trap[signo];
3483         new_act = S_DFL;
3484         if (t != NULL) { /* trap for this sig is set */
3485                 new_act = S_CATCH;
3486                 if (t[0] == '\0') /* trap is "": ignore this sig */
3487                         new_act = S_IGN;
3488         }
3489
3490         if (rootshell && new_act == S_DFL) {
3491                 switch (signo) {
3492                 case SIGINT:
3493                         if (iflag || minusc || sflag == 0)
3494                                 new_act = S_CATCH;
3495                         break;
3496                 case SIGQUIT:
3497 #if DEBUG
3498                         if (debug)
3499                                 break;
3500 #endif
3501                         /* man bash:
3502                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3503                          * commands run by bash have signal handlers
3504                          * set to the values inherited by the shell
3505                          * from its parent". */
3506                         new_act = S_IGN;
3507                         break;
3508                 case SIGTERM:
3509                         if (iflag)
3510                                 new_act = S_IGN;
3511                         break;
3512 #if JOBS
3513                 case SIGTSTP:
3514                 case SIGTTOU:
3515                         if (mflag)
3516                                 new_act = S_IGN;
3517                         break;
3518 #endif
3519                 }
3520         }
3521 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3522 //whereas we have to restore it to what shell got on entry
3523 //from the parent. See comment above
3524
3525         if (signo == SIGCHLD)
3526                 new_act = S_CATCH;
3527
3528         t = &sigmode[signo - 1];
3529         cur_act = *t;
3530         if (cur_act == 0) {
3531                 /* current setting is not yet known */
3532                 if (sigaction(signo, NULL, &act)) {
3533                         /* pretend it worked; maybe we should give a warning,
3534                          * but other shells don't. We don't alter sigmode,
3535                          * so we retry every time.
3536                          * btw, in Linux it never fails. --vda */
3537                         return;
3538                 }
3539                 if (act.sa_handler == SIG_IGN) {
3540                         cur_act = S_HARD_IGN;
3541                         if (mflag
3542                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3543                         ) {
3544                                 cur_act = S_IGN;   /* don't hard ignore these */
3545                         }
3546                 }
3547         }
3548         if (cur_act == S_HARD_IGN || cur_act == new_act)
3549                 return;
3550
3551         act.sa_handler = SIG_DFL;
3552         switch (new_act) {
3553         case S_CATCH:
3554                 act.sa_handler = signal_handler;
3555                 break;
3556         case S_IGN:
3557                 act.sa_handler = SIG_IGN;
3558                 break;
3559         }
3560
3561         /* flags and mask matter only if !DFL and !IGN, but we do it
3562          * for all cases for more deterministic behavior:
3563          */
3564         act.sa_flags = 0;
3565         sigfillset(&act.sa_mask);
3566
3567         sigaction_set(signo, &act);
3568
3569         *t = new_act;
3570 }
3571
3572 /* mode flags for set_curjob */
3573 #define CUR_DELETE 2
3574 #define CUR_RUNNING 1
3575 #define CUR_STOPPED 0
3576
3577 #if JOBS
3578 /* pgrp of shell on invocation */
3579 static int initialpgrp; //references:2
3580 static int ttyfd = -1; //5
3581 #endif
3582 /* array of jobs */
3583 static struct job *jobtab; //5
3584 /* size of array */
3585 static unsigned njobs; //4
3586 /* current job */
3587 static struct job *curjob; //lots
3588 /* number of presumed living untracked jobs */
3589 static int jobless; //4
3590
3591 #if 0
3592 /* Bash has a feature: it restores termios after a successful wait for
3593  * a foreground job which had at least one stopped or sigkilled member.
3594  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3595  * properly restoring tty state. Should we do this too?
3596  * A reproducer: ^Z an interactive python:
3597  *
3598  * # python
3599  * Python 2.7.12 (...)
3600  * >>> ^Z
3601  *      { python leaves tty in -icanon -echo state. We do survive that... }
3602  *  [1]+  Stopped                    python
3603  *      { ...however, next program (python #2) does not survive it well: }
3604  * # python
3605  * Python 2.7.12 (...)
3606  * >>> Traceback (most recent call last):
3607  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3608  *   File "<stdin>", line 1, in <module>
3609  * NameError: name 'qwerty' is not defined
3610  *
3611  * The implementation below is modeled on bash code and seems to work.
3612  * However, I'm not sure we should do this. For one: what if I'd fg
3613  * the stopped python instead? It'll be confused by "restored" tty state.
3614  */
3615 static struct termios shell_tty_info;
3616 static void
3617 get_tty_state(void)
3618 {
3619         if (rootshell && ttyfd >= 0)
3620                 tcgetattr(ttyfd, &shell_tty_info);
3621 }
3622 static void
3623 set_tty_state(void)
3624 {
3625         /* if (rootshell) - caller ensures this */
3626         if (ttyfd >= 0)
3627                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3628 }
3629 static int
3630 job_signal_status(struct job *jp)
3631 {
3632         int status;
3633         unsigned i;
3634         struct procstat *ps = jp->ps;
3635         for (i = 0; i < jp->nprocs; i++) {
3636                 status = ps[i].ps_status;
3637                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3638                         return status;
3639         }
3640         return 0;
3641 }
3642 static void
3643 restore_tty_if_stopped_or_signaled(struct job *jp)
3644 {
3645 //TODO: check what happens if we come from waitforjob() in expbackq()
3646         if (rootshell) {
3647                 int s = job_signal_status(jp);
3648                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3649                         set_tty_state();
3650         }
3651 }
3652 #else
3653 # define get_tty_state() ((void)0)
3654 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3655 #endif
3656
3657 static void
3658 set_curjob(struct job *jp, unsigned mode)
3659 {
3660         struct job *jp1;
3661         struct job **jpp, **curp;
3662
3663         /* first remove from list */
3664         jpp = curp = &curjob;
3665         while (1) {
3666                 jp1 = *jpp;
3667                 if (jp1 == jp)
3668                         break;
3669                 jpp = &jp1->prev_job;
3670         }
3671         *jpp = jp1->prev_job;
3672
3673         /* Then re-insert in correct position */
3674         jpp = curp;
3675         switch (mode) {
3676         default:
3677 #if DEBUG
3678                 abort();
3679 #endif
3680         case CUR_DELETE:
3681                 /* job being deleted */
3682                 break;
3683         case CUR_RUNNING:
3684                 /* newly created job or backgrounded job,
3685                  * put after all stopped jobs.
3686                  */
3687                 while (1) {
3688                         jp1 = *jpp;
3689 #if JOBS
3690                         if (!jp1 || jp1->state != JOBSTOPPED)
3691 #endif
3692                                 break;
3693                         jpp = &jp1->prev_job;
3694                 }
3695                 /* FALLTHROUGH */
3696 #if JOBS
3697         case CUR_STOPPED:
3698 #endif
3699                 /* newly stopped job - becomes curjob */
3700                 jp->prev_job = *jpp;
3701                 *jpp = jp;
3702                 break;
3703         }
3704 }
3705
3706 #if JOBS || DEBUG
3707 static int
3708 jobno(const struct job *jp)
3709 {
3710         return jp - jobtab + 1;
3711 }
3712 #endif
3713
3714 /*
3715  * Convert a job name to a job structure.
3716  */
3717 #if !JOBS
3718 #define getjob(name, getctl) getjob(name)
3719 #endif
3720 static struct job *
3721 getjob(const char *name, int getctl)
3722 {
3723         struct job *jp;
3724         struct job *found;
3725         const char *err_msg = "%s: no such job";
3726         unsigned num;
3727         int c;
3728         const char *p;
3729         char *(*match)(const char *, const char *);
3730
3731         jp = curjob;
3732         p = name;
3733         if (!p)
3734                 goto currentjob;
3735
3736         if (*p != '%')
3737                 goto err;
3738
3739         c = *++p;
3740         if (!c)
3741                 goto currentjob;
3742
3743         if (!p[1]) {
3744                 if (c == '+' || c == '%') {
3745  currentjob:
3746                         err_msg = "No current job";
3747                         goto check;
3748                 }
3749                 if (c == '-') {
3750                         if (jp)
3751                                 jp = jp->prev_job;
3752                         err_msg = "No previous job";
3753  check:
3754                         if (!jp)
3755                                 goto err;
3756                         goto gotit;
3757                 }
3758         }
3759
3760         if (is_number(p)) {
3761                 num = atoi(p);
3762                 if (num > 0 && num <= njobs) {
3763                         jp = jobtab + num - 1;
3764                         if (jp->used)
3765                                 goto gotit;
3766                         goto err;
3767                 }
3768         }
3769
3770         match = prefix;
3771         if (*p == '?') {
3772                 match = strstr;
3773                 p++;
3774         }
3775
3776         found = NULL;
3777         while (jp) {
3778                 if (match(jp->ps[0].ps_cmd, p)) {
3779                         if (found)
3780                                 goto err;
3781                         found = jp;
3782                         err_msg = "%s: ambiguous";
3783                 }
3784                 jp = jp->prev_job;
3785         }
3786         if (!found)
3787                 goto err;
3788         jp = found;
3789
3790  gotit:
3791 #if JOBS
3792         err_msg = "job %s not created under job control";
3793         if (getctl && jp->jobctl == 0)
3794                 goto err;
3795 #endif
3796         return jp;
3797  err:
3798         ash_msg_and_raise_error(err_msg, name);
3799 }
3800
3801 /*
3802  * Mark a job structure as unused.
3803  */
3804 static void
3805 freejob(struct job *jp)
3806 {
3807         struct procstat *ps;
3808         int i;
3809
3810         INT_OFF;
3811         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3812                 if (ps->ps_cmd != nullstr)
3813                         free(ps->ps_cmd);
3814         }
3815         if (jp->ps != &jp->ps0)
3816                 free(jp->ps);
3817         jp->used = 0;
3818         set_curjob(jp, CUR_DELETE);
3819         INT_ON;
3820 }
3821
3822 #if JOBS
3823 static void
3824 xtcsetpgrp(int fd, pid_t pgrp)
3825 {
3826         if (tcsetpgrp(fd, pgrp))
3827                 ash_msg_and_raise_error("can't set tty process group (%m)");
3828 }
3829
3830 /*
3831  * Turn job control on and off.
3832  *
3833  * Note:  This code assumes that the third arg to ioctl is a character
3834  * pointer, which is true on Berkeley systems but not System V.  Since
3835  * System V doesn't have job control yet, this isn't a problem now.
3836  *
3837  * Called with interrupts off.
3838  */
3839 static void
3840 setjobctl(int on)
3841 {
3842         int fd;
3843         int pgrp;
3844
3845         if (on == doing_jobctl || rootshell == 0)
3846                 return;
3847         if (on) {
3848                 int ofd;
3849                 ofd = fd = open(_PATH_TTY, O_RDWR);
3850                 if (fd < 0) {
3851         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3852          * That sometimes helps to acquire controlling tty.
3853          * Obviously, a workaround for bugs when someone
3854          * failed to provide a controlling tty to bash! :) */
3855                         fd = 2;
3856                         while (!isatty(fd))
3857                                 if (--fd < 0)
3858                                         goto out;
3859                 }
3860                 /* fd is a tty at this point */
3861                 fd = fcntl(fd, F_DUPFD, 10);
3862                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3863                         close(ofd);
3864                 if (fd < 0)
3865                         goto out; /* F_DUPFD failed */
3866                 close_on_exec_on(fd);
3867                 while (1) { /* while we are in the background */
3868                         pgrp = tcgetpgrp(fd);
3869                         if (pgrp < 0) {
3870  out:
3871                                 ash_msg("can't access tty; job control turned off");
3872                                 mflag = on = 0;
3873                                 goto close;
3874                         }
3875                         if (pgrp == getpgrp())
3876                                 break;
3877                         killpg(0, SIGTTIN);
3878                 }
3879                 initialpgrp = pgrp;
3880
3881                 setsignal(SIGTSTP);
3882                 setsignal(SIGTTOU);
3883                 setsignal(SIGTTIN);
3884                 pgrp = rootpid;
3885                 setpgid(0, pgrp);
3886                 xtcsetpgrp(fd, pgrp);
3887         } else {
3888                 /* turning job control off */
3889                 fd = ttyfd;
3890                 pgrp = initialpgrp;
3891                 /* was xtcsetpgrp, but this can make exiting ash
3892                  * loop forever if pty is already deleted */
3893                 tcsetpgrp(fd, pgrp);
3894                 setpgid(0, pgrp);
3895                 setsignal(SIGTSTP);
3896                 setsignal(SIGTTOU);
3897                 setsignal(SIGTTIN);
3898  close:
3899                 if (fd >= 0)
3900                         close(fd);
3901                 fd = -1;
3902         }
3903         ttyfd = fd;
3904         doing_jobctl = on;
3905 }
3906
3907 static int FAST_FUNC
3908 killcmd(int argc, char **argv)
3909 {
3910         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3911                 int i = 1;
3912                 do {
3913                         if (argv[i][0] == '%') {
3914                                 /*
3915                                  * "kill %N" - job kill
3916                                  * Converting to pgrp / pid kill
3917                                  */
3918                                 struct job *jp;
3919                                 char *dst;
3920                                 int j, n;
3921
3922                                 jp = getjob(argv[i], 0);
3923                                 /*
3924                                  * In jobs started under job control, we signal
3925                                  * entire process group by kill -PGRP_ID.
3926                                  * This happens, f.e., in interactive shell.
3927                                  *
3928                                  * Otherwise, we signal each child via
3929                                  * kill PID1 PID2 PID3.
3930                                  * Testcases:
3931                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3932                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3933                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3934                                  */
3935                                 n = jp->nprocs; /* can't be 0 (I hope) */
3936                                 if (jp->jobctl)
3937                                         n = 1;
3938                                 dst = alloca(n * sizeof(int)*4);
3939                                 argv[i] = dst;
3940                                 for (j = 0; j < n; j++) {
3941                                         struct procstat *ps = &jp->ps[j];
3942                                         /* Skip non-running and not-stopped members
3943                                          * (i.e. dead members) of the job
3944                                          */
3945                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3946                                                 continue;
3947                                         /*
3948                                          * kill_main has matching code to expect
3949                                          * leading space. Needed to not confuse
3950                                          * negative pids with "kill -SIGNAL_NO" syntax
3951                                          */
3952                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3953                                 }
3954                                 *dst = '\0';
3955                         }
3956                 } while (argv[++i]);
3957         }
3958         return kill_main(argc, argv);
3959 }
3960
3961 static void
3962 showpipe(struct job *jp /*, FILE *out*/)
3963 {
3964         struct procstat *ps;
3965         struct procstat *psend;
3966
3967         psend = jp->ps + jp->nprocs;
3968         for (ps = jp->ps + 1; ps < psend; ps++)
3969                 printf(" | %s", ps->ps_cmd);
3970         newline_and_flush(stdout);
3971         flush_stdout_stderr();
3972 }
3973
3974
3975 static int
3976 restartjob(struct job *jp, int mode)
3977 {
3978         struct procstat *ps;
3979         int i;
3980         int status;
3981         pid_t pgid;
3982
3983         INT_OFF;
3984         if (jp->state == JOBDONE)
3985                 goto out;
3986         jp->state = JOBRUNNING;
3987         pgid = jp->ps[0].ps_pid;
3988         if (mode == FORK_FG) {
3989                 get_tty_state();
3990                 xtcsetpgrp(ttyfd, pgid);
3991         }
3992         killpg(pgid, SIGCONT);
3993         ps = jp->ps;
3994         i = jp->nprocs;
3995         do {
3996                 if (WIFSTOPPED(ps->ps_status)) {
3997                         ps->ps_status = -1;
3998                 }
3999                 ps++;
4000         } while (--i);
4001  out:
4002         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4003         INT_ON;
4004         return status;
4005 }
4006
4007 static int FAST_FUNC
4008 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4009 {
4010         struct job *jp;
4011         int mode;
4012         int retval;
4013
4014         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4015         nextopt(nullstr);
4016         argv = argptr;
4017         do {
4018                 jp = getjob(*argv, 1);
4019                 if (mode == FORK_BG) {
4020                         set_curjob(jp, CUR_RUNNING);
4021                         printf("[%d] ", jobno(jp));
4022                 }
4023                 out1str(jp->ps[0].ps_cmd);
4024                 showpipe(jp /*, stdout*/);
4025                 retval = restartjob(jp, mode);
4026         } while (*argv && *++argv);
4027         return retval;
4028 }
4029 #endif
4030
4031 static int
4032 sprint_status48(char *s, int status, int sigonly)
4033 {
4034         int col;
4035         int st;
4036
4037         col = 0;
4038         if (!WIFEXITED(status)) {
4039 #if JOBS
4040                 if (WIFSTOPPED(status))
4041                         st = WSTOPSIG(status);
4042                 else
4043 #endif
4044                         st = WTERMSIG(status);
4045                 if (sigonly) {
4046                         if (st == SIGINT || st == SIGPIPE)
4047                                 goto out;
4048 #if JOBS
4049                         if (WIFSTOPPED(status))
4050                                 goto out;
4051 #endif
4052                 }
4053                 st &= 0x7f;
4054 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4055                 col = fmtstr(s, 32, strsignal(st));
4056                 if (WCOREDUMP(status)) {
4057                         strcpy(s + col, " (core dumped)");
4058                         col += sizeof(" (core dumped)")-1;
4059                 }
4060         } else if (!sigonly) {
4061                 st = WEXITSTATUS(status);
4062                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4063         }
4064  out:
4065         return col;
4066 }
4067
4068 static int
4069 wait_block_or_sig(int *status)
4070 {
4071         int pid;
4072
4073         do {
4074                 sigset_t mask;
4075
4076                 /* Poll all children for changes in their state */
4077                 got_sigchld = 0;
4078                 /* if job control is active, accept stopped processes too */
4079                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4080                 if (pid != 0)
4081                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4082
4083                 /* Children exist, but none are ready. Sleep until interesting signal */
4084 #if 1
4085                 sigfillset(&mask);
4086                 sigprocmask(SIG_SETMASK, &mask, &mask);
4087                 while (!got_sigchld && !pending_sig)
4088                         sigsuspend(&mask);
4089                 sigprocmask(SIG_SETMASK, &mask, NULL);
4090 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4091                 while (!got_sigchld && !pending_sig)
4092                         pause();
4093 #endif
4094
4095                 /* If it was SIGCHLD, poll children again */
4096         } while (got_sigchld);
4097
4098         return pid;
4099 }
4100
4101 #define DOWAIT_NONBLOCK 0
4102 #define DOWAIT_BLOCK    1
4103 #define DOWAIT_BLOCK_OR_SIG 2
4104
4105 static int
4106 dowait(int block, struct job *job)
4107 {
4108         int pid;
4109         int status;
4110         struct job *jp;
4111         struct job *thisjob = NULL;
4112
4113         TRACE(("dowait(0x%x) called\n", block));
4114
4115         /* It's wrong to call waitpid() outside of INT_OFF region:
4116          * signal can arrive just after syscall return and handler can
4117          * longjmp away, losing stop/exit notification processing.
4118          * Thus, for "jobs" builtin, and for waiting for a fg job,
4119          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4120          *
4121          * However, for "wait" builtin it is wrong to simply call waitpid()
4122          * in INT_OFF region: "wait" needs to wait for any running job
4123          * to change state, but should exit on any trap too.
4124          * In INT_OFF region, a signal just before syscall entry can set
4125          * pending_sig variables, but we can't check them, and we would
4126          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4127          *
4128          * Because of this, we run inside INT_OFF, but use a special routine
4129          * which combines waitpid() and sigsuspend().
4130          * This is the reason why we need to have a handler for SIGCHLD:
4131          * SIG_DFL handler does not wake sigsuspend().
4132          */
4133         INT_OFF;
4134         if (block == DOWAIT_BLOCK_OR_SIG) {
4135                 pid = wait_block_or_sig(&status);
4136         } else {
4137                 int wait_flags = 0;
4138                 if (block == DOWAIT_NONBLOCK)
4139                         wait_flags = WNOHANG;
4140                 /* if job control is active, accept stopped processes too */
4141                 if (doing_jobctl)
4142                         wait_flags |= WUNTRACED;
4143                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4144                 pid = waitpid(-1, &status, wait_flags);
4145         }
4146         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4147                                 pid, status, errno, strerror(errno)));
4148         if (pid <= 0)
4149                 goto out;
4150
4151         thisjob = NULL;
4152         for (jp = curjob; jp; jp = jp->prev_job) {
4153                 int jobstate;
4154                 struct procstat *ps;
4155                 struct procstat *psend;
4156                 if (jp->state == JOBDONE)
4157                         continue;
4158                 jobstate = JOBDONE;
4159                 ps = jp->ps;
4160                 psend = ps + jp->nprocs;
4161                 do {
4162                         if (ps->ps_pid == pid) {
4163                                 TRACE(("Job %d: changing status of proc %d "
4164                                         "from 0x%x to 0x%x\n",
4165                                         jobno(jp), pid, ps->ps_status, status));
4166                                 ps->ps_status = status;
4167                                 thisjob = jp;
4168                         }
4169                         if (ps->ps_status == -1)
4170                                 jobstate = JOBRUNNING;
4171 #if JOBS
4172                         if (jobstate == JOBRUNNING)
4173                                 continue;
4174                         if (WIFSTOPPED(ps->ps_status)) {
4175                                 jp->stopstatus = ps->ps_status;
4176                                 jobstate = JOBSTOPPED;
4177                         }
4178 #endif
4179                 } while (++ps < psend);
4180                 if (!thisjob)
4181                         continue;
4182
4183                 /* Found the job where one of its processes changed its state.
4184                  * Is there at least one live and running process in this job? */
4185                 if (jobstate != JOBRUNNING) {
4186                         /* No. All live processes in the job are stopped
4187                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4188                          */
4189                         thisjob->changed = 1;
4190                         if (thisjob->state != jobstate) {
4191                                 TRACE(("Job %d: changing state from %d to %d\n",
4192                                         jobno(thisjob), thisjob->state, jobstate));
4193                                 thisjob->state = jobstate;
4194 #if JOBS
4195                                 if (jobstate == JOBSTOPPED)
4196                                         set_curjob(thisjob, CUR_STOPPED);
4197 #endif
4198                         }
4199                 }
4200                 goto out;
4201         }
4202         /* The process wasn't found in job list */
4203 #if JOBS
4204         if (!WIFSTOPPED(status))
4205                 jobless--;
4206 #endif
4207  out:
4208         INT_ON;
4209
4210         if (thisjob && thisjob == job) {
4211                 char s[48 + 1];
4212                 int len;
4213
4214                 len = sprint_status48(s, status, 1);
4215                 if (len) {
4216                         s[len] = '\n';
4217                         s[len + 1] = '\0';
4218                         out2str(s);
4219                 }
4220         }
4221         return pid;
4222 }
4223
4224 #if JOBS
4225 static void
4226 showjob(struct job *jp, int mode)
4227 {
4228         struct procstat *ps;
4229         struct procstat *psend;
4230         int col;
4231         int indent_col;
4232         char s[16 + 16 + 48];
4233         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4234
4235         ps = jp->ps;
4236
4237         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4238                 /* just output process (group) id of pipeline */
4239                 fprintf(out, "%d\n", ps->ps_pid);
4240                 return;
4241         }
4242
4243         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4244         indent_col = col;
4245
4246         if (jp == curjob)
4247                 s[col - 3] = '+';
4248         else if (curjob && jp == curjob->prev_job)
4249                 s[col - 3] = '-';
4250
4251         if (mode & SHOW_PIDS)
4252                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4253
4254         psend = ps + jp->nprocs;
4255
4256         if (jp->state == JOBRUNNING) {
4257                 strcpy(s + col, "Running");
4258                 col += sizeof("Running") - 1;
4259         } else {
4260                 int status = psend[-1].ps_status;
4261                 if (jp->state == JOBSTOPPED)
4262                         status = jp->stopstatus;
4263                 col += sprint_status48(s + col, status, 0);
4264         }
4265         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4266
4267         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4268          * or prints several "PID             | <cmdN>" lines,
4269          * depending on SHOW_PIDS bit.
4270          * We do not print status of individual processes
4271          * between PID and <cmdN>. bash does it, but not very well:
4272          * first line shows overall job status, not process status,
4273          * making it impossible to know 1st process status.
4274          */
4275         goto start;
4276         do {
4277                 /* for each process */
4278                 s[0] = '\0';
4279                 col = 33;
4280                 if (mode & SHOW_PIDS)
4281                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4282  start:
4283                 fprintf(out, "%s%*c%s%s",
4284                                 s,
4285                                 33 - col >= 0 ? 33 - col : 0, ' ',
4286                                 ps == jp->ps ? "" : "| ",
4287                                 ps->ps_cmd
4288                 );
4289         } while (++ps != psend);
4290         newline_and_flush(out);
4291
4292         jp->changed = 0;
4293
4294         if (jp->state == JOBDONE) {
4295                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4296                 freejob(jp);
4297         }
4298 }
4299
4300 /*
4301  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4302  * statuses have changed since the last call to showjobs.
4303  */
4304 static void
4305 showjobs(int mode)
4306 {
4307         struct job *jp;
4308
4309         TRACE(("showjobs(0x%x) called\n", mode));
4310
4311         /* Handle all finished jobs */
4312         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4313                 continue;
4314
4315         for (jp = curjob; jp; jp = jp->prev_job) {
4316                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4317                         showjob(jp, mode);
4318                 }
4319         }
4320 }
4321
4322 static int FAST_FUNC
4323 jobscmd(int argc UNUSED_PARAM, char **argv)
4324 {
4325         int mode, m;
4326
4327         mode = 0;
4328         while ((m = nextopt("lp")) != '\0') {
4329                 if (m == 'l')
4330                         mode |= SHOW_PIDS;
4331                 else
4332                         mode |= SHOW_ONLY_PGID;
4333         }
4334
4335         argv = argptr;
4336         if (*argv) {
4337                 do
4338                         showjob(getjob(*argv, 0), mode);
4339                 while (*++argv);
4340         } else {
4341                 showjobs(mode);
4342         }
4343
4344         return 0;
4345 }
4346 #endif /* JOBS */
4347
4348 /* Called only on finished or stopped jobs (no members are running) */
4349 static int
4350 getstatus(struct job *job)
4351 {
4352         int status;
4353         int retval;
4354         struct procstat *ps;
4355
4356         /* Fetch last member's status */
4357         ps = job->ps + job->nprocs - 1;
4358         status = ps->ps_status;
4359         if (pipefail) {
4360                 /* "set -o pipefail" mode: use last _nonzero_ status */
4361                 while (status == 0 && --ps >= job->ps)
4362                         status = ps->ps_status;
4363         }
4364
4365         retval = WEXITSTATUS(status);
4366         if (!WIFEXITED(status)) {
4367 #if JOBS
4368                 retval = WSTOPSIG(status);
4369                 if (!WIFSTOPPED(status))
4370 #endif
4371                 {
4372                         /* XXX: limits number of signals */
4373                         retval = WTERMSIG(status);
4374 #if JOBS
4375                         if (retval == SIGINT)
4376                                 job->sigint = 1;
4377 #endif
4378                 }
4379                 retval += 128;
4380         }
4381         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4382                 jobno(job), job->nprocs, status, retval));
4383         return retval;
4384 }
4385
4386 static int FAST_FUNC
4387 waitcmd(int argc UNUSED_PARAM, char **argv)
4388 {
4389         struct job *job;
4390         int retval;
4391         struct job *jp;
4392
4393         nextopt(nullstr);
4394         retval = 0;
4395
4396         argv = argptr;
4397         if (!*argv) {
4398                 /* wait for all jobs */
4399                 for (;;) {
4400                         jp = curjob;
4401                         while (1) {
4402                                 if (!jp) /* no running procs */
4403                                         goto ret;
4404                                 if (jp->state == JOBRUNNING)
4405                                         break;
4406                                 jp->waited = 1;
4407                                 jp = jp->prev_job;
4408                         }
4409         /* man bash:
4410          * "When bash is waiting for an asynchronous command via
4411          * the wait builtin, the reception of a signal for which a trap
4412          * has been set will cause the wait builtin to return immediately
4413          * with an exit status greater than 128, immediately after which
4414          * the trap is executed."
4415          */
4416                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4417         /* if child sends us a signal *and immediately exits*,
4418          * dowait() returns pid > 0. Check this case,
4419          * not "if (dowait() < 0)"!
4420          */
4421                         if (pending_sig)
4422                                 goto sigout;
4423                 }
4424         }
4425
4426         retval = 127;
4427         do {
4428                 if (**argv != '%') {
4429                         pid_t pid = number(*argv);
4430                         job = curjob;
4431                         while (1) {
4432                                 if (!job)
4433                                         goto repeat;
4434                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4435                                         break;
4436                                 job = job->prev_job;
4437                         }
4438                 } else {
4439                         job = getjob(*argv, 0);
4440                 }
4441                 /* loop until process terminated or stopped */
4442                 while (job->state == JOBRUNNING) {
4443                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4444                         if (pending_sig)
4445                                 goto sigout;
4446                 }
4447                 job->waited = 1;
4448                 retval = getstatus(job);
4449  repeat: ;
4450         } while (*++argv);
4451
4452  ret:
4453         return retval;
4454  sigout:
4455         retval = 128 + pending_sig;
4456         return retval;
4457 }
4458
4459 static struct job *
4460 growjobtab(void)
4461 {
4462         size_t len;
4463         ptrdiff_t offset;
4464         struct job *jp, *jq;
4465
4466         len = njobs * sizeof(*jp);
4467         jq = jobtab;
4468         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4469
4470         offset = (char *)jp - (char *)jq;
4471         if (offset) {
4472                 /* Relocate pointers */
4473                 size_t l = len;
4474
4475                 jq = (struct job *)((char *)jq + l);
4476                 while (l) {
4477                         l -= sizeof(*jp);
4478                         jq--;
4479 #define joff(p) ((struct job *)((char *)(p) + l))
4480 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4481                         if (joff(jp)->ps == &jq->ps0)
4482                                 jmove(joff(jp)->ps);
4483                         if (joff(jp)->prev_job)
4484                                 jmove(joff(jp)->prev_job);
4485                 }
4486                 if (curjob)
4487                         jmove(curjob);
4488 #undef joff
4489 #undef jmove
4490         }
4491
4492         njobs += 4;
4493         jobtab = jp;
4494         jp = (struct job *)((char *)jp + len);
4495         jq = jp + 3;
4496         do {
4497                 jq->used = 0;
4498         } while (--jq >= jp);
4499         return jp;
4500 }
4501
4502 /*
4503  * Return a new job structure.
4504  * Called with interrupts off.
4505  */
4506 static struct job *
4507 makejob(/*union node *node,*/ int nprocs)
4508 {
4509         int i;
4510         struct job *jp;
4511
4512         for (i = njobs, jp = jobtab; ; jp++) {
4513                 if (--i < 0) {
4514                         jp = growjobtab();
4515                         break;
4516                 }
4517                 if (jp->used == 0)
4518                         break;
4519                 if (jp->state != JOBDONE || !jp->waited)
4520                         continue;
4521 #if JOBS
4522                 if (doing_jobctl)
4523                         continue;
4524 #endif
4525                 freejob(jp);
4526                 break;
4527         }
4528         memset(jp, 0, sizeof(*jp));
4529 #if JOBS
4530         /* jp->jobctl is a bitfield.
4531          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4532         if (doing_jobctl)
4533                 jp->jobctl = 1;
4534 #endif
4535         jp->prev_job = curjob;
4536         curjob = jp;
4537         jp->used = 1;
4538         jp->ps = &jp->ps0;
4539         if (nprocs > 1) {
4540                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4541         }
4542         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4543                                 jobno(jp)));
4544         return jp;
4545 }
4546
4547 #if JOBS
4548 /*
4549  * Return a string identifying a command (to be printed by the
4550  * jobs command).
4551  */
4552 static char *cmdnextc;
4553
4554 static void
4555 cmdputs(const char *s)
4556 {
4557         static const char vstype[VSTYPE + 1][3] = {
4558                 "", "}", "-", "+", "?", "=",
4559                 "%", "%%", "#", "##"
4560                 IF_BASH_SUBSTR(, ":")
4561                 IF_BASH_PATTERN_SUBST(, "/", "//")
4562         };
4563
4564         const char *p, *str;
4565         char cc[2];
4566         char *nextc;
4567         unsigned char c;
4568         unsigned char subtype = 0;
4569         int quoted = 0;
4570
4571         cc[1] = '\0';
4572         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4573         p = s;
4574         while ((c = *p++) != '\0') {
4575                 str = NULL;
4576                 switch (c) {
4577                 case CTLESC:
4578                         c = *p++;
4579                         break;
4580                 case CTLVAR:
4581                         subtype = *p++;
4582                         if ((subtype & VSTYPE) == VSLENGTH)
4583                                 str = "${#";
4584                         else
4585                                 str = "${";
4586                         goto dostr;
4587                 case CTLENDVAR:
4588                         str = "\"}" + !(quoted & 1);
4589                         quoted >>= 1;
4590                         subtype = 0;
4591                         goto dostr;
4592                 case CTLBACKQ:
4593                         str = "$(...)";
4594                         goto dostr;
4595 #if ENABLE_FEATURE_SH_MATH
4596                 case CTLARI:
4597                         str = "$((";
4598                         goto dostr;
4599                 case CTLENDARI:
4600                         str = "))";
4601                         goto dostr;
4602 #endif
4603                 case CTLQUOTEMARK:
4604                         quoted ^= 1;
4605                         c = '"';
4606                         break;
4607                 case '=':
4608                         if (subtype == 0)
4609                                 break;
4610                         if ((subtype & VSTYPE) != VSNORMAL)
4611                                 quoted <<= 1;
4612                         str = vstype[subtype & VSTYPE];
4613                         if (subtype & VSNUL)
4614                                 c = ':';
4615                         else
4616                                 goto checkstr;
4617                         break;
4618                 case '\'':
4619                 case '\\':
4620                 case '"':
4621                 case '$':
4622                         /* These can only happen inside quotes */
4623                         cc[0] = c;
4624                         str = cc;
4625                         c = '\\';
4626                         break;
4627                 default:
4628                         break;
4629                 }
4630                 USTPUTC(c, nextc);
4631  checkstr:
4632                 if (!str)
4633                         continue;
4634  dostr:
4635                 while ((c = *str++) != '\0') {
4636                         USTPUTC(c, nextc);
4637                 }
4638         } /* while *p++ not NUL */
4639
4640         if (quoted & 1) {
4641                 USTPUTC('"', nextc);
4642         }
4643         *nextc = 0;
4644         cmdnextc = nextc;
4645 }
4646
4647 /* cmdtxt() and cmdlist() call each other */
4648 static void cmdtxt(union node *n);
4649
4650 static void
4651 cmdlist(union node *np, int sep)
4652 {
4653         for (; np; np = np->narg.next) {
4654                 if (!sep)
4655                         cmdputs(" ");
4656                 cmdtxt(np);
4657                 if (sep && np->narg.next)
4658                         cmdputs(" ");
4659         }
4660 }
4661
4662 static void
4663 cmdtxt(union node *n)
4664 {
4665         union node *np;
4666         struct nodelist *lp;
4667         const char *p;
4668
4669         if (!n)
4670                 return;
4671         switch (n->type) {
4672         default:
4673 #if DEBUG
4674                 abort();
4675 #endif
4676         case NPIPE:
4677                 lp = n->npipe.cmdlist;
4678                 for (;;) {
4679                         cmdtxt(lp->n);
4680                         lp = lp->next;
4681                         if (!lp)
4682                                 break;
4683                         cmdputs(" | ");
4684                 }
4685                 break;
4686         case NSEMI:
4687                 p = "; ";
4688                 goto binop;
4689         case NAND:
4690                 p = " && ";
4691                 goto binop;
4692         case NOR:
4693                 p = " || ";
4694  binop:
4695                 cmdtxt(n->nbinary.ch1);
4696                 cmdputs(p);
4697                 n = n->nbinary.ch2;
4698                 goto donode;
4699         case NREDIR:
4700         case NBACKGND:
4701                 n = n->nredir.n;
4702                 goto donode;
4703         case NNOT:
4704                 cmdputs("!");
4705                 n = n->nnot.com;
4706  donode:
4707                 cmdtxt(n);
4708                 break;
4709         case NIF:
4710                 cmdputs("if ");
4711                 cmdtxt(n->nif.test);
4712                 cmdputs("; then ");
4713                 if (n->nif.elsepart) {
4714                         cmdtxt(n->nif.ifpart);
4715                         cmdputs("; else ");
4716                         n = n->nif.elsepart;
4717                 } else {
4718                         n = n->nif.ifpart;
4719                 }
4720                 p = "; fi";
4721                 goto dotail;
4722         case NSUBSHELL:
4723                 cmdputs("(");
4724                 n = n->nredir.n;
4725                 p = ")";
4726                 goto dotail;
4727         case NWHILE:
4728                 p = "while ";
4729                 goto until;
4730         case NUNTIL:
4731                 p = "until ";
4732  until:
4733                 cmdputs(p);
4734                 cmdtxt(n->nbinary.ch1);
4735                 n = n->nbinary.ch2;
4736                 p = "; done";
4737  dodo:
4738                 cmdputs("; do ");
4739  dotail:
4740                 cmdtxt(n);
4741                 goto dotail2;
4742         case NFOR:
4743                 cmdputs("for ");
4744                 cmdputs(n->nfor.var);
4745                 cmdputs(" in ");
4746                 cmdlist(n->nfor.args, 1);
4747                 n = n->nfor.body;
4748                 p = "; done";
4749                 goto dodo;
4750         case NDEFUN:
4751                 cmdputs(n->narg.text);
4752                 p = "() { ... }";
4753                 goto dotail2;
4754         case NCMD:
4755                 cmdlist(n->ncmd.args, 1);
4756                 cmdlist(n->ncmd.redirect, 0);
4757                 break;
4758         case NARG:
4759                 p = n->narg.text;
4760  dotail2:
4761                 cmdputs(p);
4762                 break;
4763         case NHERE:
4764         case NXHERE:
4765                 p = "<<...";
4766                 goto dotail2;
4767         case NCASE:
4768                 cmdputs("case ");
4769                 cmdputs(n->ncase.expr->narg.text);
4770                 cmdputs(" in ");
4771                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4772                         cmdtxt(np->nclist.pattern);
4773                         cmdputs(") ");
4774                         cmdtxt(np->nclist.body);
4775                         cmdputs(";; ");
4776                 }
4777                 p = "esac";
4778                 goto dotail2;
4779         case NTO:
4780                 p = ">";
4781                 goto redir;
4782         case NCLOBBER:
4783                 p = ">|";
4784                 goto redir;
4785         case NAPPEND:
4786                 p = ">>";
4787                 goto redir;
4788 #if BASH_REDIR_OUTPUT
4789         case NTO2:
4790 #endif
4791         case NTOFD:
4792                 p = ">&";
4793                 goto redir;
4794         case NFROM:
4795                 p = "<";
4796                 goto redir;
4797         case NFROMFD:
4798                 p = "<&";
4799                 goto redir;
4800         case NFROMTO:
4801                 p = "<>";
4802  redir:
4803                 cmdputs(utoa(n->nfile.fd));
4804                 cmdputs(p);
4805                 if (n->type == NTOFD || n->type == NFROMFD) {
4806                         cmdputs(utoa(n->ndup.dupfd));
4807                         break;
4808                 }
4809                 n = n->nfile.fname;
4810                 goto donode;
4811         }
4812 }
4813
4814 static char *
4815 commandtext(union node *n)
4816 {
4817         char *name;
4818
4819         STARTSTACKSTR(cmdnextc);
4820         cmdtxt(n);
4821         name = stackblock();
4822         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4823         return ckstrdup(name);
4824 }
4825 #endif /* JOBS */
4826
4827 /*
4828  * Fork off a subshell.  If we are doing job control, give the subshell its
4829  * own process group.  Jp is a job structure that the job is to be added to.
4830  * N is the command that will be evaluated by the child.  Both jp and n may
4831  * be NULL.  The mode parameter can be one of the following:
4832  *      FORK_FG - Fork off a foreground process.
4833  *      FORK_BG - Fork off a background process.
4834  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4835  *                   process group even if job control is on.
4836  *
4837  * When job control is turned off, background processes have their standard
4838  * input redirected to /dev/null (except for the second and later processes
4839  * in a pipeline).
4840  *
4841  * Called with interrupts off.
4842  */
4843 /*
4844  * Clear traps on a fork.
4845  */
4846 static void
4847 clear_traps(void)
4848 {
4849         char **tp;
4850
4851         INT_OFF;
4852         for (tp = trap; tp < &trap[NSIG]; tp++) {
4853                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4854                         if (trap_ptr == trap)
4855                                 free(*tp);
4856                         /* else: it "belongs" to trap_ptr vector, don't free */
4857                         *tp = NULL;
4858                         if ((tp - trap) != 0)
4859                                 setsignal(tp - trap);
4860                 }
4861         }
4862         may_have_traps = 0;
4863         INT_ON;
4864 }
4865
4866 /* Lives far away from here, needed for forkchild */
4867 static void closescript(void);
4868
4869 /* Called after fork(), in child */
4870 /* jp and n are NULL when called by openhere() for heredoc support */
4871 static NOINLINE void
4872 forkchild(struct job *jp, union node *n, int mode)
4873 {
4874         int oldlvl;
4875
4876         TRACE(("Child shell %d\n", getpid()));
4877         oldlvl = shlvl;
4878         shlvl++;
4879
4880         /* man bash: "Non-builtin commands run by bash have signal handlers
4881          * set to the values inherited by the shell from its parent".
4882          * Do we do it correctly? */
4883
4884         closescript();
4885
4886         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4887          && n && n->type == NCMD        /* is it single cmd? */
4888         /* && n->ncmd.args->type == NARG - always true? */
4889          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4890          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4891         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4892         ) {
4893                 TRACE(("Trap hack\n"));
4894                 /* Awful hack for `trap` or $(trap).
4895                  *
4896                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4897                  * contains an example where "trap" is executed in a subshell:
4898                  *
4899                  * save_traps=$(trap)
4900                  * ...
4901                  * eval "$save_traps"
4902                  *
4903                  * Standard does not say that "trap" in subshell shall print
4904                  * parent shell's traps. It only says that its output
4905                  * must have suitable form, but then, in the above example
4906                  * (which is not supposed to be normative), it implies that.
4907                  *
4908                  * bash (and probably other shell) does implement it
4909                  * (traps are reset to defaults, but "trap" still shows them),
4910                  * but as a result, "trap" logic is hopelessly messed up:
4911                  *
4912                  * # trap
4913                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4914                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4915                  * # true | trap   <--- trap is in subshell - no output (ditto)
4916                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4917                  * trap -- 'echo Ho' SIGWINCH
4918                  * # echo `(trap)`         <--- in subshell in subshell - output
4919                  * trap -- 'echo Ho' SIGWINCH
4920                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4921                  * trap -- 'echo Ho' SIGWINCH
4922                  *
4923                  * The rules when to forget and when to not forget traps
4924                  * get really complex and nonsensical.
4925                  *
4926                  * Our solution: ONLY bare $(trap) or `trap` is special.
4927                  */
4928                 /* Save trap handler strings for trap builtin to print */
4929                 trap_ptr = xmemdup(trap, sizeof(trap));
4930                 /* Fall through into clearing traps */
4931         }
4932         clear_traps();
4933 #if JOBS
4934         /* do job control only in root shell */
4935         doing_jobctl = 0;
4936         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4937                 pid_t pgrp;
4938
4939                 if (jp->nprocs == 0)
4940                         pgrp = getpid();
4941                 else
4942                         pgrp = jp->ps[0].ps_pid;
4943                 /* this can fail because we are doing it in the parent also */
4944                 setpgid(0, pgrp);
4945                 if (mode == FORK_FG)
4946                         xtcsetpgrp(ttyfd, pgrp);
4947                 setsignal(SIGTSTP);
4948                 setsignal(SIGTTOU);
4949         } else
4950 #endif
4951         if (mode == FORK_BG) {
4952                 /* man bash: "When job control is not in effect,
4953                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4954                 ignoresig(SIGINT);
4955                 ignoresig(SIGQUIT);
4956                 if (jp->nprocs == 0) {
4957                         close(0);
4958                         if (open(bb_dev_null, O_RDONLY) != 0)
4959                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4960                 }
4961         }
4962         if (oldlvl == 0) {
4963                 if (iflag) { /* why if iflag only? */
4964                         setsignal(SIGINT);
4965                         setsignal(SIGTERM);
4966                 }
4967                 /* man bash:
4968                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4969                  * commands run by bash have signal handlers
4970                  * set to the values inherited by the shell
4971                  * from its parent".
4972                  * Take care of the second rule: */
4973                 setsignal(SIGQUIT);
4974         }
4975 #if JOBS
4976         if (n && n->type == NCMD
4977          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4978         ) {
4979                 TRACE(("Job hack\n"));
4980                 /* "jobs": we do not want to clear job list for it,
4981                  * instead we remove only _its_ own_ job from job list.
4982                  * This makes "jobs .... | cat" more useful.
4983                  */
4984                 freejob(curjob);
4985                 return;
4986         }
4987 #endif
4988         for (jp = curjob; jp; jp = jp->prev_job)
4989                 freejob(jp);
4990         jobless = 0;
4991 }
4992
4993 /* Called after fork(), in parent */
4994 #if !JOBS
4995 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4996 #endif
4997 static void
4998 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4999 {
5000         TRACE(("In parent shell: child = %d\n", pid));
5001         if (!jp) {
5002                 /* jp is NULL when called by openhere() for heredoc support */
5003                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5004                         continue;
5005                 jobless++;
5006                 return;
5007         }
5008 #if JOBS
5009         if (mode != FORK_NOJOB && jp->jobctl) {
5010                 int pgrp;
5011
5012                 if (jp->nprocs == 0)
5013                         pgrp = pid;
5014                 else
5015                         pgrp = jp->ps[0].ps_pid;
5016                 /* This can fail because we are doing it in the child also */
5017                 setpgid(pid, pgrp);
5018         }
5019 #endif
5020         if (mode == FORK_BG) {
5021                 backgndpid = pid;               /* set $! */
5022                 set_curjob(jp, CUR_RUNNING);
5023         }
5024         if (jp) {
5025                 struct procstat *ps = &jp->ps[jp->nprocs++];
5026                 ps->ps_pid = pid;
5027                 ps->ps_status = -1;
5028                 ps->ps_cmd = nullstr;
5029 #if JOBS
5030                 if (doing_jobctl && n)
5031                         ps->ps_cmd = commandtext(n);
5032 #endif
5033         }
5034 }
5035
5036 /* jp and n are NULL when called by openhere() for heredoc support */
5037 static int
5038 forkshell(struct job *jp, union node *n, int mode)
5039 {
5040         int pid;
5041
5042         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5043         pid = fork();
5044         if (pid < 0) {
5045                 TRACE(("Fork failed, errno=%d", errno));
5046                 if (jp)
5047                         freejob(jp);
5048                 ash_msg_and_raise_error("can't fork");
5049         }
5050         if (pid == 0) {
5051                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5052                 forkchild(jp, n, mode);
5053         } else {
5054                 forkparent(jp, n, mode, pid);
5055         }
5056         return pid;
5057 }
5058
5059 /*
5060  * Wait for job to finish.
5061  *
5062  * Under job control we have the problem that while a child process
5063  * is running interrupts generated by the user are sent to the child
5064  * but not to the shell.  This means that an infinite loop started by
5065  * an interactive user may be hard to kill.  With job control turned off,
5066  * an interactive user may place an interactive program inside a loop.
5067  * If the interactive program catches interrupts, the user doesn't want
5068  * these interrupts to also abort the loop.  The approach we take here
5069  * is to have the shell ignore interrupt signals while waiting for a
5070  * foreground process to terminate, and then send itself an interrupt
5071  * signal if the child process was terminated by an interrupt signal.
5072  * Unfortunately, some programs want to do a bit of cleanup and then
5073  * exit on interrupt; unless these processes terminate themselves by
5074  * sending a signal to themselves (instead of calling exit) they will
5075  * confuse this approach.
5076  *
5077  * Called with interrupts off.
5078  */
5079 static int
5080 waitforjob(struct job *jp)
5081 {
5082         int st;
5083
5084         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5085
5086         INT_OFF;
5087         while (jp->state == JOBRUNNING) {
5088                 /* In non-interactive shells, we _can_ get
5089                  * a keyboard signal here and be EINTRed,
5090                  * but we just loop back, waiting for command to complete.
5091                  *
5092                  * man bash:
5093                  * "If bash is waiting for a command to complete and receives
5094                  * a signal for which a trap has been set, the trap
5095                  * will not be executed until the command completes."
5096                  *
5097                  * Reality is that even if trap is not set, bash
5098                  * will not act on the signal until command completes.
5099                  * Try this. sleep5intoff.c:
5100                  * #include <signal.h>
5101                  * #include <unistd.h>
5102                  * int main() {
5103                  *         sigset_t set;
5104                  *         sigemptyset(&set);
5105                  *         sigaddset(&set, SIGINT);
5106                  *         sigaddset(&set, SIGQUIT);
5107                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5108                  *         sleep(5);
5109                  *         return 0;
5110                  * }
5111                  * $ bash -c './sleep5intoff; echo hi'
5112                  * ^C^C^C^C <--- pressing ^C once a second
5113                  * $ _
5114                  * $ bash -c './sleep5intoff; echo hi'
5115                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5116                  * $ _
5117                  */
5118                 dowait(DOWAIT_BLOCK, jp);
5119         }
5120         INT_ON;
5121
5122         st = getstatus(jp);
5123 #if JOBS
5124         if (jp->jobctl) {
5125                 xtcsetpgrp(ttyfd, rootpid);
5126                 restore_tty_if_stopped_or_signaled(jp);
5127
5128                 /*
5129                  * This is truly gross.
5130                  * If we're doing job control, then we did a TIOCSPGRP which
5131                  * caused us (the shell) to no longer be in the controlling
5132                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5133                  * intuit from the subprocess exit status whether a SIGINT
5134                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5135                  */
5136                 if (jp->sigint) /* TODO: do the same with all signals */
5137                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5138         }
5139         if (jp->state == JOBDONE)
5140 #endif
5141                 freejob(jp);
5142         return st;
5143 }
5144
5145 /*
5146  * return 1 if there are stopped jobs, otherwise 0
5147  */
5148 static int
5149 stoppedjobs(void)
5150 {
5151         struct job *jp;
5152         int retval;
5153
5154         retval = 0;
5155         if (job_warning)
5156                 goto out;
5157         jp = curjob;
5158         if (jp && jp->state == JOBSTOPPED) {
5159                 out2str("You have stopped jobs.\n");
5160                 job_warning = 2;
5161                 retval++;
5162         }
5163  out:
5164         return retval;
5165 }
5166
5167
5168 /*
5169  * Code for dealing with input/output redirection.
5170  */
5171
5172 #undef EMPTY
5173 #undef CLOSED
5174 #define EMPTY -2                /* marks an unused slot in redirtab */
5175 #define CLOSED -3               /* marks a slot of previously-closed fd */
5176
5177 /*
5178  * Open a file in noclobber mode.
5179  * The code was copied from bash.
5180  */
5181 static int
5182 noclobberopen(const char *fname)
5183 {
5184         int r, fd;
5185         struct stat finfo, finfo2;
5186
5187         /*
5188          * If the file exists and is a regular file, return an error
5189          * immediately.
5190          */
5191         r = stat(fname, &finfo);
5192         if (r == 0 && S_ISREG(finfo.st_mode)) {
5193                 errno = EEXIST;
5194                 return -1;
5195         }
5196
5197         /*
5198          * If the file was not present (r != 0), make sure we open it
5199          * exclusively so that if it is created before we open it, our open
5200          * will fail.  Make sure that we do not truncate an existing file.
5201          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5202          * file was not a regular file, we leave O_EXCL off.
5203          */
5204         if (r != 0)
5205                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5206         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5207
5208         /* If the open failed, return the file descriptor right away. */
5209         if (fd < 0)
5210                 return fd;
5211
5212         /*
5213          * OK, the open succeeded, but the file may have been changed from a
5214          * non-regular file to a regular file between the stat and the open.
5215          * We are assuming that the O_EXCL open handles the case where FILENAME
5216          * did not exist and is symlinked to an existing file between the stat
5217          * and open.
5218          */
5219
5220         /*
5221          * If we can open it and fstat the file descriptor, and neither check
5222          * revealed that it was a regular file, and the file has not been
5223          * replaced, return the file descriptor.
5224          */
5225         if (fstat(fd, &finfo2) == 0
5226          && !S_ISREG(finfo2.st_mode)
5227          && finfo.st_dev == finfo2.st_dev
5228          && finfo.st_ino == finfo2.st_ino
5229         ) {
5230                 return fd;
5231         }
5232
5233         /* The file has been replaced.  badness. */
5234         close(fd);
5235         errno = EEXIST;
5236         return -1;
5237 }
5238
5239 /*
5240  * Handle here documents.  Normally we fork off a process to write the
5241  * data to a pipe.  If the document is short, we can stuff the data in
5242  * the pipe without forking.
5243  */
5244 /* openhere needs this forward reference */
5245 static void expandhere(union node *arg, int fd);
5246 static int
5247 openhere(union node *redir)
5248 {
5249         int pip[2];
5250         size_t len = 0;
5251
5252         if (pipe(pip) < 0)
5253                 ash_msg_and_raise_error("pipe call failed");
5254         if (redir->type == NHERE) {
5255                 len = strlen(redir->nhere.doc->narg.text);
5256                 if (len <= PIPE_BUF) {
5257                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5258                         goto out;
5259                 }
5260         }
5261         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5262                 /* child */
5263                 close(pip[0]);
5264                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5265                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5266                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5267                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5268                 signal(SIGPIPE, SIG_DFL);
5269                 if (redir->type == NHERE)
5270                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5271                 else /* NXHERE */
5272                         expandhere(redir->nhere.doc, pip[1]);
5273                 _exit(EXIT_SUCCESS);
5274         }
5275  out:
5276         close(pip[1]);
5277         return pip[0];
5278 }
5279
5280 static int
5281 openredirect(union node *redir)
5282 {
5283         char *fname;
5284         int f;
5285
5286         switch (redir->nfile.type) {
5287 /* Can't happen, our single caller does this itself */
5288 //      case NTOFD:
5289 //      case NFROMFD:
5290 //              return -1;
5291         case NHERE:
5292         case NXHERE:
5293                 return openhere(redir);
5294         }
5295
5296         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5297          * allocated space. Do it only when we know it is safe.
5298          */
5299         fname = redir->nfile.expfname;
5300
5301         switch (redir->nfile.type) {
5302         default:
5303 #if DEBUG
5304                 abort();
5305 #endif
5306         case NFROM:
5307                 f = open(fname, O_RDONLY);
5308                 if (f < 0)
5309                         goto eopen;
5310                 break;
5311         case NFROMTO:
5312                 f = open(fname, O_RDWR|O_CREAT, 0666);
5313                 if (f < 0)
5314                         goto ecreate;
5315                 break;
5316         case NTO:
5317 #if BASH_REDIR_OUTPUT
5318         case NTO2:
5319 #endif
5320                 /* Take care of noclobber mode. */
5321                 if (Cflag) {
5322                         f = noclobberopen(fname);
5323                         if (f < 0)
5324                                 goto ecreate;
5325                         break;
5326                 }
5327                 /* FALLTHROUGH */
5328         case NCLOBBER:
5329                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5330                 if (f < 0)
5331                         goto ecreate;
5332                 break;
5333         case NAPPEND:
5334                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5335                 if (f < 0)
5336                         goto ecreate;
5337                 break;
5338         }
5339
5340         return f;
5341  ecreate:
5342         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5343  eopen:
5344         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5345 }
5346
5347 /*
5348  * Copy a file descriptor to be >= 10. Throws exception on error.
5349  */
5350 static int
5351 savefd(int from)
5352 {
5353         int newfd;
5354         int err;
5355
5356         newfd = fcntl(from, F_DUPFD, 10);
5357         err = newfd < 0 ? errno : 0;
5358         if (err != EBADF) {
5359                 if (err)
5360                         ash_msg_and_raise_error("%d: %m", from);
5361                 close(from);
5362                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5363         }
5364
5365         return newfd;
5366 }
5367 static int
5368 dup2_or_raise(int from, int to)
5369 {
5370         int newfd;
5371
5372         newfd = (from != to) ? dup2(from, to) : to;
5373         if (newfd < 0) {
5374                 /* Happens when source fd is not open: try "echo >&99" */
5375                 ash_msg_and_raise_error("%d: %m", from);
5376         }
5377         return newfd;
5378 }
5379
5380 /* Struct def and variable are moved down to the first usage site */
5381 struct two_fd_t {
5382         int orig, copy;
5383 };
5384 struct redirtab {
5385         struct redirtab *next;
5386         int pair_count;
5387         struct two_fd_t two_fd[];
5388 };
5389 #define redirlist (G_var.redirlist)
5390 enum {
5391         COPYFD_RESTORE = (int)~(INT_MAX),
5392 };
5393
5394 static int
5395 need_to_remember(struct redirtab *rp, int fd)
5396 {
5397         int i;
5398
5399         if (!rp) /* remembering was not requested */
5400                 return 0;
5401
5402         for (i = 0; i < rp->pair_count; i++) {
5403                 if (rp->two_fd[i].orig == fd) {
5404                         /* already remembered */
5405                         return 0;
5406                 }
5407         }
5408         return 1;
5409 }
5410
5411 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5412 static int
5413 is_hidden_fd(struct redirtab *rp, int fd)
5414 {
5415         int i;
5416         struct parsefile *pf;
5417
5418         if (fd == -1)
5419                 return 0;
5420         /* Check open scripts' fds */
5421         pf = g_parsefile;
5422         while (pf) {
5423                 /* We skip pf_fd == 0 case because of the following case:
5424                  * $ ash  # running ash interactively
5425                  * $ . ./script.sh
5426                  * and in script.sh: "exec 9>&0".
5427                  * Even though top-level pf_fd _is_ 0,
5428                  * it's still ok to use it: "read" builtin uses it,
5429                  * why should we cripple "exec" builtin?
5430                  */
5431                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5432                         return 1;
5433                 }
5434                 pf = pf->prev;
5435         }
5436
5437         if (!rp)
5438                 return 0;
5439         /* Check saved fds of redirects */
5440         fd |= COPYFD_RESTORE;
5441         for (i = 0; i < rp->pair_count; i++) {
5442                 if (rp->two_fd[i].copy == fd) {
5443                         return 1;
5444                 }
5445         }
5446         return 0;
5447 }
5448
5449 /*
5450  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5451  * old file descriptors are stashed away so that the redirection can be
5452  * undone by calling popredir.
5453  */
5454 /* flags passed to redirect */
5455 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5456 #define REDIR_SAVEFD2 03        /* set preverrout */
5457 static void
5458 redirect(union node *redir, int flags)
5459 {
5460         struct redirtab *sv;
5461         int sv_pos;
5462         int i;
5463         int fd;
5464         int newfd;
5465         int copied_fd2 = -1;
5466
5467         if (!redir) {
5468                 return;
5469         }
5470
5471         sv = NULL;
5472         sv_pos = 0;
5473         INT_OFF;
5474         if (flags & REDIR_PUSH) {
5475                 union node *tmp = redir;
5476                 do {
5477                         sv_pos++;
5478 #if BASH_REDIR_OUTPUT
5479                         if (tmp->nfile.type == NTO2)
5480                                 sv_pos++;
5481 #endif
5482                         tmp = tmp->nfile.next;
5483                 } while (tmp);
5484                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5485                 sv->next = redirlist;
5486                 sv->pair_count = sv_pos;
5487                 redirlist = sv;
5488                 while (sv_pos > 0) {
5489                         sv_pos--;
5490                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5491                 }
5492         }
5493
5494         do {
5495                 int right_fd = -1;
5496                 fd = redir->nfile.fd;
5497                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5498                         right_fd = redir->ndup.dupfd;
5499                         //bb_error_msg("doing %d > %d", fd, right_fd);
5500                         /* redirect from/to same file descriptor? */
5501                         if (right_fd == fd)
5502                                 continue;
5503                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5504                         if (is_hidden_fd(sv, right_fd)) {
5505                                 errno = EBADF; /* as if it is closed */
5506                                 ash_msg_and_raise_error("%d: %m", right_fd);
5507                         }
5508                         newfd = -1;
5509                 } else {
5510                         newfd = openredirect(redir); /* always >= 0 */
5511                         if (fd == newfd) {
5512                                 /* Descriptor wasn't open before redirect.
5513                                  * Mark it for close in the future */
5514                                 if (need_to_remember(sv, fd)) {
5515                                         goto remember_to_close;
5516                                 }
5517                                 continue;
5518                         }
5519                 }
5520 #if BASH_REDIR_OUTPUT
5521  redirect_more:
5522 #endif
5523                 if (need_to_remember(sv, fd)) {
5524                         /* Copy old descriptor */
5525                         /* Careful to not accidentally "save"
5526                          * to the same fd as right side fd in N>&M */
5527                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5528 #if defined(F_DUPFD_CLOEXEC)
5529                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5530 #else
5531                         i = fcntl(fd, F_DUPFD, minfd);
5532 #endif
5533                         if (i == -1) {
5534                                 i = errno;
5535                                 if (i != EBADF) {
5536                                         /* Strange error (e.g. "too many files" EMFILE?) */
5537                                         if (newfd >= 0)
5538                                                 close(newfd);
5539                                         errno = i;
5540                                         ash_msg_and_raise_error("%d: %m", fd);
5541                                         /* NOTREACHED */
5542                                 }
5543                                 /* EBADF: it is not open - good, remember to close it */
5544  remember_to_close:
5545                                 i = CLOSED;
5546                         } else { /* fd is open, save its copy */
5547 #if !defined(F_DUPFD_CLOEXEC)
5548                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5549 #endif
5550                                 /* "exec fd>&-" should not close fds
5551                                  * which point to script file(s).
5552                                  * Force them to be restored afterwards */
5553                                 if (is_hidden_fd(sv, fd))
5554                                         i |= COPYFD_RESTORE;
5555                         }
5556                         if (fd == 2)
5557                                 copied_fd2 = i;
5558                         sv->two_fd[sv_pos].orig = fd;
5559                         sv->two_fd[sv_pos].copy = i;
5560                         sv_pos++;
5561                 }
5562                 if (newfd < 0) {
5563                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5564                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5565                                 /* Don't want to trigger debugging */
5566                                 if (fd != -1)
5567                                         close(fd);
5568                         } else {
5569                                 dup2_or_raise(redir->ndup.dupfd, fd);
5570                         }
5571                 } else if (fd != newfd) { /* move newfd to fd */
5572                         dup2_or_raise(newfd, fd);
5573 #if BASH_REDIR_OUTPUT
5574                         if (!(redir->nfile.type == NTO2 && fd == 2))
5575 #endif
5576                                 close(newfd);
5577                 }
5578 #if BASH_REDIR_OUTPUT
5579                 if (redir->nfile.type == NTO2 && fd == 1) {
5580                         /* We already redirected it to fd 1, now copy it to 2 */
5581                         newfd = 1;
5582                         fd = 2;
5583                         goto redirect_more;
5584                 }
5585 #endif
5586         } while ((redir = redir->nfile.next) != NULL);
5587
5588         INT_ON;
5589         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5590                 preverrout_fd = copied_fd2;
5591 }
5592
5593 /*
5594  * Undo the effects of the last redirection.
5595  */
5596 static void
5597 popredir(int drop, int restore)
5598 {
5599         struct redirtab *rp;
5600         int i;
5601
5602         if (redirlist == NULL)
5603                 return;
5604         INT_OFF;
5605         rp = redirlist;
5606         for (i = 0; i < rp->pair_count; i++) {
5607                 int fd = rp->two_fd[i].orig;
5608                 int copy = rp->two_fd[i].copy;
5609                 if (copy == CLOSED) {
5610                         if (!drop)
5611                                 close(fd);
5612                         continue;
5613                 }
5614                 if (copy != EMPTY) {
5615                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5616                                 copy &= ~COPYFD_RESTORE;
5617                                 /*close(fd);*/
5618                                 dup2_or_raise(copy, fd);
5619                         }
5620                         close(copy & ~COPYFD_RESTORE);
5621                 }
5622         }
5623         redirlist = rp->next;
5624         free(rp);
5625         INT_ON;
5626 }
5627
5628 /*
5629  * Undo all redirections.  Called on error or interrupt.
5630  */
5631
5632 static int
5633 redirectsafe(union node *redir, int flags)
5634 {
5635         int err;
5636         volatile int saveint;
5637         struct jmploc *volatile savehandler = exception_handler;
5638         struct jmploc jmploc;
5639
5640         SAVE_INT(saveint);
5641         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5642         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5643         if (!err) {
5644                 exception_handler = &jmploc;
5645                 redirect(redir, flags);
5646         }
5647         exception_handler = savehandler;
5648         if (err && exception_type != EXERROR)
5649                 longjmp(exception_handler->loc, 1);
5650         RESTORE_INT(saveint);
5651         return err;
5652 }
5653
5654
5655 /* ============ Routines to expand arguments to commands
5656  *
5657  * We have to deal with backquotes, shell variables, and file metacharacters.
5658  */
5659
5660 #if ENABLE_FEATURE_SH_MATH
5661 static arith_t
5662 ash_arith(const char *s)
5663 {
5664         arith_state_t math_state;
5665         arith_t result;
5666
5667         math_state.lookupvar = lookupvar;
5668         math_state.setvar    = setvar0;
5669         //math_state.endofname = endofname;
5670
5671         INT_OFF;
5672         result = arith(&math_state, s);
5673         if (math_state.errmsg)
5674                 ash_msg_and_raise_error(math_state.errmsg);
5675         INT_ON;
5676
5677         return result;
5678 }
5679 #endif
5680
5681 /*
5682  * expandarg flags
5683  */
5684 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5685 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5686 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5687 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5688 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5689  * POSIX says for this case:
5690  *  Pathname expansion shall not be performed on the word by a
5691  *  non-interactive shell; an interactive shell may perform it, but shall
5692  *  do so only when the expansion would result in one word.
5693  * Currently, our code complies to the above rule by never globbing
5694  * redirection filenames.
5695  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5696  * (this means that on a typical Linux distro, bash almost always
5697  * performs globbing, and thus diverges from what we do).
5698  */
5699 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5700 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5701 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5702 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5703 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5704 /*
5705  * rmescape() flags
5706  */
5707 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5708 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5709 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5710 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5711 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5712
5713 /* Add CTLESC when necessary. */
5714 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5715 /* Do not skip NUL characters. */
5716 #define QUOTES_KEEPNUL EXP_TILDE
5717
5718 /*
5719  * Structure specifying which parts of the string should be searched
5720  * for IFS characters.
5721  */
5722 struct ifsregion {
5723         struct ifsregion *next; /* next region in list */
5724         int begoff;             /* offset of start of region */
5725         int endoff;             /* offset of end of region */
5726         int nulonly;            /* search for nul bytes only */
5727 };
5728
5729 struct arglist {
5730         struct strlist *list;
5731         struct strlist **lastp;
5732 };
5733
5734 /* output of current string */
5735 static char *expdest;
5736 /* list of back quote expressions */
5737 static struct nodelist *argbackq;
5738 /* first struct in list of ifs regions */
5739 static struct ifsregion ifsfirst;
5740 /* last struct in list */
5741 static struct ifsregion *ifslastp;
5742 /* holds expanded arg list */
5743 static struct arglist exparg;
5744
5745 /*
5746  * Our own itoa().
5747  */
5748 #if !ENABLE_FEATURE_SH_MATH
5749 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5750 typedef long arith_t;
5751 # define ARITH_FMT "%ld"
5752 #endif
5753 static int
5754 cvtnum(arith_t num)
5755 {
5756         int len;
5757
5758         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5759         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5760         STADJUST(len, expdest);
5761         return len;
5762 }
5763
5764 /*
5765  * Break the argument string into pieces based upon IFS and add the
5766  * strings to the argument list.  The regions of the string to be
5767  * searched for IFS characters have been stored by recordregion.
5768  */
5769 static void
5770 ifsbreakup(char *string, struct arglist *arglist)
5771 {
5772         struct ifsregion *ifsp;
5773         struct strlist *sp;
5774         char *start;
5775         char *p;
5776         char *q;
5777         const char *ifs, *realifs;
5778         int ifsspc;
5779         int nulonly;
5780
5781         start = string;
5782         if (ifslastp != NULL) {
5783                 ifsspc = 0;
5784                 nulonly = 0;
5785                 realifs = ifsset() ? ifsval() : defifs;
5786                 ifsp = &ifsfirst;
5787                 do {
5788                         p = string + ifsp->begoff;
5789                         nulonly = ifsp->nulonly;
5790                         ifs = nulonly ? nullstr : realifs;
5791                         ifsspc = 0;
5792                         while (p < string + ifsp->endoff) {
5793                                 q = p;
5794                                 if ((unsigned char)*p == CTLESC)
5795                                         p++;
5796                                 if (!strchr(ifs, *p)) {
5797                                         p++;
5798                                         continue;
5799                                 }
5800                                 if (!nulonly)
5801                                         ifsspc = (strchr(defifs, *p) != NULL);
5802                                 /* Ignore IFS whitespace at start */
5803                                 if (q == start && ifsspc) {
5804                                         p++;
5805                                         start = p;
5806                                         continue;
5807                                 }
5808                                 *q = '\0';
5809                                 sp = stzalloc(sizeof(*sp));
5810                                 sp->text = start;
5811                                 *arglist->lastp = sp;
5812                                 arglist->lastp = &sp->next;
5813                                 p++;
5814                                 if (!nulonly) {
5815                                         for (;;) {
5816                                                 if (p >= string + ifsp->endoff) {
5817                                                         break;
5818                                                 }
5819                                                 q = p;
5820                                                 if ((unsigned char)*p == CTLESC)
5821                                                         p++;
5822                                                 if (strchr(ifs, *p) == NULL) {
5823                                                         p = q;
5824                                                         break;
5825                                                 }
5826                                                 if (strchr(defifs, *p) == NULL) {
5827                                                         if (ifsspc) {
5828                                                                 p++;
5829                                                                 ifsspc = 0;
5830                                                         } else {
5831                                                                 p = q;
5832                                                                 break;
5833                                                         }
5834                                                 } else
5835                                                         p++;
5836                                         }
5837                                 }
5838                                 start = p;
5839                         } /* while */
5840                         ifsp = ifsp->next;
5841                 } while (ifsp != NULL);
5842                 if (nulonly)
5843                         goto add;
5844         }
5845
5846         if (!*start)
5847                 return;
5848
5849  add:
5850         sp = stzalloc(sizeof(*sp));
5851         sp->text = start;
5852         *arglist->lastp = sp;
5853         arglist->lastp = &sp->next;
5854 }
5855
5856 static void
5857 ifsfree(void)
5858 {
5859         struct ifsregion *p = ifsfirst.next;
5860
5861         if (!p)
5862                 goto out;
5863
5864         INT_OFF;
5865         do {
5866                 struct ifsregion *ifsp;
5867                 ifsp = p->next;
5868                 free(p);
5869                 p = ifsp;
5870         } while (p);
5871         ifsfirst.next = NULL;
5872         INT_ON;
5873  out:
5874         ifslastp = NULL;
5875 }
5876
5877 static size_t
5878 esclen(const char *start, const char *p)
5879 {
5880         size_t esc = 0;
5881
5882         while (p > start && (unsigned char)*--p == CTLESC) {
5883                 esc++;
5884         }
5885         return esc;
5886 }
5887
5888 /*
5889  * Remove any CTLESC characters from a string.
5890  */
5891 static char *
5892 rmescapes(char *str, int flag)
5893 {
5894         static const char qchars[] ALIGN1 = {
5895                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5896
5897         char *p, *q, *r;
5898         unsigned inquotes;
5899         unsigned protect_against_glob;
5900         unsigned globbing;
5901         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5902
5903         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5904         if (!p)
5905                 return str;
5906
5907         q = p;
5908         r = str;
5909         if (flag & RMESCAPE_ALLOC) {
5910                 size_t len = p - str;
5911                 size_t fulllen = len + strlen(p) + 1;
5912
5913                 if (flag & RMESCAPE_GROW) {
5914                         int strloc = str - (char *)stackblock();
5915                         r = makestrspace(fulllen, expdest);
5916                         /* p and str may be invalidated by makestrspace */
5917                         str = (char *)stackblock() + strloc;
5918                         p = str + len;
5919                 } else if (flag & RMESCAPE_HEAP) {
5920                         r = ckmalloc(fulllen);
5921                 } else {
5922                         r = stalloc(fulllen);
5923                 }
5924                 q = r;
5925                 if (len > 0) {
5926                         q = (char *)mempcpy(q, str, len);
5927                 }
5928         }
5929
5930         inquotes = 0;
5931         globbing = flag & RMESCAPE_GLOB;
5932         protect_against_glob = globbing;
5933         while (*p) {
5934                 if ((unsigned char)*p == CTLQUOTEMARK) {
5935 // Note: both inquotes and protect_against_glob only affect whether
5936 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5937                         inquotes = ~inquotes;
5938                         p++;
5939                         protect_against_glob = globbing;
5940                         continue;
5941                 }
5942                 if ((unsigned char)*p == CTLESC) {
5943                         p++;
5944 #if DEBUG
5945                         if (*p == '\0')
5946                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5947 #endif
5948                         if (protect_against_glob) {
5949                                 /*
5950                                  * We used to trust glob() and fnmatch() to eat
5951                                  * superfluous escapes (\z where z has no
5952                                  * special meaning anyway). But this causes
5953                                  * bugs such as string of one greek letter rho
5954                                  * (unicode-encoded as two bytes "cf,81")
5955                                  * getting encoded as "cf,CTLESC,81"
5956                                  * and here, converted to "cf,\,81" -
5957                                  * which does not go well with some flavors
5958                                  * of fnmatch() in unicode locales
5959                                  * (for example, glibc <= 2.22).
5960                                  *
5961                                  * Lets add "\" only on the chars which need it.
5962                                  * Testcases for less obvious chars are shown.
5963                                  */
5964                                 if (*p == '*'
5965                                  || *p == '?'
5966                                  || *p == '['
5967                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5968                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5969                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5970                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5971                                 /* Some libc support [^negate], that's why "^" also needs love */
5972                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5973                                 ) {
5974                                         *q++ = '\\';
5975                                 }
5976                         }
5977                 } else if (*p == '\\' && !inquotes) {
5978                         /* naked back slash */
5979                         protect_against_glob = 0;
5980                         goto copy;
5981                 }
5982 #if BASH_PATTERN_SUBST
5983                 else if (*p == '/' && slash) {
5984                         /* stop handling globbing and mark location of slash */
5985                         globbing = slash = 0;
5986                         *p = CTLESC;
5987                 }
5988 #endif
5989                 protect_against_glob = globbing;
5990  copy:
5991                 *q++ = *p++;
5992         }
5993         *q = '\0';
5994         if (flag & RMESCAPE_GROW) {
5995                 expdest = r;
5996                 STADJUST(q - r + 1, expdest);
5997         }
5998         return r;
5999 }
6000 #define pmatch(a, b) !fnmatch((a), (b), 0)
6001
6002 /*
6003  * Prepare a pattern for a expmeta (internal glob(3)) call.
6004  *
6005  * Returns an stalloced string.
6006  */
6007 static char *
6008 preglob(const char *pattern, int flag)
6009 {
6010         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6011 }
6012
6013 /*
6014  * Put a string on the stack.
6015  */
6016 static void
6017 memtodest(const char *p, size_t len, int syntax, int quotes)
6018 {
6019         char *q;
6020
6021         if (!len)
6022                 return;
6023
6024         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6025
6026         do {
6027                 unsigned char c = *p++;
6028                 if (c) {
6029                         if (quotes & QUOTES_ESC) {
6030                                 int n = SIT(c, syntax);
6031                                 if (n == CCTL
6032                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6033                                      && n == CBACK
6034                                     )
6035                                 ) {
6036                                         USTPUTC(CTLESC, q);
6037                                 }
6038                         }
6039                 } else if (!(quotes & QUOTES_KEEPNUL))
6040                         continue;
6041                 USTPUTC(c, q);
6042         } while (--len);
6043
6044         expdest = q;
6045 }
6046
6047 static size_t
6048 strtodest(const char *p, int syntax, int quotes)
6049 {
6050         size_t len = strlen(p);
6051         memtodest(p, len, syntax, quotes);
6052         return len;
6053 }
6054
6055 /*
6056  * Record the fact that we have to scan this region of the
6057  * string for IFS characters.
6058  */
6059 static void
6060 recordregion(int start, int end, int nulonly)
6061 {
6062         struct ifsregion *ifsp;
6063
6064         if (ifslastp == NULL) {
6065                 ifsp = &ifsfirst;
6066         } else {
6067                 INT_OFF;
6068                 ifsp = ckzalloc(sizeof(*ifsp));
6069                 /*ifsp->next = NULL; - ckzalloc did it */
6070                 ifslastp->next = ifsp;
6071                 INT_ON;
6072         }
6073         ifslastp = ifsp;
6074         ifslastp->begoff = start;
6075         ifslastp->endoff = end;
6076         ifslastp->nulonly = nulonly;
6077 }
6078
6079 static void
6080 removerecordregions(int endoff)
6081 {
6082         if (ifslastp == NULL)
6083                 return;
6084
6085         if (ifsfirst.endoff > endoff) {
6086                 while (ifsfirst.next) {
6087                         struct ifsregion *ifsp;
6088                         INT_OFF;
6089                         ifsp = ifsfirst.next->next;
6090                         free(ifsfirst.next);
6091                         ifsfirst.next = ifsp;
6092                         INT_ON;
6093                 }
6094                 if (ifsfirst.begoff > endoff) {
6095                         ifslastp = NULL;
6096                 } else {
6097                         ifslastp = &ifsfirst;
6098                         ifsfirst.endoff = endoff;
6099                 }
6100                 return;
6101         }
6102
6103         ifslastp = &ifsfirst;
6104         while (ifslastp->next && ifslastp->next->begoff < endoff)
6105                 ifslastp = ifslastp->next;
6106         while (ifslastp->next) {
6107                 struct ifsregion *ifsp;
6108                 INT_OFF;
6109                 ifsp = ifslastp->next->next;
6110                 free(ifslastp->next);
6111                 ifslastp->next = ifsp;
6112                 INT_ON;
6113         }
6114         if (ifslastp->endoff > endoff)
6115                 ifslastp->endoff = endoff;
6116 }
6117
6118 static char *
6119 exptilde(char *startp, char *p, int flags)
6120 {
6121         unsigned char c;
6122         char *name;
6123         struct passwd *pw;
6124         const char *home;
6125         int quotes = flags & QUOTES_ESC;
6126
6127         name = p + 1;
6128
6129         while ((c = *++p) != '\0') {
6130                 switch (c) {
6131                 case CTLESC:
6132                         return startp;
6133                 case CTLQUOTEMARK:
6134                         return startp;
6135                 case ':':
6136                         if (flags & EXP_VARTILDE)
6137                                 goto done;
6138                         break;
6139                 case '/':
6140                 case CTLENDVAR:
6141                         goto done;
6142                 }
6143         }
6144  done:
6145         *p = '\0';
6146         if (*name == '\0') {
6147                 home = lookupvar("HOME");
6148         } else {
6149                 pw = getpwnam(name);
6150                 if (pw == NULL)
6151                         goto lose;
6152                 home = pw->pw_dir;
6153         }
6154         if (!home || !*home)
6155                 goto lose;
6156         *p = c;
6157         strtodest(home, SQSYNTAX, quotes);
6158         return p;
6159  lose:
6160         *p = c;
6161         return startp;
6162 }
6163
6164 /*
6165  * Execute a command inside back quotes.  If it's a builtin command, we
6166  * want to save its output in a block obtained from malloc.  Otherwise
6167  * we fork off a subprocess and get the output of the command via a pipe.
6168  * Should be called with interrupts off.
6169  */
6170 struct backcmd {                /* result of evalbackcmd */
6171         int fd;                 /* file descriptor to read from */
6172         int nleft;              /* number of chars in buffer */
6173         char *buf;              /* buffer */
6174         struct job *jp;         /* job structure for command */
6175 };
6176
6177 /* These forward decls are needed to use "eval" code for backticks handling: */
6178 #define EV_EXIT 01              /* exit after evaluating tree */
6179 static int evaltree(union node *, int);
6180
6181 static void FAST_FUNC
6182 evalbackcmd(union node *n, struct backcmd *result)
6183 {
6184         int pip[2];
6185         struct job *jp;
6186
6187         result->fd = -1;
6188         result->buf = NULL;
6189         result->nleft = 0;
6190         result->jp = NULL;
6191         if (n == NULL) {
6192                 goto out;
6193         }
6194
6195         if (pipe(pip) < 0)
6196                 ash_msg_and_raise_error("pipe call failed");
6197         jp = makejob(/*n,*/ 1);
6198         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6199                 /* child */
6200                 FORCE_INT_ON;
6201                 close(pip[0]);
6202                 if (pip[1] != 1) {
6203                         /*close(1);*/
6204                         dup2_or_raise(pip[1], 1);
6205                         close(pip[1]);
6206                 }
6207 /* TODO: eflag clearing makes the following not abort:
6208  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6209  * which is what bash does (unless it is in POSIX mode).
6210  * dash deleted "eflag = 0" line in the commit
6211  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6212  *  [EVAL] Don't clear eflag in evalbackcmd
6213  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6214  */
6215                 eflag = 0;
6216                 ifsfree();
6217                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6218                 /* NOTREACHED */
6219         }
6220         /* parent */
6221         close(pip[1]);
6222         result->fd = pip[0];
6223         result->jp = jp;
6224
6225  out:
6226         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6227                 result->fd, result->buf, result->nleft, result->jp));
6228 }
6229
6230 /*
6231  * Expand stuff in backwards quotes.
6232  */
6233 static void
6234 expbackq(union node *cmd, int flag)
6235 {
6236         struct backcmd in;
6237         int i;
6238         char buf[128];
6239         char *p;
6240         char *dest;
6241         int startloc;
6242         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6243         struct stackmark smark;
6244
6245         INT_OFF;
6246         startloc = expdest - (char *)stackblock();
6247         pushstackmark(&smark, startloc);
6248         evalbackcmd(cmd, &in);
6249         popstackmark(&smark);
6250
6251         p = in.buf;
6252         i = in.nleft;
6253         if (i == 0)
6254                 goto read;
6255         for (;;) {
6256                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6257  read:
6258                 if (in.fd < 0)
6259                         break;
6260                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6261                 TRACE(("expbackq: read returns %d\n", i));
6262                 if (i <= 0)
6263                         break;
6264                 p = buf;
6265         }
6266
6267         free(in.buf);
6268         if (in.fd >= 0) {
6269                 close(in.fd);
6270                 back_exitstatus = waitforjob(in.jp);
6271         }
6272         INT_ON;
6273
6274         /* Eat all trailing newlines */
6275         dest = expdest;
6276         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6277                 STUNPUTC(dest);
6278         expdest = dest;
6279
6280         if (!(flag & EXP_QUOTED))
6281                 recordregion(startloc, dest - (char *)stackblock(), 0);
6282         TRACE(("evalbackq: size:%d:'%.*s'\n",
6283                 (int)((dest - (char *)stackblock()) - startloc),
6284                 (int)((dest - (char *)stackblock()) - startloc),
6285                 stackblock() + startloc));
6286 }
6287
6288 #if ENABLE_FEATURE_SH_MATH
6289 /*
6290  * Expand arithmetic expression.  Backup to start of expression,
6291  * evaluate, place result in (backed up) result, adjust string position.
6292  */
6293 static void
6294 expari(int flag)
6295 {
6296         char *p, *start;
6297         int begoff;
6298         int len;
6299
6300         /* ifsfree(); */
6301
6302         /*
6303          * This routine is slightly over-complicated for
6304          * efficiency.  Next we scan backwards looking for the
6305          * start of arithmetic.
6306          */
6307         start = stackblock();
6308         p = expdest - 1;
6309         *p = '\0';
6310         p--;
6311         while (1) {
6312                 int esc;
6313
6314                 while ((unsigned char)*p != CTLARI) {
6315                         p--;
6316 #if DEBUG
6317                         if (p < start) {
6318                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6319                         }
6320 #endif
6321                 }
6322
6323                 esc = esclen(start, p);
6324                 if (!(esc % 2)) {
6325                         break;
6326                 }
6327
6328                 p -= esc + 1;
6329         }
6330
6331         begoff = p - start;
6332
6333         removerecordregions(begoff);
6334
6335         expdest = p;
6336
6337         if (flag & QUOTES_ESC)
6338                 rmescapes(p + 1, 0);
6339
6340         len = cvtnum(ash_arith(p + 1));
6341
6342         if (!(flag & EXP_QUOTED))
6343                 recordregion(begoff, begoff + len, 0);
6344 }
6345 #endif
6346
6347 /* argstr needs it */
6348 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6349
6350 /*
6351  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6352  * characters to allow for further processing.  Otherwise treat
6353  * $@ like $* since no splitting will be performed.
6354  *
6355  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6356  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6357  * for correct expansion of "B=$A" word.
6358  */
6359 static void
6360 argstr(char *p, int flags, struct strlist *var_str_list)
6361 {
6362         static const char spclchars[] ALIGN1 = {
6363                 '=',
6364                 ':',
6365                 CTLQUOTEMARK,
6366                 CTLENDVAR,
6367                 CTLESC,
6368                 CTLVAR,
6369                 CTLBACKQ,
6370 #if ENABLE_FEATURE_SH_MATH
6371                 CTLENDARI,
6372 #endif
6373                 '\0'
6374         };
6375         const char *reject = spclchars;
6376         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6377         int inquotes;
6378         size_t length;
6379         int startloc;
6380
6381         if (!(flags & EXP_VARTILDE)) {
6382                 reject += 2;
6383         } else if (flags & EXP_VARTILDE2) {
6384                 reject++;
6385         }
6386         inquotes = 0;
6387         length = 0;
6388         if (flags & EXP_TILDE) {
6389                 char *q;
6390
6391                 flags &= ~EXP_TILDE;
6392  tilde:
6393                 q = p;
6394                 if (*q == '~')
6395                         p = exptilde(p, q, flags);
6396         }
6397  start:
6398         startloc = expdest - (char *)stackblock();
6399         for (;;) {
6400                 unsigned char c;
6401
6402                 length += strcspn(p + length, reject);
6403                 c = p[length];
6404                 if (c) {
6405                         if (!(c & 0x80)
6406                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6407                         ) {
6408                                 /* c == '=' || c == ':' || c == CTLENDARI */
6409                                 length++;
6410                         }
6411                 }
6412                 if (length > 0) {
6413                         int newloc;
6414                         expdest = stack_nputstr(p, length, expdest);
6415                         newloc = expdest - (char *)stackblock();
6416                         if (breakall && !inquotes && newloc > startloc) {
6417                                 recordregion(startloc, newloc, 0);
6418                         }
6419                         startloc = newloc;
6420                 }
6421                 p += length + 1;
6422                 length = 0;
6423
6424                 switch (c) {
6425                 case '\0':
6426                         goto breakloop;
6427                 case '=':
6428                         if (flags & EXP_VARTILDE2) {
6429                                 p--;
6430                                 continue;
6431                         }
6432                         flags |= EXP_VARTILDE2;
6433                         reject++;
6434                         /* fall through */
6435                 case ':':
6436                         /*
6437                          * sort of a hack - expand tildes in variable
6438                          * assignments (after the first '=' and after ':'s).
6439                          */
6440                         if (*--p == '~') {
6441                                 goto tilde;
6442                         }
6443                         continue;
6444                 }
6445
6446                 switch (c) {
6447                 case CTLENDVAR: /* ??? */
6448                         goto breakloop;
6449                 case CTLQUOTEMARK:
6450                         inquotes ^= EXP_QUOTED;
6451                         /* "$@" syntax adherence hack */
6452                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6453                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6454                                 goto start;
6455                         }
6456  addquote:
6457                         if (flags & QUOTES_ESC) {
6458                                 p--;
6459                                 length++;
6460                                 startloc++;
6461                         }
6462                         break;
6463                 case CTLESC:
6464                         startloc++;
6465                         length++;
6466
6467                         /*
6468                          * Quoted parameter expansion pattern: remove quote
6469                          * unless inside inner quotes or we have a literal
6470                          * backslash.
6471                          */
6472                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6473                             EXP_QPAT && *p != '\\')
6474                                 break;
6475
6476                         goto addquote;
6477                 case CTLVAR:
6478                         TRACE(("argstr: evalvar('%s')\n", p));
6479                         p = evalvar(p, flags | inquotes, var_str_list);
6480                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6481                         goto start;
6482                 case CTLBACKQ:
6483                         expbackq(argbackq->n, flags | inquotes);
6484                         argbackq = argbackq->next;
6485                         goto start;
6486 #if ENABLE_FEATURE_SH_MATH
6487                 case CTLENDARI:
6488                         p--;
6489                         expari(flags | inquotes);
6490                         goto start;
6491 #endif
6492                 }
6493         }
6494  breakloop: ;
6495 }
6496
6497 static char *
6498 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6499                 char *pattern, int quotes, int zero)
6500 {
6501         char *loc, *loc2;
6502         char c;
6503
6504         loc = startp;
6505         loc2 = rmesc;
6506         do {
6507                 int match;
6508                 const char *s = loc2;
6509
6510                 c = *loc2;
6511                 if (zero) {
6512                         *loc2 = '\0';
6513                         s = rmesc;
6514                 }
6515                 match = pmatch(pattern, s);
6516
6517                 *loc2 = c;
6518                 if (match)
6519                         return loc;
6520                 if (quotes && (unsigned char)*loc == CTLESC)
6521                         loc++;
6522                 loc++;
6523                 loc2++;
6524         } while (c);
6525         return NULL;
6526 }
6527
6528 static char *
6529 scanright(char *startp, char *rmesc, char *rmescend,
6530                 char *pattern, int quotes, int match_at_start)
6531 {
6532 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6533         int try2optimize = match_at_start;
6534 #endif
6535         int esc = 0;
6536         char *loc;
6537         char *loc2;
6538
6539         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6540          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6541          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6542          * Logic:
6543          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6544          * and on each iteration they go back two/one char until they reach the beginning.
6545          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6546          */
6547         /* TODO: document in what other circumstances we are called. */
6548
6549         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6550                 int match;
6551                 char c = *loc2;
6552                 const char *s = loc2;
6553                 if (match_at_start) {
6554                         *loc2 = '\0';
6555                         s = rmesc;
6556                 }
6557                 match = pmatch(pattern, s);
6558                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6559                 *loc2 = c;
6560                 if (match)
6561                         return loc;
6562 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6563                 if (try2optimize) {
6564                         /* Maybe we can optimize this:
6565                          * if pattern ends with unescaped *, we can avoid checking
6566                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6567                          * it won't match truncated "raw_value_of_" strings too.
6568                          */
6569                         unsigned plen = strlen(pattern);
6570                         /* Does it end with "*"? */
6571                         if (plen != 0 && pattern[--plen] == '*') {
6572                                 /* "xxxx*" is not escaped */
6573                                 /* "xxx\*" is escaped */
6574                                 /* "xx\\*" is not escaped */
6575                                 /* "x\\\*" is escaped */
6576                                 int slashes = 0;
6577                                 while (plen != 0 && pattern[--plen] == '\\')
6578                                         slashes++;
6579                                 if (!(slashes & 1))
6580                                         break; /* ends with unescaped "*" */
6581                         }
6582                         try2optimize = 0;
6583                 }
6584 #endif
6585                 loc--;
6586                 if (quotes) {
6587                         if (--esc < 0) {
6588                                 esc = esclen(startp, loc);
6589                         }
6590                         if (esc % 2) {
6591                                 esc--;
6592                                 loc--;
6593                         }
6594                 }
6595         }
6596         return NULL;
6597 }
6598
6599 static void varunset(const char *, const char *, const char *, int) NORETURN;
6600 static void
6601 varunset(const char *end, const char *var, const char *umsg, int varflags)
6602 {
6603         const char *msg;
6604         const char *tail;
6605
6606         tail = nullstr;
6607         msg = "parameter not set";
6608         if (umsg) {
6609                 if ((unsigned char)*end == CTLENDVAR) {
6610                         if (varflags & VSNUL)
6611                                 tail = " or null";
6612                 } else {
6613                         msg = umsg;
6614                 }
6615         }
6616         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6617 }
6618
6619 static const char *
6620 subevalvar(char *p, char *varname, int strloc, int subtype,
6621                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6622 {
6623         struct nodelist *saveargbackq = argbackq;
6624         int quotes = flag & QUOTES_ESC;
6625         char *startp;
6626         char *loc;
6627         char *rmesc, *rmescend;
6628         char *str;
6629         int amount, resetloc;
6630         IF_BASH_PATTERN_SUBST(int workloc;)
6631         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6632         int zero;
6633         char *(*scan)(char*, char*, char*, char*, int, int);
6634
6635         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6636         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6637
6638         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6639                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6640                         var_str_list);
6641         STPUTC('\0', expdest);
6642         argbackq = saveargbackq;
6643         startp = (char *)stackblock() + startloc;
6644
6645         switch (subtype) {
6646         case VSASSIGN:
6647                 setvar0(varname, startp);
6648                 amount = startp - expdest;
6649                 STADJUST(amount, expdest);
6650                 return startp;
6651
6652         case VSQUESTION:
6653                 varunset(p, varname, startp, varflags);
6654                 /* NOTREACHED */
6655
6656 #if BASH_SUBSTR
6657         case VSSUBSTR: {
6658                 int pos, len, orig_len;
6659                 char *colon;
6660
6661                 loc = str = stackblock() + strloc;
6662
6663 # if !ENABLE_FEATURE_SH_MATH
6664 #  define ash_arith number
6665 # endif
6666                 /* Read POS in ${var:POS:LEN} */
6667                 colon = strchr(loc, ':');
6668                 if (colon) *colon = '\0';
6669                 pos = ash_arith(loc);
6670                 if (colon) *colon = ':';
6671
6672                 /* Read LEN in ${var:POS:LEN} */
6673                 len = str - startp - 1;
6674                 /* *loc != '\0', guaranteed by parser */
6675                 if (quotes) {
6676                         char *ptr;
6677
6678                         /* Adjust the length by the number of escapes */
6679                         for (ptr = startp; ptr < (str - 1); ptr++) {
6680                                 if ((unsigned char)*ptr == CTLESC) {
6681                                         len--;
6682                                         ptr++;
6683                                 }
6684                         }
6685                 }
6686                 orig_len = len;
6687                 if (*loc++ == ':') {
6688                         /* ${var::LEN} */
6689                         len = ash_arith(loc);
6690                 } else {
6691                         /* Skip POS in ${var:POS:LEN} */
6692                         len = orig_len;
6693                         while (*loc && *loc != ':') {
6694                                 loc++;
6695                         }
6696                         if (*loc++ == ':') {
6697                                 len = ash_arith(loc);
6698                         }
6699                 }
6700 #  undef ash_arith
6701
6702                 if (pos < 0) {
6703                         /* ${VAR:$((-n)):l} starts n chars from the end */
6704                         pos = orig_len + pos;
6705                 }
6706                 if ((unsigned)pos >= orig_len) {
6707                         /* apart from obvious ${VAR:999999:l},
6708                          * covers ${VAR:$((-9999999)):l} - result is ""
6709                          * (bash compat)
6710                          */
6711                         pos = 0;
6712                         len = 0;
6713                 }
6714                 if (len < 0) {
6715                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6716                         len = (orig_len - pos) + len;
6717                 }
6718                 if ((unsigned)len > (orig_len - pos))
6719                         len = orig_len - pos;
6720
6721                 for (str = startp; pos; str++, pos--) {
6722                         if (quotes && (unsigned char)*str == CTLESC)
6723                                 str++;
6724                 }
6725                 for (loc = startp; len; len--) {
6726                         if (quotes && (unsigned char)*str == CTLESC)
6727                                 *loc++ = *str++;
6728                         *loc++ = *str++;
6729                 }
6730                 *loc = '\0';
6731                 amount = loc - expdest;
6732                 STADJUST(amount, expdest);
6733                 return loc;
6734         }
6735 #endif /* BASH_SUBSTR */
6736         }
6737
6738         resetloc = expdest - (char *)stackblock();
6739
6740 #if BASH_PATTERN_SUBST
6741         /* We'll comeback here if we grow the stack while handling
6742          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6743          * stack will need rebasing, and we'll need to remove our work
6744          * areas each time
6745          */
6746  restart:
6747 #endif
6748
6749         amount = expdest - ((char *)stackblock() + resetloc);
6750         STADJUST(-amount, expdest);
6751         startp = (char *)stackblock() + startloc;
6752
6753         rmesc = startp;
6754         rmescend = (char *)stackblock() + strloc;
6755         if (quotes) {
6756                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6757                 if (rmesc != startp) {
6758                         rmescend = expdest;
6759                         startp = (char *)stackblock() + startloc;
6760                 }
6761         }
6762         rmescend--;
6763         str = (char *)stackblock() + strloc;
6764         /*
6765          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6766          * The result is a_\_z_c (not a\_\_z_c)!
6767          *
6768          * The search pattern and replace string treat backslashes differently!
6769          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6770          * and string.  It's only used on the first call.
6771          */
6772         preglob(str, IF_BASH_PATTERN_SUBST(
6773                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6774                         RMESCAPE_SLASH : ) 0);
6775
6776 #if BASH_PATTERN_SUBST
6777         workloc = expdest - (char *)stackblock();
6778         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6779                 int len;
6780                 char *idx, *end;
6781
6782                 if (!repl) {
6783                         repl = strchr(str, CTLESC);
6784                         if (repl)
6785                                 *repl++ = '\0';
6786                         else
6787                                 repl = nullstr;
6788                 }
6789                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6790
6791                 /* If there's no pattern to match, return the expansion unmolested */
6792                 if (str[0] == '\0')
6793                         return NULL;
6794
6795                 len = 0;
6796                 idx = startp;
6797                 end = str - 1;
6798                 while (idx < end) {
6799  try_to_match:
6800                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6801                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6802                         if (!loc) {
6803                                 /* No match, advance */
6804                                 char *restart_detect = stackblock();
6805  skip_matching:
6806                                 STPUTC(*idx, expdest);
6807                                 if (quotes && (unsigned char)*idx == CTLESC) {
6808                                         idx++;
6809                                         len++;
6810                                         STPUTC(*idx, expdest);
6811                                 }
6812                                 if (stackblock() != restart_detect)
6813                                         goto restart;
6814                                 idx++;
6815                                 len++;
6816                                 rmesc++;
6817                                 /* continue; - prone to quadratic behavior, smarter code: */
6818                                 if (idx >= end)
6819                                         break;
6820                                 if (str[0] == '*') {
6821                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6822                                          * it would never match "ong_string" etc, no point in trying.
6823                                          */
6824                                         goto skip_matching;
6825                                 }
6826                                 goto try_to_match;
6827                         }
6828
6829                         if (subtype == VSREPLACEALL) {
6830                                 while (idx < loc) {
6831                                         if (quotes && (unsigned char)*idx == CTLESC)
6832                                                 idx++;
6833                                         idx++;
6834                                         rmesc++;
6835                                 }
6836                         } else {
6837                                 idx = loc;
6838                         }
6839
6840                         //bb_error_msg("repl:'%s'", repl);
6841                         for (loc = (char*)repl; *loc; loc++) {
6842                                 char *restart_detect = stackblock();
6843                                 if (quotes && *loc == '\\') {
6844                                         STPUTC(CTLESC, expdest);
6845                                         len++;
6846                                 }
6847                                 STPUTC(*loc, expdest);
6848                                 if (stackblock() != restart_detect)
6849                                         goto restart;
6850                                 len++;
6851                         }
6852
6853                         if (subtype == VSREPLACE) {
6854                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6855                                 while (*idx) {
6856                                         char *restart_detect = stackblock();
6857                                         STPUTC(*idx, expdest);
6858                                         if (stackblock() != restart_detect)
6859                                                 goto restart;
6860                                         len++;
6861                                         idx++;
6862                                 }
6863                                 break;
6864                         }
6865                 }
6866
6867                 /* We've put the replaced text into a buffer at workloc, now
6868                  * move it to the right place and adjust the stack.
6869                  */
6870                 STPUTC('\0', expdest);
6871                 startp = (char *)stackblock() + startloc;
6872                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6873                 //bb_error_msg("startp:'%s'", startp);
6874                 amount = expdest - (startp + len);
6875                 STADJUST(-amount, expdest);
6876                 return startp;
6877         }
6878 #endif /* BASH_PATTERN_SUBST */
6879
6880         subtype -= VSTRIMRIGHT;
6881 #if DEBUG
6882         if (subtype < 0 || subtype > 7)
6883                 abort();
6884 #endif
6885         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6886         zero = subtype >> 1;
6887         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6888         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6889
6890         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6891         if (loc) {
6892                 if (zero) {
6893                         memmove(startp, loc, str - loc);
6894                         loc = startp + (str - loc) - 1;
6895                 }
6896                 *loc = '\0';
6897                 amount = loc - expdest;
6898                 STADJUST(amount, expdest);
6899         }
6900         return loc;
6901 }
6902
6903 /*
6904  * Add the value of a specialized variable to the stack string.
6905  * name parameter (examples):
6906  * ash -c 'echo $1'      name:'1='
6907  * ash -c 'echo $qwe'    name:'qwe='
6908  * ash -c 'echo $$'      name:'$='
6909  * ash -c 'echo ${$}'    name:'$='
6910  * ash -c 'echo ${$##q}' name:'$=q'
6911  * ash -c 'echo ${#$}'   name:'$='
6912  * note: examples with bad shell syntax:
6913  * ash -c 'echo ${#$1}'  name:'$=1'
6914  * ash -c 'echo ${#1#}'  name:'1=#'
6915  */
6916 static NOINLINE ssize_t
6917 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6918 {
6919         const char *p;
6920         int num;
6921         int i;
6922         ssize_t len = 0;
6923         int sep;
6924         int quoted = *quotedp;
6925         int subtype = varflags & VSTYPE;
6926         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6927         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6928         int syntax;
6929
6930         sep = (flags & EXP_FULL) << CHAR_BIT;
6931         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6932
6933         switch (*name) {
6934         case '$':
6935                 num = rootpid;
6936                 goto numvar;
6937         case '?':
6938                 num = exitstatus;
6939                 goto numvar;
6940         case '#':
6941                 num = shellparam.nparam;
6942                 goto numvar;
6943         case '!':
6944                 num = backgndpid;
6945                 if (num == 0)
6946                         return -1;
6947  numvar:
6948                 len = cvtnum(num);
6949                 goto check_1char_name;
6950         case '-':
6951                 expdest = makestrspace(NOPTS, expdest);
6952                 for (i = NOPTS - 1; i >= 0; i--) {
6953                         if (optlist[i]) {
6954                                 USTPUTC(optletters(i), expdest);
6955                                 len++;
6956                         }
6957                 }
6958  check_1char_name:
6959 #if 0
6960                 /* handles cases similar to ${#$1} */
6961                 if (name[2] != '\0')
6962                         raise_error_syntax("bad substitution");
6963 #endif
6964                 break;
6965         case '@':
6966                 if (quoted && sep)
6967                         goto param;
6968                 /* fall through */
6969         case '*': {
6970                 char **ap;
6971                 char sepc;
6972
6973                 if (quoted)
6974                         sep = 0;
6975                 sep |= ifsset() ? ifsval()[0] : ' ';
6976  param:
6977                 sepc = sep;
6978                 *quotedp = !sepc;
6979                 ap = shellparam.p;
6980                 if (!ap)
6981                         return -1;
6982                 while ((p = *ap++) != NULL) {
6983                         len += strtodest(p, syntax, quotes);
6984
6985                         if (*ap && sep) {
6986                                 len++;
6987                                 memtodest(&sepc, 1, syntax, quotes);
6988                         }
6989                 }
6990                 break;
6991         } /* case '*' */
6992         case '0':
6993         case '1':
6994         case '2':
6995         case '3':
6996         case '4':
6997         case '5':
6998         case '6':
6999         case '7':
7000         case '8':
7001         case '9':
7002                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7003                 if (num < 0 || num > shellparam.nparam)
7004                         return -1;
7005                 p = num ? shellparam.p[num - 1] : arg0;
7006                 goto value;
7007         default:
7008                 /* NB: name has form "VAR=..." */
7009
7010                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
7011                  * which should be considered before we check variables. */
7012                 if (var_str_list) {
7013                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
7014                         p = NULL;
7015                         do {
7016                                 char *str, *eq;
7017                                 str = var_str_list->text;
7018                                 eq = strchr(str, '=');
7019                                 if (!eq) /* stop at first non-assignment */
7020                                         break;
7021                                 eq++;
7022                                 if (name_len == (unsigned)(eq - str)
7023                                  && strncmp(str, name, name_len) == 0
7024                                 ) {
7025                                         p = eq;
7026                                         /* goto value; - WRONG! */
7027                                         /* think "A=1 A=2 B=$A" */
7028                                 }
7029                                 var_str_list = var_str_list->next;
7030                         } while (var_str_list);
7031                         if (p)
7032                                 goto value;
7033                 }
7034                 p = lookupvar(name);
7035  value:
7036                 if (!p)
7037                         return -1;
7038
7039                 len = strtodest(p, syntax, quotes);
7040 #if ENABLE_UNICODE_SUPPORT
7041                 if (subtype == VSLENGTH && len > 0) {
7042                         reinit_unicode_for_ash();
7043                         if (unicode_status == UNICODE_ON) {
7044                                 STADJUST(-len, expdest);
7045                                 discard = 0;
7046                                 len = unicode_strlen(p);
7047                         }
7048                 }
7049 #endif
7050                 break;
7051         }
7052
7053         if (discard)
7054                 STADJUST(-len, expdest);
7055         return len;
7056 }
7057
7058 /*
7059  * Expand a variable, and return a pointer to the next character in the
7060  * input string.
7061  */
7062 static char *
7063 evalvar(char *p, int flag, struct strlist *var_str_list)
7064 {
7065         char varflags;
7066         char subtype;
7067         int quoted;
7068         char easy;
7069         char *var;
7070         int patloc;
7071         int startloc;
7072         ssize_t varlen;
7073
7074         varflags = (unsigned char) *p++;
7075         subtype = varflags & VSTYPE;
7076
7077         if (!subtype)
7078                 raise_error_syntax("bad substitution");
7079
7080         quoted = flag & EXP_QUOTED;
7081         var = p;
7082         easy = (!quoted || (*var == '@' && shellparam.nparam));
7083         startloc = expdest - (char *)stackblock();
7084         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7085
7086  again:
7087         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7088         if (varflags & VSNUL)
7089                 varlen--;
7090
7091         if (subtype == VSPLUS) {
7092                 varlen = -1 - varlen;
7093                 goto vsplus;
7094         }
7095
7096         if (subtype == VSMINUS) {
7097  vsplus:
7098                 if (varlen < 0) {
7099                         argstr(
7100                                 p,
7101                                 flag | EXP_TILDE | EXP_WORD,
7102                                 var_str_list
7103                         );
7104                         goto end;
7105                 }
7106                 goto record;
7107         }
7108
7109         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7110                 if (varlen >= 0)
7111                         goto record;
7112
7113                 subevalvar(p, var, 0, subtype, startloc, varflags,
7114                            flag & ~QUOTES_ESC, var_str_list);
7115                 varflags &= ~VSNUL;
7116                 /*
7117                  * Remove any recorded regions beyond
7118                  * start of variable
7119                  */
7120                 removerecordregions(startloc);
7121                 goto again;
7122         }
7123
7124         if (varlen < 0 && uflag)
7125                 varunset(p, var, 0, 0);
7126
7127         if (subtype == VSLENGTH) {
7128                 cvtnum(varlen > 0 ? varlen : 0);
7129                 goto record;
7130         }
7131
7132         if (subtype == VSNORMAL) {
7133  record:
7134                 if (!easy)
7135                         goto end;
7136                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7137                 goto end;
7138         }
7139
7140 #if DEBUG
7141         switch (subtype) {
7142         case VSTRIMLEFT:
7143         case VSTRIMLEFTMAX:
7144         case VSTRIMRIGHT:
7145         case VSTRIMRIGHTMAX:
7146 #if BASH_SUBSTR
7147         case VSSUBSTR:
7148 #endif
7149 #if BASH_PATTERN_SUBST
7150         case VSREPLACE:
7151         case VSREPLACEALL:
7152 #endif
7153                 break;
7154         default:
7155                 abort();
7156         }
7157 #endif
7158
7159         if (varlen >= 0) {
7160                 /*
7161                  * Terminate the string and start recording the pattern
7162                  * right after it
7163                  */
7164                 STPUTC('\0', expdest);
7165                 patloc = expdest - (char *)stackblock();
7166                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7167                                 startloc, varflags, flag, var_str_list)) {
7168                         int amount = expdest - (
7169                                 (char *)stackblock() + patloc - 1
7170                         );
7171                         STADJUST(-amount, expdest);
7172                 }
7173                 /* Remove any recorded regions beyond start of variable */
7174                 removerecordregions(startloc);
7175                 goto record;
7176         }
7177
7178  end:
7179         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7180                 int nesting = 1;
7181                 for (;;) {
7182                         unsigned char c = *p++;
7183                         if (c == CTLESC)
7184                                 p++;
7185                         else if (c == CTLBACKQ) {
7186                                 if (varlen >= 0)
7187                                         argbackq = argbackq->next;
7188                         } else if (c == CTLVAR) {
7189                                 if ((*p++ & VSTYPE) != VSNORMAL)
7190                                         nesting++;
7191                         } else if (c == CTLENDVAR) {
7192                                 if (--nesting == 0)
7193                                         break;
7194                         }
7195                 }
7196         }
7197         return p;
7198 }
7199
7200 /*
7201  * Add a file name to the list.
7202  */
7203 static void
7204 addfname(const char *name)
7205 {
7206         struct strlist *sp;
7207
7208         sp = stzalloc(sizeof(*sp));
7209         sp->text = sstrdup(name);
7210         *exparg.lastp = sp;
7211         exparg.lastp = &sp->next;
7212 }
7213
7214 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7215 static int
7216 hasmeta(const char *p)
7217 {
7218         static const char chars[] ALIGN1 = {
7219                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7220         };
7221
7222         for (;;) {
7223                 p = strpbrk(p, chars);
7224                 if (!p)
7225                         break;
7226                 switch ((unsigned char) *p) {
7227                 case CTLQUOTEMARK:
7228                         for (;;) {
7229                                 p++;
7230                                 if (*p == CTLQUOTEMARK)
7231                                         break;
7232                                 if (*p == CTLESC)
7233                                         p++;
7234                                 if (*p == '\0') /* huh? */
7235                                         return 0;
7236                         }
7237                         break;
7238                 case '\\':
7239                 case CTLESC:
7240                         p++;
7241                         if (*p == '\0')
7242                                 return 0;
7243                         break;
7244                 case '[':
7245                         if (!strchr(p + 1, ']')) {
7246                                 /* It's not a properly closed [] pattern,
7247                                  * but other metas may follow. Continue checking.
7248                                  * my[file* _is_ globbed by bash
7249                                  * and matches filenames like "my[file1".
7250                                  */
7251                                 break;
7252                         }
7253                         /* fallthrough */
7254                 default:
7255                 /* case '*': */
7256                 /* case '?': */
7257                         return 1;
7258                 }
7259                 p++;
7260         }
7261
7262         return 0;
7263 }
7264
7265 /* If we want to use glob() from libc... */
7266 #if !ENABLE_ASH_INTERNAL_GLOB
7267
7268 /* Add the result of glob() to the list */
7269 static void
7270 addglob(const glob_t *pglob)
7271 {
7272         char **p = pglob->gl_pathv;
7273
7274         do {
7275                 addfname(*p);
7276         } while (*++p);
7277 }
7278 static void
7279 expandmeta(struct strlist *str /*, int flag*/)
7280 {
7281         /* TODO - EXP_REDIR */
7282
7283         while (str) {
7284                 char *p;
7285                 glob_t pglob;
7286                 int i;
7287
7288                 if (fflag)
7289                         goto nometa;
7290
7291                 if (!hasmeta(str->text))
7292                         goto nometa;
7293
7294                 INT_OFF;
7295                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7296 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7297 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7298 //
7299 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7300 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7301 // Which means you need to unescape the string, right? Not so fast:
7302 // if there _is_ a file named "file\?" (with backslash), it is returned
7303 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7304 // You DON'T KNOW by looking at the result whether you need to unescape it.
7305 //
7306 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7307 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7308 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7309 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7310 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7311 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7312                 i = glob(p, 0, NULL, &pglob);
7313                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7314                 if (p != str->text)
7315                         free(p);
7316                 switch (i) {
7317                 case 0:
7318 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7319                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7320                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7321                                 goto nometa2;
7322 #endif
7323                         addglob(&pglob);
7324                         globfree(&pglob);
7325                         INT_ON;
7326                         break;
7327                 case GLOB_NOMATCH:
7328  //nometa2:
7329                         globfree(&pglob);
7330                         INT_ON;
7331  nometa:
7332                         *exparg.lastp = str;
7333                         rmescapes(str->text, 0);
7334                         exparg.lastp = &str->next;
7335                         break;
7336                 default:        /* GLOB_NOSPACE */
7337                         globfree(&pglob);
7338                         INT_ON;
7339                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7340                 }
7341                 str = str->next;
7342         }
7343 }
7344
7345 #else
7346 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7347
7348 /*
7349  * Do metacharacter (i.e. *, ?, [...]) expansion.
7350  */
7351 static void
7352 expmeta(char *expdir, char *enddir, char *name)
7353 {
7354         char *p;
7355         const char *cp;
7356         char *start;
7357         char *endname;
7358         int metaflag;
7359         struct stat statb;
7360         DIR *dirp;
7361         struct dirent *dp;
7362         int atend;
7363         int matchdot;
7364         int esc;
7365
7366         metaflag = 0;
7367         start = name;
7368         for (p = name; esc = 0, *p; p += esc + 1) {
7369                 if (*p == '*' || *p == '?')
7370                         metaflag = 1;
7371                 else if (*p == '[') {
7372                         char *q = p + 1;
7373                         if (*q == '!')
7374                                 q++;
7375                         for (;;) {
7376                                 if (*q == '\\')
7377                                         q++;
7378                                 if (*q == '/' || *q == '\0')
7379                                         break;
7380                                 if (*++q == ']') {
7381                                         metaflag = 1;
7382                                         break;
7383                                 }
7384                         }
7385                 } else {
7386                         if (*p == '\\')
7387                                 esc++;
7388                         if (p[esc] == '/') {
7389                                 if (metaflag)
7390                                         break;
7391                                 start = p + esc + 1;
7392                         }
7393                 }
7394         }
7395         if (metaflag == 0) {    /* we've reached the end of the file name */
7396                 if (enddir != expdir)
7397                         metaflag++;
7398                 p = name;
7399                 do {
7400                         if (*p == '\\')
7401                                 p++;
7402                         *enddir++ = *p;
7403                 } while (*p++);
7404                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7405                         addfname(expdir);
7406                 return;
7407         }
7408         endname = p;
7409         if (name < start) {
7410                 p = name;
7411                 do {
7412                         if (*p == '\\')
7413                                 p++;
7414                         *enddir++ = *p++;
7415                 } while (p < start);
7416         }
7417         if (enddir == expdir) {
7418                 cp = ".";
7419         } else if (enddir == expdir + 1 && *expdir == '/') {
7420                 cp = "/";
7421         } else {
7422                 cp = expdir;
7423                 enddir[-1] = '\0';
7424         }
7425         dirp = opendir(cp);
7426         if (dirp == NULL)
7427                 return;
7428         if (enddir != expdir)
7429                 enddir[-1] = '/';
7430         if (*endname == 0) {
7431                 atend = 1;
7432         } else {
7433                 atend = 0;
7434                 *endname = '\0';
7435                 endname += esc + 1;
7436         }
7437         matchdot = 0;
7438         p = start;
7439         if (*p == '\\')
7440                 p++;
7441         if (*p == '.')
7442                 matchdot++;
7443         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7444                 if (dp->d_name[0] == '.' && !matchdot)
7445                         continue;
7446                 if (pmatch(start, dp->d_name)) {
7447                         if (atend) {
7448                                 strcpy(enddir, dp->d_name);
7449                                 addfname(expdir);
7450                         } else {
7451                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7452                                         continue;
7453                                 p[-1] = '/';
7454                                 expmeta(expdir, p, endname);
7455                         }
7456                 }
7457         }
7458         closedir(dirp);
7459         if (!atend)
7460                 endname[-esc - 1] = esc ? '\\' : '/';
7461 }
7462
7463 static struct strlist *
7464 msort(struct strlist *list, int len)
7465 {
7466         struct strlist *p, *q = NULL;
7467         struct strlist **lpp;
7468         int half;
7469         int n;
7470
7471         if (len <= 1)
7472                 return list;
7473         half = len >> 1;
7474         p = list;
7475         for (n = half; --n >= 0;) {
7476                 q = p;
7477                 p = p->next;
7478         }
7479         q->next = NULL;                 /* terminate first half of list */
7480         q = msort(list, half);          /* sort first half of list */
7481         p = msort(p, len - half);               /* sort second half */
7482         lpp = &list;
7483         for (;;) {
7484 #if ENABLE_LOCALE_SUPPORT
7485                 if (strcoll(p->text, q->text) < 0)
7486 #else
7487                 if (strcmp(p->text, q->text) < 0)
7488 #endif
7489                                                 {
7490                         *lpp = p;
7491                         lpp = &p->next;
7492                         p = *lpp;
7493                         if (p == NULL) {
7494                                 *lpp = q;
7495                                 break;
7496                         }
7497                 } else {
7498                         *lpp = q;
7499                         lpp = &q->next;
7500                         q = *lpp;
7501                         if (q == NULL) {
7502                                 *lpp = p;
7503                                 break;
7504                         }
7505                 }
7506         }
7507         return list;
7508 }
7509
7510 /*
7511  * Sort the results of file name expansion.  It calculates the number of
7512  * strings to sort and then calls msort (short for merge sort) to do the
7513  * work.
7514  */
7515 static struct strlist *
7516 expsort(struct strlist *str)
7517 {
7518         int len;
7519         struct strlist *sp;
7520
7521         len = 0;
7522         for (sp = str; sp; sp = sp->next)
7523                 len++;
7524         return msort(str, len);
7525 }
7526
7527 static void
7528 expandmeta(struct strlist *str /*, int flag*/)
7529 {
7530         /* TODO - EXP_REDIR */
7531
7532         while (str) {
7533                 char *expdir;
7534                 struct strlist **savelastp;
7535                 struct strlist *sp;
7536                 char *p;
7537
7538                 if (fflag)
7539                         goto nometa;
7540                 if (!hasmeta(str->text))
7541                         goto nometa;
7542                 savelastp = exparg.lastp;
7543
7544                 INT_OFF;
7545                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7546                 {
7547                         int i = strlen(str->text);
7548 //BUGGY estimation of how long expanded name can be
7549                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7550                 }
7551                 expmeta(expdir, expdir, p);
7552                 free(expdir);
7553                 if (p != str->text)
7554                         free(p);
7555                 INT_ON;
7556                 if (exparg.lastp == savelastp) {
7557                         /*
7558                          * no matches
7559                          */
7560  nometa:
7561                         *exparg.lastp = str;
7562                         rmescapes(str->text, 0);
7563                         exparg.lastp = &str->next;
7564                 } else {
7565                         *exparg.lastp = NULL;
7566                         *savelastp = sp = expsort(*savelastp);
7567                         while (sp->next != NULL)
7568                                 sp = sp->next;
7569                         exparg.lastp = &sp->next;
7570                 }
7571                 str = str->next;
7572         }
7573 }
7574 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7575
7576 /*
7577  * Perform variable substitution and command substitution on an argument,
7578  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7579  * perform splitting and file name expansion.  When arglist is NULL, perform
7580  * here document expansion.
7581  */
7582 static void
7583 expandarg(union node *arg, struct arglist *arglist, int flag)
7584 {
7585         struct strlist *sp;
7586         char *p;
7587
7588         argbackq = arg->narg.backquote;
7589         STARTSTACKSTR(expdest);
7590         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7591         argstr(arg->narg.text, flag,
7592                         /* var_str_list: */ arglist ? arglist->list : NULL);
7593         p = _STPUTC('\0', expdest);
7594         expdest = p - 1;
7595         if (arglist == NULL) {
7596                 /* here document expanded */
7597                 goto out;
7598         }
7599         p = grabstackstr(p);
7600         TRACE(("expandarg: p:'%s'\n", p));
7601         exparg.lastp = &exparg.list;
7602         /*
7603          * TODO - EXP_REDIR
7604          */
7605         if (flag & EXP_FULL) {
7606                 ifsbreakup(p, &exparg);
7607                 *exparg.lastp = NULL;
7608                 exparg.lastp = &exparg.list;
7609                 expandmeta(exparg.list /*, flag*/);
7610         } else {
7611                 sp = stzalloc(sizeof(*sp));
7612                 sp->text = p;
7613                 *exparg.lastp = sp;
7614                 exparg.lastp = &sp->next;
7615         }
7616         *exparg.lastp = NULL;
7617         if (exparg.list) {
7618                 *arglist->lastp = exparg.list;
7619                 arglist->lastp = exparg.lastp;
7620         }
7621
7622  out:
7623         ifsfree();
7624 }
7625
7626 /*
7627  * Expand shell variables and backquotes inside a here document.
7628  */
7629 static void
7630 expandhere(union node *arg, int fd)
7631 {
7632         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7633         full_write(fd, stackblock(), expdest - (char *)stackblock());
7634 }
7635
7636 /*
7637  * Returns true if the pattern matches the string.
7638  */
7639 static int
7640 patmatch(char *pattern, const char *string)
7641 {
7642         char *p = preglob(pattern, 0);
7643         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7644         return pmatch(p, string);
7645 }
7646
7647 /*
7648  * See if a pattern matches in a case statement.
7649  */
7650 static int
7651 casematch(union node *pattern, char *val)
7652 {
7653         struct stackmark smark;
7654         int result;
7655
7656         setstackmark(&smark);
7657         argbackq = pattern->narg.backquote;
7658         STARTSTACKSTR(expdest);
7659         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7660                         /* var_str_list: */ NULL);
7661         STACKSTRNUL(expdest);
7662         ifsfree();
7663         result = patmatch(stackblock(), val);
7664         popstackmark(&smark);
7665         return result;
7666 }
7667
7668
7669 /* ============ find_command */
7670
7671 struct builtincmd {
7672         const char *name;
7673         int (*builtin)(int, char **) FAST_FUNC;
7674         /* unsigned flags; */
7675 };
7676 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7677 /* "regular" builtins always take precedence over commands,
7678  * regardless of PATH=....%builtin... position */
7679 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7680 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7681
7682 struct cmdentry {
7683         smallint cmdtype;       /* CMDxxx */
7684         union param {
7685                 int index;
7686                 /* index >= 0 for commands without path (slashes) */
7687                 /* (TODO: what exactly does the value mean? PATH position?) */
7688                 /* index == -1 for commands with slashes */
7689                 /* index == (-2 - applet_no) for NOFORK applets */
7690                 const struct builtincmd *cmd;
7691                 struct funcnode *func;
7692         } u;
7693 };
7694 /* values of cmdtype */
7695 #define CMDUNKNOWN      -1      /* no entry in table for command */
7696 #define CMDNORMAL       0       /* command is an executable program */
7697 #define CMDFUNCTION     1       /* command is a shell function */
7698 #define CMDBUILTIN      2       /* command is a shell builtin */
7699
7700 /* action to find_command() */
7701 #define DO_ERR          0x01    /* prints errors */
7702 #define DO_ABS          0x02    /* checks absolute paths */
7703 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7704 #define DO_ALTPATH      0x08    /* using alternate path */
7705 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7706
7707 static void find_command(char *, struct cmdentry *, int, const char *);
7708
7709
7710 /* ============ Hashing commands */
7711
7712 /*
7713  * When commands are first encountered, they are entered in a hash table.
7714  * This ensures that a full path search will not have to be done for them
7715  * on each invocation.
7716  *
7717  * We should investigate converting to a linear search, even though that
7718  * would make the command name "hash" a misnomer.
7719  */
7720
7721 struct tblentry {
7722         struct tblentry *next;  /* next entry in hash chain */
7723         union param param;      /* definition of builtin function */
7724         smallint cmdtype;       /* CMDxxx */
7725         char rehash;            /* if set, cd done since entry created */
7726         char cmdname[1];        /* name of command */
7727 };
7728
7729 static struct tblentry **cmdtable;
7730 #define INIT_G_cmdtable() do { \
7731         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7732 } while (0)
7733
7734 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7735
7736
7737 static void
7738 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7739 {
7740 #if ENABLE_FEATURE_SH_STANDALONE
7741         if (applet_no >= 0) {
7742                 if (APPLET_IS_NOEXEC(applet_no)) {
7743                         clearenv();
7744                         while (*envp)
7745                                 putenv(*envp++);
7746                         run_applet_no_and_exit(applet_no, cmd, argv);
7747                 }
7748                 /* re-exec ourselves with the new arguments */
7749                 execve(bb_busybox_exec_path, argv, envp);
7750                 /* If they called chroot or otherwise made the binary no longer
7751                  * executable, fall through */
7752         }
7753 #endif
7754
7755  repeat:
7756 #ifdef SYSV
7757         do {
7758                 execve(cmd, argv, envp);
7759         } while (errno == EINTR);
7760 #else
7761         execve(cmd, argv, envp);
7762 #endif
7763         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7764                 /* Run "cmd" as a shell script:
7765                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7766                  * "If the execve() function fails with ENOEXEC, the shell
7767                  * shall execute a command equivalent to having a shell invoked
7768                  * with the command name as its first operand,
7769                  * with any remaining arguments passed to the new shell"
7770                  *
7771                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7772                  * just call ourselves.
7773                  *
7774                  * Note that bash reads ~80 chars of the file, and if it sees
7775                  * a zero byte before it sees newline, it doesn't try to
7776                  * interpret it, but fails with "cannot execute binary file"
7777                  * message and exit code 126. For one, this prevents attempts
7778                  * to interpret foreign ELF binaries as shell scripts.
7779                  */
7780                 argv[0] = cmd;
7781                 cmd = (char*) bb_busybox_exec_path;
7782                 /* NB: this is only possible because all callers of shellexec()
7783                  * ensure that the argv[-1] slot exists!
7784                  */
7785                 argv--;
7786                 argv[0] = (char*) "ash";
7787                 goto repeat;
7788         }
7789 }
7790
7791 /*
7792  * Exec a program.  Never returns.  If you change this routine, you may
7793  * have to change the find_command routine as well.
7794  * argv[-1] must exist and be writable! See tryexec() for why.
7795  */
7796 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7797 static void shellexec(char *prog, char **argv, const char *path, int idx)
7798 {
7799         char *cmdname;
7800         int e;
7801         char **envp;
7802         int exerrno;
7803         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7804
7805         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7806         if (strchr(prog, '/') != NULL
7807 #if ENABLE_FEATURE_SH_STANDALONE
7808          || (applet_no = find_applet_by_name(prog)) >= 0
7809 #endif
7810         ) {
7811                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7812                 if (applet_no >= 0) {
7813                         /* We tried execing ourself, but it didn't work.
7814                          * Maybe /proc/self/exe doesn't exist?
7815                          * Try $PATH search.
7816                          */
7817                         goto try_PATH;
7818                 }
7819                 e = errno;
7820         } else {
7821  try_PATH:
7822                 e = ENOENT;
7823                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7824                         if (--idx < 0 && pathopt == NULL) {
7825                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7826                                 if (errno != ENOENT && errno != ENOTDIR)
7827                                         e = errno;
7828                         }
7829                         stunalloc(cmdname);
7830                 }
7831         }
7832
7833         /* Map to POSIX errors */
7834         switch (e) {
7835         case EACCES:
7836                 exerrno = 126;
7837                 break;
7838         case ENOENT:
7839                 exerrno = 127;
7840                 break;
7841         default:
7842                 exerrno = 2;
7843                 break;
7844         }
7845         exitstatus = exerrno;
7846         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7847                 prog, e, suppress_int));
7848         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7849         /* NOTREACHED */
7850 }
7851
7852 static void
7853 printentry(struct tblentry *cmdp)
7854 {
7855         int idx;
7856         const char *path;
7857         char *name;
7858
7859         idx = cmdp->param.index;
7860         path = pathval();
7861         do {
7862                 name = path_advance(&path, cmdp->cmdname);
7863                 stunalloc(name);
7864         } while (--idx >= 0);
7865         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7866 }
7867
7868 /*
7869  * Clear out command entries.  The argument specifies the first entry in
7870  * PATH which has changed.
7871  */
7872 static void
7873 clearcmdentry(int firstchange)
7874 {
7875         struct tblentry **tblp;
7876         struct tblentry **pp;
7877         struct tblentry *cmdp;
7878
7879         INT_OFF;
7880         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7881                 pp = tblp;
7882                 while ((cmdp = *pp) != NULL) {
7883                         if ((cmdp->cmdtype == CMDNORMAL &&
7884                              cmdp->param.index >= firstchange)
7885                          || (cmdp->cmdtype == CMDBUILTIN &&
7886                              builtinloc >= firstchange)
7887                         ) {
7888                                 *pp = cmdp->next;
7889                                 free(cmdp);
7890                         } else {
7891                                 pp = &cmdp->next;
7892                         }
7893                 }
7894         }
7895         INT_ON;
7896 }
7897
7898 /*
7899  * Locate a command in the command hash table.  If "add" is nonzero,
7900  * add the command to the table if it is not already present.  The
7901  * variable "lastcmdentry" is set to point to the address of the link
7902  * pointing to the entry, so that delete_cmd_entry can delete the
7903  * entry.
7904  *
7905  * Interrupts must be off if called with add != 0.
7906  */
7907 static struct tblentry **lastcmdentry;
7908
7909 static struct tblentry *
7910 cmdlookup(const char *name, int add)
7911 {
7912         unsigned int hashval;
7913         const char *p;
7914         struct tblentry *cmdp;
7915         struct tblentry **pp;
7916
7917         p = name;
7918         hashval = (unsigned char)*p << 4;
7919         while (*p)
7920                 hashval += (unsigned char)*p++;
7921         hashval &= 0x7FFF;
7922         pp = &cmdtable[hashval % CMDTABLESIZE];
7923         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7924                 if (strcmp(cmdp->cmdname, name) == 0)
7925                         break;
7926                 pp = &cmdp->next;
7927         }
7928         if (add && cmdp == NULL) {
7929                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7930                                 + strlen(name)
7931                                 /* + 1 - already done because
7932                                  * tblentry::cmdname is char[1] */);
7933                 /*cmdp->next = NULL; - ckzalloc did it */
7934                 cmdp->cmdtype = CMDUNKNOWN;
7935                 strcpy(cmdp->cmdname, name);
7936         }
7937         lastcmdentry = pp;
7938         return cmdp;
7939 }
7940
7941 /*
7942  * Delete the command entry returned on the last lookup.
7943  */
7944 static void
7945 delete_cmd_entry(void)
7946 {
7947         struct tblentry *cmdp;
7948
7949         INT_OFF;
7950         cmdp = *lastcmdentry;
7951         *lastcmdentry = cmdp->next;
7952         if (cmdp->cmdtype == CMDFUNCTION)
7953                 freefunc(cmdp->param.func);
7954         free(cmdp);
7955         INT_ON;
7956 }
7957
7958 /*
7959  * Add a new command entry, replacing any existing command entry for
7960  * the same name - except special builtins.
7961  */
7962 static void
7963 addcmdentry(char *name, struct cmdentry *entry)
7964 {
7965         struct tblentry *cmdp;
7966
7967         cmdp = cmdlookup(name, 1);
7968         if (cmdp->cmdtype == CMDFUNCTION) {
7969                 freefunc(cmdp->param.func);
7970         }
7971         cmdp->cmdtype = entry->cmdtype;
7972         cmdp->param = entry->u;
7973         cmdp->rehash = 0;
7974 }
7975
7976 static int FAST_FUNC
7977 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7978 {
7979         struct tblentry **pp;
7980         struct tblentry *cmdp;
7981         int c;
7982         struct cmdentry entry;
7983         char *name;
7984
7985         if (nextopt("r") != '\0') {
7986                 clearcmdentry(0);
7987                 return 0;
7988         }
7989
7990         if (*argptr == NULL) {
7991                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7992                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7993                                 if (cmdp->cmdtype == CMDNORMAL)
7994                                         printentry(cmdp);
7995                         }
7996                 }
7997                 return 0;
7998         }
7999
8000         c = 0;
8001         while ((name = *argptr) != NULL) {
8002                 cmdp = cmdlookup(name, 0);
8003                 if (cmdp != NULL
8004                  && (cmdp->cmdtype == CMDNORMAL
8005                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8006                 ) {
8007                         delete_cmd_entry();
8008                 }
8009                 find_command(name, &entry, DO_ERR, pathval());
8010                 if (entry.cmdtype == CMDUNKNOWN)
8011                         c = 1;
8012                 argptr++;
8013         }
8014         return c;
8015 }
8016
8017 /*
8018  * Called when a cd is done.  Marks all commands so the next time they
8019  * are executed they will be rehashed.
8020  */
8021 static void
8022 hashcd(void)
8023 {
8024         struct tblentry **pp;
8025         struct tblentry *cmdp;
8026
8027         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8028                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8029                         if (cmdp->cmdtype == CMDNORMAL
8030                          || (cmdp->cmdtype == CMDBUILTIN
8031                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8032                              && builtinloc > 0)
8033                         ) {
8034                                 cmdp->rehash = 1;
8035                         }
8036                 }
8037         }
8038 }
8039
8040 /*
8041  * Fix command hash table when PATH changed.
8042  * Called before PATH is changed.  The argument is the new value of PATH;
8043  * pathval() still returns the old value at this point.
8044  * Called with interrupts off.
8045  */
8046 static void FAST_FUNC
8047 changepath(const char *new)
8048 {
8049         const char *old;
8050         int firstchange;
8051         int idx;
8052         int idx_bltin;
8053
8054         old = pathval();
8055         firstchange = 9999;     /* assume no change */
8056         idx = 0;
8057         idx_bltin = -1;
8058         for (;;) {
8059                 if (*old != *new) {
8060                         firstchange = idx;
8061                         if ((*old == '\0' && *new == ':')
8062                          || (*old == ':' && *new == '\0')
8063                         ) {
8064                                 firstchange++;
8065                         }
8066                         old = new;      /* ignore subsequent differences */
8067                 }
8068                 if (*new == '\0')
8069                         break;
8070                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8071                         idx_bltin = idx;
8072                 if (*new == ':')
8073                         idx++;
8074                 new++;
8075                 old++;
8076         }
8077         if (builtinloc < 0 && idx_bltin >= 0)
8078                 builtinloc = idx_bltin;             /* zap builtins */
8079         if (builtinloc >= 0 && idx_bltin < 0)
8080                 firstchange = 0;
8081         clearcmdentry(firstchange);
8082         builtinloc = idx_bltin;
8083 }
8084 enum {
8085         TEOF,
8086         TNL,
8087         TREDIR,
8088         TWORD,
8089         TSEMI,
8090         TBACKGND,
8091         TAND,
8092         TOR,
8093         TPIPE,
8094         TLP,
8095         TRP,
8096         TENDCASE,
8097         TENDBQUOTE,
8098         TNOT,
8099         TCASE,
8100         TDO,
8101         TDONE,
8102         TELIF,
8103         TELSE,
8104         TESAC,
8105         TFI,
8106         TFOR,
8107 #if BASH_FUNCTION
8108         TFUNCTION,
8109 #endif
8110         TIF,
8111         TIN,
8112         TTHEN,
8113         TUNTIL,
8114         TWHILE,
8115         TBEGIN,
8116         TEND
8117 };
8118 typedef smallint token_id_t;
8119
8120 /* Nth bit indicates if token marks the end of a list */
8121 enum {
8122         tokendlist = 0
8123         /*  0 */ | (1u << TEOF)
8124         /*  1 */ | (0u << TNL)
8125         /*  2 */ | (0u << TREDIR)
8126         /*  3 */ | (0u << TWORD)
8127         /*  4 */ | (0u << TSEMI)
8128         /*  5 */ | (0u << TBACKGND)
8129         /*  6 */ | (0u << TAND)
8130         /*  7 */ | (0u << TOR)
8131         /*  8 */ | (0u << TPIPE)
8132         /*  9 */ | (0u << TLP)
8133         /* 10 */ | (1u << TRP)
8134         /* 11 */ | (1u << TENDCASE)
8135         /* 12 */ | (1u << TENDBQUOTE)
8136         /* 13 */ | (0u << TNOT)
8137         /* 14 */ | (0u << TCASE)
8138         /* 15 */ | (1u << TDO)
8139         /* 16 */ | (1u << TDONE)
8140         /* 17 */ | (1u << TELIF)
8141         /* 18 */ | (1u << TELSE)
8142         /* 19 */ | (1u << TESAC)
8143         /* 20 */ | (1u << TFI)
8144         /* 21 */ | (0u << TFOR)
8145 #if BASH_FUNCTION
8146         /* 22 */ | (0u << TFUNCTION)
8147 #endif
8148         /* 23 */ | (0u << TIF)
8149         /* 24 */ | (0u << TIN)
8150         /* 25 */ | (1u << TTHEN)
8151         /* 26 */ | (0u << TUNTIL)
8152         /* 27 */ | (0u << TWHILE)
8153         /* 28 */ | (0u << TBEGIN)
8154         /* 29 */ | (1u << TEND)
8155         , /* thus far 29 bits used */
8156 };
8157
8158 static const char *const tokname_array[] = {
8159         "end of file",
8160         "newline",
8161         "redirection",
8162         "word",
8163         ";",
8164         "&",
8165         "&&",
8166         "||",
8167         "|",
8168         "(",
8169         ")",
8170         ";;",
8171         "`",
8172 #define KWDOFFSET 13
8173         /* the following are keywords */
8174         "!",
8175         "case",
8176         "do",
8177         "done",
8178         "elif",
8179         "else",
8180         "esac",
8181         "fi",
8182         "for",
8183 #if BASH_FUNCTION
8184         "function",
8185 #endif
8186         "if",
8187         "in",
8188         "then",
8189         "until",
8190         "while",
8191         "{",
8192         "}",
8193 };
8194
8195 /* Wrapper around strcmp for qsort/bsearch/... */
8196 static int
8197 pstrcmp(const void *a, const void *b)
8198 {
8199         return strcmp((char*)a, *(char**)b);
8200 }
8201
8202 static const char *const *
8203 findkwd(const char *s)
8204 {
8205         return bsearch(s, tokname_array + KWDOFFSET,
8206                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8207                         sizeof(tokname_array[0]), pstrcmp);
8208 }
8209
8210 /*
8211  * Locate and print what a word is...
8212  */
8213 static int
8214 describe_command(char *command, const char *path, int describe_command_verbose)
8215 {
8216         struct cmdentry entry;
8217 #if ENABLE_ASH_ALIAS
8218         const struct alias *ap;
8219 #endif
8220
8221         path = path ? path : pathval();
8222
8223         if (describe_command_verbose) {
8224                 out1str(command);
8225         }
8226
8227         /* First look at the keywords */
8228         if (findkwd(command)) {
8229                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8230                 goto out;
8231         }
8232
8233 #if ENABLE_ASH_ALIAS
8234         /* Then look at the aliases */
8235         ap = lookupalias(command, 0);
8236         if (ap != NULL) {
8237                 if (!describe_command_verbose) {
8238                         out1str("alias ");
8239                         printalias(ap);
8240                         return 0;
8241                 }
8242                 out1fmt(" is an alias for %s", ap->val);
8243                 goto out;
8244         }
8245 #endif
8246         /* Brute force */
8247         find_command(command, &entry, DO_ABS, path);
8248
8249         switch (entry.cmdtype) {
8250         case CMDNORMAL: {
8251                 int j = entry.u.index;
8252                 char *p;
8253                 if (j < 0) {
8254                         p = command;
8255                 } else {
8256                         do {
8257                                 p = path_advance(&path, command);
8258                                 stunalloc(p);
8259                         } while (--j >= 0);
8260                 }
8261                 if (describe_command_verbose) {
8262                         out1fmt(" is %s", p);
8263                 } else {
8264                         out1str(p);
8265                 }
8266                 break;
8267         }
8268
8269         case CMDFUNCTION:
8270                 if (describe_command_verbose) {
8271                         out1str(" is a shell function");
8272                 } else {
8273                         out1str(command);
8274                 }
8275                 break;
8276
8277         case CMDBUILTIN:
8278                 if (describe_command_verbose) {
8279                         out1fmt(" is a %sshell builtin",
8280                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8281                                         "special " : nullstr
8282                         );
8283                 } else {
8284                         out1str(command);
8285                 }
8286                 break;
8287
8288         default:
8289                 if (describe_command_verbose) {
8290                         out1str(": not found\n");
8291                 }
8292                 return 127;
8293         }
8294  out:
8295         out1str("\n");
8296         return 0;
8297 }
8298
8299 static int FAST_FUNC
8300 typecmd(int argc UNUSED_PARAM, char **argv)
8301 {
8302         int i = 1;
8303         int err = 0;
8304         int verbose = 1;
8305
8306         /* type -p ... ? (we don't bother checking for 'p') */
8307         if (argv[1] && argv[1][0] == '-') {
8308                 i++;
8309                 verbose = 0;
8310         }
8311         while (argv[i]) {
8312                 err |= describe_command(argv[i++], NULL, verbose);
8313         }
8314         return err;
8315 }
8316
8317 #if ENABLE_ASH_CMDCMD
8318 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8319 static char **
8320 parse_command_args(char **argv, const char **path)
8321 {
8322         char *cp, c;
8323
8324         for (;;) {
8325                 cp = *++argv;
8326                 if (!cp)
8327                         return NULL;
8328                 if (*cp++ != '-')
8329                         break;
8330                 c = *cp++;
8331                 if (!c)
8332                         break;
8333                 if (c == '-' && !*cp) {
8334                         if (!*++argv)
8335                                 return NULL;
8336                         break;
8337                 }
8338                 do {
8339                         switch (c) {
8340                         case 'p':
8341                                 *path = bb_default_path;
8342                                 break;
8343                         default:
8344                                 /* run 'typecmd' for other options */
8345                                 return NULL;
8346                         }
8347                         c = *cp++;
8348                 } while (c);
8349         }
8350         return argv;
8351 }
8352
8353 static int FAST_FUNC
8354 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8355 {
8356         char *cmd;
8357         int c;
8358         enum {
8359                 VERIFY_BRIEF = 1,
8360                 VERIFY_VERBOSE = 2,
8361         } verify = 0;
8362         const char *path = NULL;
8363
8364         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8365          * never reaches this function.
8366          */
8367
8368         while ((c = nextopt("pvV")) != '\0')
8369                 if (c == 'V')
8370                         verify |= VERIFY_VERBOSE;
8371                 else if (c == 'v')
8372                         /*verify |= VERIFY_BRIEF*/;
8373 #if DEBUG
8374                 else if (c != 'p')
8375                         abort();
8376 #endif
8377                 else
8378                         path = bb_default_path;
8379
8380         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8381         cmd = *argptr;
8382         if (/*verify && */ cmd)
8383                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8384
8385         return 0;
8386 }
8387 #endif
8388
8389
8390 /*static int funcblocksize;     // size of structures in function */
8391 /*static int funcstringsize;    // size of strings in node */
8392 static void *funcblock;         /* block to allocate function from */
8393 static char *funcstring_end;    /* end of block to allocate strings from */
8394
8395 /* flags in argument to evaltree */
8396 #define EV_EXIT    01           /* exit after evaluating tree */
8397 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8398
8399 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8400         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8401         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8402         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8403         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8404         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8405         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8406         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8407         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8408         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8409         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8410         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8411         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8412         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8413         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8414         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8415         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8416         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8417 #if BASH_REDIR_OUTPUT
8418         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8419 #endif
8420         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8421         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8422         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8423         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8424         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8425         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8426         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8427         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8428         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8429 };
8430
8431 static int calcsize(int funcblocksize, union node *n);
8432
8433 static int
8434 sizenodelist(int funcblocksize, struct nodelist *lp)
8435 {
8436         while (lp) {
8437                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8438                 funcblocksize = calcsize(funcblocksize, lp->n);
8439                 lp = lp->next;
8440         }
8441         return funcblocksize;
8442 }
8443
8444 static int
8445 calcsize(int funcblocksize, union node *n)
8446 {
8447         if (n == NULL)
8448                 return funcblocksize;
8449         funcblocksize += nodesize[n->type];
8450         switch (n->type) {
8451         case NCMD:
8452                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8453                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8454                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8455                 break;
8456         case NPIPE:
8457                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8458                 break;
8459         case NREDIR:
8460         case NBACKGND:
8461         case NSUBSHELL:
8462                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8463                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8464                 break;
8465         case NAND:
8466         case NOR:
8467         case NSEMI:
8468         case NWHILE:
8469         case NUNTIL:
8470                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8471                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8472                 break;
8473         case NIF:
8474                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8475                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8476                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8477                 break;
8478         case NFOR:
8479                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8480                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8481                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8482                 break;
8483         case NCASE:
8484                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8485                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8486                 break;
8487         case NCLIST:
8488                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8489                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8490                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8491                 break;
8492         case NDEFUN:
8493         case NARG:
8494                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8495                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8496                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8497                 break;
8498         case NTO:
8499 #if BASH_REDIR_OUTPUT
8500         case NTO2:
8501 #endif
8502         case NCLOBBER:
8503         case NFROM:
8504         case NFROMTO:
8505         case NAPPEND:
8506                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8507                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8508                 break;
8509         case NTOFD:
8510         case NFROMFD:
8511                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8512                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8513         break;
8514         case NHERE:
8515         case NXHERE:
8516                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8517                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8518                 break;
8519         case NNOT:
8520                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8521                 break;
8522         };
8523         return funcblocksize;
8524 }
8525
8526 static char *
8527 nodeckstrdup(char *s)
8528 {
8529         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8530         return strcpy(funcstring_end, s);
8531 }
8532
8533 static union node *copynode(union node *);
8534
8535 static struct nodelist *
8536 copynodelist(struct nodelist *lp)
8537 {
8538         struct nodelist *start;
8539         struct nodelist **lpp;
8540
8541         lpp = &start;
8542         while (lp) {
8543                 *lpp = funcblock;
8544                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8545                 (*lpp)->n = copynode(lp->n);
8546                 lp = lp->next;
8547                 lpp = &(*lpp)->next;
8548         }
8549         *lpp = NULL;
8550         return start;
8551 }
8552
8553 static union node *
8554 copynode(union node *n)
8555 {
8556         union node *new;
8557
8558         if (n == NULL)
8559                 return NULL;
8560         new = funcblock;
8561         funcblock = (char *) funcblock + nodesize[n->type];
8562
8563         switch (n->type) {
8564         case NCMD:
8565                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8566                 new->ncmd.args = copynode(n->ncmd.args);
8567                 new->ncmd.assign = copynode(n->ncmd.assign);
8568                 break;
8569         case NPIPE:
8570                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8571                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8572                 break;
8573         case NREDIR:
8574         case NBACKGND:
8575         case NSUBSHELL:
8576                 new->nredir.redirect = copynode(n->nredir.redirect);
8577                 new->nredir.n = copynode(n->nredir.n);
8578                 break;
8579         case NAND:
8580         case NOR:
8581         case NSEMI:
8582         case NWHILE:
8583         case NUNTIL:
8584                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8585                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8586                 break;
8587         case NIF:
8588                 new->nif.elsepart = copynode(n->nif.elsepart);
8589                 new->nif.ifpart = copynode(n->nif.ifpart);
8590                 new->nif.test = copynode(n->nif.test);
8591                 break;
8592         case NFOR:
8593                 new->nfor.var = nodeckstrdup(n->nfor.var);
8594                 new->nfor.body = copynode(n->nfor.body);
8595                 new->nfor.args = copynode(n->nfor.args);
8596                 break;
8597         case NCASE:
8598                 new->ncase.cases = copynode(n->ncase.cases);
8599                 new->ncase.expr = copynode(n->ncase.expr);
8600                 break;
8601         case NCLIST:
8602                 new->nclist.body = copynode(n->nclist.body);
8603                 new->nclist.pattern = copynode(n->nclist.pattern);
8604                 new->nclist.next = copynode(n->nclist.next);
8605                 break;
8606         case NDEFUN:
8607         case NARG:
8608                 new->narg.backquote = copynodelist(n->narg.backquote);
8609                 new->narg.text = nodeckstrdup(n->narg.text);
8610                 new->narg.next = copynode(n->narg.next);
8611                 break;
8612         case NTO:
8613 #if BASH_REDIR_OUTPUT
8614         case NTO2:
8615 #endif
8616         case NCLOBBER:
8617         case NFROM:
8618         case NFROMTO:
8619         case NAPPEND:
8620                 new->nfile.fname = copynode(n->nfile.fname);
8621                 new->nfile.fd = n->nfile.fd;
8622                 new->nfile.next = copynode(n->nfile.next);
8623                 break;
8624         case NTOFD:
8625         case NFROMFD:
8626                 new->ndup.vname = copynode(n->ndup.vname);
8627                 new->ndup.dupfd = n->ndup.dupfd;
8628                 new->ndup.fd = n->ndup.fd;
8629                 new->ndup.next = copynode(n->ndup.next);
8630                 break;
8631         case NHERE:
8632         case NXHERE:
8633                 new->nhere.doc = copynode(n->nhere.doc);
8634                 new->nhere.fd = n->nhere.fd;
8635                 new->nhere.next = copynode(n->nhere.next);
8636                 break;
8637         case NNOT:
8638                 new->nnot.com = copynode(n->nnot.com);
8639                 break;
8640         };
8641         new->type = n->type;
8642         return new;
8643 }
8644
8645 /*
8646  * Make a copy of a parse tree.
8647  */
8648 static struct funcnode *
8649 copyfunc(union node *n)
8650 {
8651         struct funcnode *f;
8652         size_t blocksize;
8653
8654         /*funcstringsize = 0;*/
8655         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8656         f = ckzalloc(blocksize /* + funcstringsize */);
8657         funcblock = (char *) f + offsetof(struct funcnode, n);
8658         funcstring_end = (char *) f + blocksize;
8659         copynode(n);
8660         /* f->count = 0; - ckzalloc did it */
8661         return f;
8662 }
8663
8664 /*
8665  * Define a shell function.
8666  */
8667 static void
8668 defun(union node *func)
8669 {
8670         struct cmdentry entry;
8671
8672         INT_OFF;
8673         entry.cmdtype = CMDFUNCTION;
8674         entry.u.func = copyfunc(func);
8675         addcmdentry(func->narg.text, &entry);
8676         INT_ON;
8677 }
8678
8679 /* Reasons for skipping commands (see comment on breakcmd routine) */
8680 #define SKIPBREAK      (1 << 0)
8681 #define SKIPCONT       (1 << 1)
8682 #define SKIPFUNC       (1 << 2)
8683 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8684 static int skipcount;           /* number of levels to skip */
8685 static int funcnest;            /* depth of function calls */
8686 static int loopnest;            /* current loop nesting level */
8687
8688 /* Forward decl way out to parsing code - dotrap needs it */
8689 static int evalstring(char *s, int flags);
8690
8691 /* Called to execute a trap.
8692  * Single callsite - at the end of evaltree().
8693  * If we return non-zero, evaltree raises EXEXIT exception.
8694  *
8695  * Perhaps we should avoid entering new trap handlers
8696  * while we are executing a trap handler. [is it a TODO?]
8697  */
8698 static void
8699 dotrap(void)
8700 {
8701         uint8_t *g;
8702         int sig;
8703         uint8_t last_status;
8704
8705         if (!pending_sig)
8706                 return;
8707
8708         last_status = exitstatus;
8709         pending_sig = 0;
8710         barrier();
8711
8712         TRACE(("dotrap entered\n"));
8713         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8714                 char *p;
8715
8716                 if (!*g)
8717                         continue;
8718
8719                 if (evalskip) {
8720                         pending_sig = sig;
8721                         break;
8722                 }
8723
8724                 p = trap[sig];
8725                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8726                  * don't upset it by resetting gotsig[SIGINT-1] */
8727                 if (sig == SIGINT && !p)
8728                         continue;
8729
8730                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8731                 *g = 0;
8732                 if (!p)
8733                         continue;
8734                 evalstring(p, 0);
8735         }
8736         exitstatus = last_status;
8737         TRACE(("dotrap returns\n"));
8738 }
8739
8740 /* forward declarations - evaluation is fairly recursive business... */
8741 static int evalloop(union node *, int);
8742 static int evalfor(union node *, int);
8743 static int evalcase(union node *, int);
8744 static int evalsubshell(union node *, int);
8745 static void expredir(union node *);
8746 static int evalpipe(union node *, int);
8747 static int evalcommand(union node *, int);
8748 static int evalbltin(const struct builtincmd *, int, char **, int);
8749 static void prehash(union node *);
8750
8751 /*
8752  * Evaluate a parse tree.  The value is left in the global variable
8753  * exitstatus.
8754  */
8755 static int
8756 evaltree(union node *n, int flags)
8757 {
8758         int checkexit = 0;
8759         int (*evalfn)(union node *, int);
8760         int status = 0;
8761
8762         if (n == NULL) {
8763                 TRACE(("evaltree(NULL) called\n"));
8764                 goto out;
8765         }
8766         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8767
8768         dotrap();
8769
8770         switch (n->type) {
8771         default:
8772 #if DEBUG
8773                 out1fmt("Node type = %d\n", n->type);
8774                 fflush_all();
8775                 break;
8776 #endif
8777         case NNOT:
8778                 status = !evaltree(n->nnot.com, EV_TESTED);
8779                 goto setstatus;
8780         case NREDIR:
8781                 expredir(n->nredir.redirect);
8782                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8783                 if (!status) {
8784                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8785                 }
8786                 if (n->nredir.redirect)
8787                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8788                 goto setstatus;
8789         case NCMD:
8790                 evalfn = evalcommand;
8791  checkexit:
8792                 if (eflag && !(flags & EV_TESTED))
8793                         checkexit = ~0;
8794                 goto calleval;
8795         case NFOR:
8796                 evalfn = evalfor;
8797                 goto calleval;
8798         case NWHILE:
8799         case NUNTIL:
8800                 evalfn = evalloop;
8801                 goto calleval;
8802         case NSUBSHELL:
8803         case NBACKGND:
8804                 evalfn = evalsubshell;
8805                 goto checkexit;
8806         case NPIPE:
8807                 evalfn = evalpipe;
8808                 goto checkexit;
8809         case NCASE:
8810                 evalfn = evalcase;
8811                 goto calleval;
8812         case NAND:
8813         case NOR:
8814         case NSEMI: {
8815
8816 #if NAND + 1 != NOR
8817 #error NAND + 1 != NOR
8818 #endif
8819 #if NOR + 1 != NSEMI
8820 #error NOR + 1 != NSEMI
8821 #endif
8822                 unsigned is_or = n->type - NAND;
8823                 status = evaltree(
8824                         n->nbinary.ch1,
8825                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8826                 );
8827                 if ((!status) == is_or || evalskip)
8828                         break;
8829                 n = n->nbinary.ch2;
8830  evaln:
8831                 evalfn = evaltree;
8832  calleval:
8833                 status = evalfn(n, flags);
8834                 goto setstatus;
8835         }
8836         case NIF:
8837                 status = evaltree(n->nif.test, EV_TESTED);
8838                 if (evalskip)
8839                         break;
8840                 if (!status) {
8841                         n = n->nif.ifpart;
8842                         goto evaln;
8843                 }
8844                 if (n->nif.elsepart) {
8845                         n = n->nif.elsepart;
8846                         goto evaln;
8847                 }
8848                 status = 0;
8849                 goto setstatus;
8850         case NDEFUN:
8851                 defun(n);
8852                 /* Not necessary. To test it:
8853                  * "false; f() { qwerty; }; echo $?" should print 0.
8854                  */
8855                 /* status = 0; */
8856  setstatus:
8857                 exitstatus = status;
8858                 break;
8859         }
8860  out:
8861         /* Order of checks below is important:
8862          * signal handlers trigger before exit caused by "set -e".
8863          */
8864         dotrap();
8865
8866         if (checkexit & status)
8867                 raise_exception(EXEXIT);
8868         if (flags & EV_EXIT)
8869                 raise_exception(EXEXIT);
8870
8871         TRACE(("leaving evaltree (no interrupts)\n"));
8872         return exitstatus;
8873 }
8874
8875 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8876 static
8877 #endif
8878 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8879
8880 static int
8881 skiploop(void)
8882 {
8883         int skip = evalskip;
8884
8885         switch (skip) {
8886         case 0:
8887                 break;
8888         case SKIPBREAK:
8889         case SKIPCONT:
8890                 if (--skipcount <= 0) {
8891                         evalskip = 0;
8892                         break;
8893                 }
8894                 skip = SKIPBREAK;
8895                 break;
8896         }
8897         return skip;
8898 }
8899
8900 static int
8901 evalloop(union node *n, int flags)
8902 {
8903         int skip;
8904         int status;
8905
8906         loopnest++;
8907         status = 0;
8908         flags &= EV_TESTED;
8909         do {
8910                 int i;
8911
8912                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8913                 skip = skiploop();
8914                 if (skip == SKIPFUNC)
8915                         status = i;
8916                 if (skip)
8917                         continue;
8918                 if (n->type != NWHILE)
8919                         i = !i;
8920                 if (i != 0)
8921                         break;
8922                 status = evaltree(n->nbinary.ch2, flags);
8923                 skip = skiploop();
8924         } while (!(skip & ~SKIPCONT));
8925         loopnest--;
8926
8927         return status;
8928 }
8929
8930 static int
8931 evalfor(union node *n, int flags)
8932 {
8933         struct arglist arglist;
8934         union node *argp;
8935         struct strlist *sp;
8936         struct stackmark smark;
8937         int status = 0;
8938
8939         setstackmark(&smark);
8940         arglist.list = NULL;
8941         arglist.lastp = &arglist.list;
8942         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8943                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8944         }
8945         *arglist.lastp = NULL;
8946
8947         loopnest++;
8948         flags &= EV_TESTED;
8949         for (sp = arglist.list; sp; sp = sp->next) {
8950                 setvar0(n->nfor.var, sp->text);
8951                 status = evaltree(n->nfor.body, flags);
8952                 if (skiploop() & ~SKIPCONT)
8953                         break;
8954         }
8955         loopnest--;
8956         popstackmark(&smark);
8957
8958         return status;
8959 }
8960
8961 static int
8962 evalcase(union node *n, int flags)
8963 {
8964         union node *cp;
8965         union node *patp;
8966         struct arglist arglist;
8967         struct stackmark smark;
8968         int status = 0;
8969
8970         setstackmark(&smark);
8971         arglist.list = NULL;
8972         arglist.lastp = &arglist.list;
8973         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8974         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8975                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8976                         if (casematch(patp, arglist.list->text)) {
8977                                 /* Ensure body is non-empty as otherwise
8978                                  * EV_EXIT may prevent us from setting the
8979                                  * exit status.
8980                                  */
8981                                 if (evalskip == 0 && cp->nclist.body) {
8982                                         status = evaltree(cp->nclist.body, flags);
8983                                 }
8984                                 goto out;
8985                         }
8986                 }
8987         }
8988  out:
8989         popstackmark(&smark);
8990
8991         return status;
8992 }
8993
8994 /*
8995  * Kick off a subshell to evaluate a tree.
8996  */
8997 static int
8998 evalsubshell(union node *n, int flags)
8999 {
9000         struct job *jp;
9001         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9002         int status;
9003
9004         expredir(n->nredir.redirect);
9005         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9006                 goto nofork;
9007         INT_OFF;
9008         if (backgnd == FORK_FG)
9009                 get_tty_state();
9010         jp = makejob(/*n,*/ 1);
9011         if (forkshell(jp, n, backgnd) == 0) {
9012                 /* child */
9013                 INT_ON;
9014                 flags |= EV_EXIT;
9015                 if (backgnd)
9016                         flags &= ~EV_TESTED;
9017  nofork:
9018                 redirect(n->nredir.redirect, 0);
9019                 evaltreenr(n->nredir.n, flags);
9020                 /* never returns */
9021         }
9022         /* parent */
9023         status = 0;
9024         if (backgnd == FORK_FG)
9025                 status = waitforjob(jp);
9026         INT_ON;
9027         return status;
9028 }
9029
9030 /*
9031  * Compute the names of the files in a redirection list.
9032  */
9033 static void fixredir(union node *, const char *, int);
9034 static void
9035 expredir(union node *n)
9036 {
9037         union node *redir;
9038
9039         for (redir = n; redir; redir = redir->nfile.next) {
9040                 struct arglist fn;
9041
9042                 fn.list = NULL;
9043                 fn.lastp = &fn.list;
9044                 switch (redir->type) {
9045                 case NFROMTO:
9046                 case NFROM:
9047                 case NTO:
9048 #if BASH_REDIR_OUTPUT
9049                 case NTO2:
9050 #endif
9051                 case NCLOBBER:
9052                 case NAPPEND:
9053                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9054                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9055 #if BASH_REDIR_OUTPUT
9056  store_expfname:
9057 #endif
9058 #if 0
9059 // By the design of stack allocator, the loop of this kind:
9060 //      while true; do while true; do break; done </dev/null; done
9061 // will look like a memory leak: ash plans to free expfname's
9062 // of "/dev/null" as soon as it finishes running the loop
9063 // (in this case, never).
9064 // This "fix" is wrong:
9065                         if (redir->nfile.expfname)
9066                                 stunalloc(redir->nfile.expfname);
9067 // It results in corrupted state of stacked allocations.
9068 #endif
9069                         redir->nfile.expfname = fn.list->text;
9070                         break;
9071                 case NFROMFD:
9072                 case NTOFD: /* >& */
9073                         if (redir->ndup.vname) {
9074                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9075                                 if (fn.list == NULL)
9076                                         ash_msg_and_raise_error("redir error");
9077 #if BASH_REDIR_OUTPUT
9078 //FIXME: we used expandarg with different args!
9079                                 if (!isdigit_str9(fn.list->text)) {
9080                                         /* >&file, not >&fd */
9081                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9082                                                 ash_msg_and_raise_error("redir error");
9083                                         redir->type = NTO2;
9084                                         goto store_expfname;
9085                                 }
9086 #endif
9087                                 fixredir(redir, fn.list->text, 1);
9088                         }
9089                         break;
9090                 }
9091         }
9092 }
9093
9094 /*
9095  * Evaluate a pipeline.  All the processes in the pipeline are children
9096  * of the process creating the pipeline.  (This differs from some versions
9097  * of the shell, which make the last process in a pipeline the parent
9098  * of all the rest.)
9099  */
9100 static int
9101 evalpipe(union node *n, int flags)
9102 {
9103         struct job *jp;
9104         struct nodelist *lp;
9105         int pipelen;
9106         int prevfd;
9107         int pip[2];
9108         int status = 0;
9109
9110         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9111         pipelen = 0;
9112         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9113                 pipelen++;
9114         flags |= EV_EXIT;
9115         INT_OFF;
9116         if (n->npipe.pipe_backgnd == 0)
9117                 get_tty_state();
9118         jp = makejob(/*n,*/ pipelen);
9119         prevfd = -1;
9120         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9121                 prehash(lp->n);
9122                 pip[1] = -1;
9123                 if (lp->next) {
9124                         if (pipe(pip) < 0) {
9125                                 close(prevfd);
9126                                 ash_msg_and_raise_error("pipe call failed");
9127                         }
9128                 }
9129                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9130                         /* child */
9131                         INT_ON;
9132                         if (pip[1] >= 0) {
9133                                 close(pip[0]);
9134                         }
9135                         if (prevfd > 0) {
9136                                 dup2(prevfd, 0);
9137                                 close(prevfd);
9138                         }
9139                         if (pip[1] > 1) {
9140                                 dup2(pip[1], 1);
9141                                 close(pip[1]);
9142                         }
9143                         evaltreenr(lp->n, flags);
9144                         /* never returns */
9145                 }
9146                 /* parent */
9147                 if (prevfd >= 0)
9148                         close(prevfd);
9149                 prevfd = pip[0];
9150                 /* Don't want to trigger debugging */
9151                 if (pip[1] != -1)
9152                         close(pip[1]);
9153         }
9154         if (n->npipe.pipe_backgnd == 0) {
9155                 status = waitforjob(jp);
9156                 TRACE(("evalpipe:  job done exit status %d\n", status));
9157         }
9158         INT_ON;
9159
9160         return status;
9161 }
9162
9163 /*
9164  * Controls whether the shell is interactive or not.
9165  */
9166 static void
9167 setinteractive(int on)
9168 {
9169         static smallint is_interactive;
9170
9171         if (++on == is_interactive)
9172                 return;
9173         is_interactive = on;
9174         setsignal(SIGINT);
9175         setsignal(SIGQUIT);
9176         setsignal(SIGTERM);
9177 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9178         if (is_interactive > 1) {
9179                 /* Looks like they want an interactive shell */
9180                 static smallint did_banner;
9181
9182                 if (!did_banner) {
9183                         /* note: ash and hush share this string */
9184                         out1fmt("\n\n%s %s\n"
9185                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9186                                 "\n",
9187                                 bb_banner,
9188                                 "built-in shell (ash)"
9189                         );
9190                         did_banner = 1;
9191                 }
9192         }
9193 #endif
9194 }
9195
9196 static void
9197 optschanged(void)
9198 {
9199 #if DEBUG
9200         opentrace();
9201 #endif
9202         setinteractive(iflag);
9203         setjobctl(mflag);
9204 #if ENABLE_FEATURE_EDITING_VI
9205         if (viflag)
9206                 line_input_state->flags |= VI_MODE;
9207         else
9208                 line_input_state->flags &= ~VI_MODE;
9209 #else
9210         viflag = 0; /* forcibly keep the option off */
9211 #endif
9212 }
9213
9214 static struct localvar *localvars;
9215
9216 /*
9217  * Called after a function returns.
9218  * Interrupts must be off.
9219  */
9220 static void
9221 poplocalvars(void)
9222 {
9223         struct localvar *lvp;
9224         struct var *vp;
9225
9226         while ((lvp = localvars) != NULL) {
9227                 localvars = lvp->next;
9228                 vp = lvp->vp;
9229                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9230                 if (vp == NULL) {       /* $- saved */
9231                         memcpy(optlist, lvp->text, sizeof(optlist));
9232                         free((char*)lvp->text);
9233                         optschanged();
9234                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9235                         unsetvar(vp->var_text);
9236                 } else {
9237                         if (vp->var_func)
9238                                 vp->var_func(var_end(lvp->text));
9239                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9240                                 free((char*)vp->var_text);
9241                         vp->flags = lvp->flags;
9242                         vp->var_text = lvp->text;
9243                 }
9244                 free(lvp);
9245         }
9246 }
9247
9248 static int
9249 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9250 {
9251         volatile struct shparam saveparam;
9252         struct localvar *volatile savelocalvars;
9253         struct jmploc *volatile savehandler;
9254         struct jmploc jmploc;
9255         int e;
9256
9257         saveparam = shellparam;
9258         savelocalvars = localvars;
9259         savehandler = exception_handler;
9260         e = setjmp(jmploc.loc);
9261         if (e) {
9262                 goto funcdone;
9263         }
9264         INT_OFF;
9265         exception_handler = &jmploc;
9266         localvars = NULL;
9267         shellparam.malloced = 0;
9268         func->count++;
9269         funcnest++;
9270         INT_ON;
9271         shellparam.nparam = argc - 1;
9272         shellparam.p = argv + 1;
9273 #if ENABLE_ASH_GETOPTS
9274         shellparam.optind = 1;
9275         shellparam.optoff = -1;
9276 #endif
9277         evaltree(func->n.narg.next, flags & EV_TESTED);
9278  funcdone:
9279         INT_OFF;
9280         funcnest--;
9281         freefunc(func);
9282         poplocalvars();
9283         localvars = savelocalvars;
9284         freeparam(&shellparam);
9285         shellparam = saveparam;
9286         exception_handler = savehandler;
9287         INT_ON;
9288         evalskip &= ~SKIPFUNC;
9289         return e;
9290 }
9291
9292 /*
9293  * Make a variable a local variable.  When a variable is made local, it's
9294  * value and flags are saved in a localvar structure.  The saved values
9295  * will be restored when the shell function returns.  We handle the name
9296  * "-" as a special case: it makes changes to "set +-options" local
9297  * (options will be restored on return from the function).
9298  */
9299 static void
9300 mklocal(char *name)
9301 {
9302         struct localvar *lvp;
9303         struct var **vpp;
9304         struct var *vp;
9305         char *eq = strchr(name, '=');
9306
9307         INT_OFF;
9308         /* Cater for duplicate "local". Examples:
9309          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9310          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9311          */
9312         lvp = localvars;
9313         while (lvp) {
9314                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9315                         if (eq)
9316                                 setvareq(name, 0);
9317                         /* else:
9318                          * it's a duplicate "local VAR" declaration, do nothing
9319                          */
9320                         goto ret;
9321                 }
9322                 lvp = lvp->next;
9323         }
9324
9325         lvp = ckzalloc(sizeof(*lvp));
9326         if (LONE_DASH(name)) {
9327                 char *p;
9328                 p = ckmalloc(sizeof(optlist));
9329                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9330                 vp = NULL;
9331         } else {
9332                 vpp = hashvar(name);
9333                 vp = *findvar(vpp, name);
9334                 if (vp == NULL) {
9335                         /* variable did not exist yet */
9336                         if (eq)
9337                                 setvareq(name, VSTRFIXED);
9338                         else
9339                                 setvar(name, NULL, VSTRFIXED);
9340                         vp = *vpp;      /* the new variable */
9341                         lvp->flags = VUNSET;
9342                 } else {
9343                         lvp->text = vp->var_text;
9344                         lvp->flags = vp->flags;
9345                         /* make sure neither "struct var" nor string gets freed
9346                          * during (un)setting:
9347                          */
9348                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9349                         if (eq)
9350                                 setvareq(name, 0);
9351                         else
9352                                 /* "local VAR" unsets VAR: */
9353                                 setvar0(name, NULL);
9354                 }
9355         }
9356         lvp->vp = vp;
9357         lvp->next = localvars;
9358         localvars = lvp;
9359  ret:
9360         INT_ON;
9361 }
9362
9363 /*
9364  * The "local" command.
9365  */
9366 static int FAST_FUNC
9367 localcmd(int argc UNUSED_PARAM, char **argv)
9368 {
9369         char *name;
9370
9371         if (!funcnest)
9372                 ash_msg_and_raise_error("not in a function");
9373
9374         argv = argptr;
9375         while ((name = *argv++) != NULL) {
9376                 mklocal(name);
9377         }
9378         return 0;
9379 }
9380
9381 static int FAST_FUNC
9382 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9383 {
9384         return 1;
9385 }
9386
9387 static int FAST_FUNC
9388 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9389 {
9390         return 0;
9391 }
9392
9393 static int FAST_FUNC
9394 execcmd(int argc UNUSED_PARAM, char **argv)
9395 {
9396         optionarg = NULL;
9397         while (nextopt("a:") != '\0')
9398                 /* nextopt() sets optionarg to "-a ARGV0" */;
9399
9400         argv = argptr;
9401         if (argv[0]) {
9402                 char *prog;
9403
9404                 iflag = 0;              /* exit on error */
9405                 mflag = 0;
9406                 optschanged();
9407                 /* We should set up signals for "exec CMD"
9408                  * the same way as for "CMD" without "exec".
9409                  * But optschanged->setinteractive->setsignal
9410                  * still thought we are a root shell. Therefore, for example,
9411                  * SIGQUIT is still set to IGN. Fix it:
9412                  */
9413                 shlvl++;
9414                 setsignal(SIGQUIT);
9415                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9416                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9417                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9418
9419                 prog = argv[0];
9420                 if (optionarg)
9421                         argv[0] = optionarg;
9422                 shellexec(prog, argv, pathval(), 0);
9423                 /* NOTREACHED */
9424         }
9425         return 0;
9426 }
9427
9428 /*
9429  * The return command.
9430  */
9431 static int FAST_FUNC
9432 returncmd(int argc UNUSED_PARAM, char **argv)
9433 {
9434         /*
9435          * If called outside a function, do what ksh does;
9436          * skip the rest of the file.
9437          */
9438         evalskip = SKIPFUNC;
9439         return argv[1] ? number(argv[1]) : exitstatus;
9440 }
9441
9442 /* Forward declarations for builtintab[] */
9443 static int breakcmd(int, char **) FAST_FUNC;
9444 static int dotcmd(int, char **) FAST_FUNC;
9445 static int evalcmd(int, char **, int) FAST_FUNC;
9446 static int exitcmd(int, char **) FAST_FUNC;
9447 static int exportcmd(int, char **) FAST_FUNC;
9448 #if ENABLE_ASH_GETOPTS
9449 static int getoptscmd(int, char **) FAST_FUNC;
9450 #endif
9451 #if ENABLE_ASH_HELP
9452 static int helpcmd(int, char **) FAST_FUNC;
9453 #endif
9454 #if MAX_HISTORY
9455 static int historycmd(int, char **) FAST_FUNC;
9456 #endif
9457 #if ENABLE_FEATURE_SH_MATH
9458 static int letcmd(int, char **) FAST_FUNC;
9459 #endif
9460 static int readcmd(int, char **) FAST_FUNC;
9461 static int setcmd(int, char **) FAST_FUNC;
9462 static int shiftcmd(int, char **) FAST_FUNC;
9463 static int timescmd(int, char **) FAST_FUNC;
9464 static int trapcmd(int, char **) FAST_FUNC;
9465 static int umaskcmd(int, char **) FAST_FUNC;
9466 static int unsetcmd(int, char **) FAST_FUNC;
9467 static int ulimitcmd(int, char **) FAST_FUNC;
9468
9469 #define BUILTIN_NOSPEC          "0"
9470 #define BUILTIN_SPECIAL         "1"
9471 #define BUILTIN_REGULAR         "2"
9472 #define BUILTIN_SPEC_REG        "3"
9473 #define BUILTIN_ASSIGN          "4"
9474 #define BUILTIN_SPEC_ASSG       "5"
9475 #define BUILTIN_REG_ASSG        "6"
9476 #define BUILTIN_SPEC_REG_ASSG   "7"
9477
9478 /* Stubs for calling non-FAST_FUNC's */
9479 #if ENABLE_ASH_ECHO
9480 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9481 #endif
9482 #if ENABLE_ASH_PRINTF
9483 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9484 #endif
9485 #if ENABLE_ASH_TEST || BASH_TEST2
9486 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9487 #endif
9488
9489 /* Keep these in proper order since it is searched via bsearch() */
9490 static const struct builtincmd builtintab[] = {
9491         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9492         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9493 #if ENABLE_ASH_TEST
9494         { BUILTIN_REGULAR       "["       , testcmd    },
9495 #endif
9496 #if BASH_TEST2
9497         { BUILTIN_REGULAR       "[["      , testcmd    },
9498 #endif
9499 #if ENABLE_ASH_ALIAS
9500         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9501 #endif
9502 #if JOBS
9503         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9504 #endif
9505         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9506         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9507         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9508 #if ENABLE_ASH_CMDCMD
9509         { BUILTIN_REGULAR       "command" , commandcmd },
9510 #endif
9511         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9512 #if ENABLE_ASH_ECHO
9513         { BUILTIN_REGULAR       "echo"    , echocmd    },
9514 #endif
9515         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9516         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9517         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9518         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9519         { BUILTIN_REGULAR       "false"   , falsecmd   },
9520 #if JOBS
9521         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9522 #endif
9523 #if ENABLE_ASH_GETOPTS
9524         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9525 #endif
9526         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9527 #if ENABLE_ASH_HELP
9528         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9529 #endif
9530 #if MAX_HISTORY
9531         { BUILTIN_NOSPEC        "history" , historycmd },
9532 #endif
9533 #if JOBS
9534         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9535         { BUILTIN_REGULAR       "kill"    , killcmd    },
9536 #endif
9537 #if ENABLE_FEATURE_SH_MATH
9538         { BUILTIN_NOSPEC        "let"     , letcmd     },
9539 #endif
9540         { BUILTIN_ASSIGN        "local"   , localcmd   },
9541 #if ENABLE_ASH_PRINTF
9542         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9543 #endif
9544         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9545         { BUILTIN_REGULAR       "read"    , readcmd    },
9546         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9547         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9548         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9549         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9550 #if BASH_SOURCE
9551         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9552 #endif
9553 #if ENABLE_ASH_TEST
9554         { BUILTIN_REGULAR       "test"    , testcmd    },
9555 #endif
9556         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9557         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9558         { BUILTIN_REGULAR       "true"    , truecmd    },
9559         { BUILTIN_NOSPEC        "type"    , typecmd    },
9560         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9561         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9562 #if ENABLE_ASH_ALIAS
9563         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9564 #endif
9565         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9566         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9567 };
9568
9569 /* Should match the above table! */
9570 #define COMMANDCMD (builtintab + \
9571         /* . : */       2 + \
9572         /* [ */         1 * ENABLE_ASH_TEST + \
9573         /* [[ */        1 * BASH_TEST2 + \
9574         /* alias */     1 * ENABLE_ASH_ALIAS + \
9575         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9576         /* break cd cddir  */   3)
9577 #define EVALCMD (COMMANDCMD + \
9578         /* command */   1 * ENABLE_ASH_CMDCMD + \
9579         /* continue */  1 + \
9580         /* echo */      1 * ENABLE_ASH_ECHO + \
9581         0)
9582 #define EXECCMD (EVALCMD + \
9583         /* eval */      1)
9584
9585 /*
9586  * Search the table of builtin commands.
9587  */
9588 static int
9589 pstrcmp1(const void *a, const void *b)
9590 {
9591         return strcmp((char*)a, *(char**)b + 1);
9592 }
9593 static struct builtincmd *
9594 find_builtin(const char *name)
9595 {
9596         struct builtincmd *bp;
9597
9598         bp = bsearch(
9599                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9600                 pstrcmp1
9601         );
9602         return bp;
9603 }
9604
9605 /*
9606  * Execute a simple command.
9607  */
9608 static int
9609 isassignment(const char *p)
9610 {
9611         const char *q = endofname(p);
9612         if (p == q)
9613                 return 0;
9614         return *q == '=';
9615 }
9616 static int FAST_FUNC
9617 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9618 {
9619         /* Preserve exitstatus of a previous possible redirection
9620          * as POSIX mandates */
9621         return back_exitstatus;
9622 }
9623 static int
9624 evalcommand(union node *cmd, int flags)
9625 {
9626         static const struct builtincmd null_bltin = {
9627                 "\0\0", bltincmd /* why three NULs? */
9628         };
9629         struct stackmark smark;
9630         union node *argp;
9631         struct arglist arglist;
9632         struct arglist varlist;
9633         char **argv;
9634         int argc;
9635         const struct strlist *sp;
9636         struct cmdentry cmdentry;
9637         struct job *jp;
9638         char *lastarg;
9639         const char *path;
9640         int spclbltin;
9641         int status;
9642         char **nargv;
9643         struct builtincmd *bcmd;
9644         smallint cmd_is_exec;
9645         smallint pseudovarflag = 0;
9646
9647         /* First expand the arguments. */
9648         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9649         setstackmark(&smark);
9650         back_exitstatus = 0;
9651
9652         cmdentry.cmdtype = CMDBUILTIN;
9653         cmdentry.u.cmd = &null_bltin;
9654         varlist.lastp = &varlist.list;
9655         *varlist.lastp = NULL;
9656         arglist.lastp = &arglist.list;
9657         *arglist.lastp = NULL;
9658
9659         argc = 0;
9660         if (cmd->ncmd.args) {
9661                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9662                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9663         }
9664
9665         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9666                 struct strlist **spp;
9667
9668                 spp = arglist.lastp;
9669                 if (pseudovarflag && isassignment(argp->narg.text))
9670                         expandarg(argp, &arglist, EXP_VARTILDE);
9671                 else
9672                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9673
9674                 for (sp = *spp; sp; sp = sp->next)
9675                         argc++;
9676         }
9677
9678         /* Reserve one extra spot at the front for shellexec. */
9679         nargv = stalloc(sizeof(char *) * (argc + 2));
9680         argv = ++nargv;
9681         for (sp = arglist.list; sp; sp = sp->next) {
9682                 TRACE(("evalcommand arg: %s\n", sp->text));
9683                 *nargv++ = sp->text;
9684         }
9685         *nargv = NULL;
9686
9687         lastarg = NULL;
9688         if (iflag && funcnest == 0 && argc > 0)
9689                 lastarg = nargv[-1];
9690
9691         preverrout_fd = 2;
9692         expredir(cmd->ncmd.redirect);
9693         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9694
9695         path = vpath.var_text;
9696         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9697                 struct strlist **spp;
9698                 char *p;
9699
9700                 spp = varlist.lastp;
9701                 expandarg(argp, &varlist, EXP_VARTILDE);
9702
9703                 /*
9704                  * Modify the command lookup path, if a PATH= assignment
9705                  * is present
9706                  */
9707                 p = (*spp)->text;
9708                 if (varcmp(p, path) == 0)
9709                         path = p;
9710         }
9711
9712         /* Print the command if xflag is set. */
9713         if (xflag) {
9714                 const char *pfx = "";
9715
9716                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9717
9718                 sp = varlist.list;
9719                 while (sp) {
9720                         char *varval = sp->text;
9721                         char *eq = strchrnul(varval, '=');
9722                         if (*eq)
9723                                 eq++;
9724                         fdprintf(preverrout_fd, "%s%.*s%s",
9725                                 pfx,
9726                                 (int)(eq - varval), varval,
9727                                 maybe_single_quote(eq)
9728                         );
9729                         sp = sp->next;
9730                         pfx = " ";
9731                 }
9732
9733                 sp = arglist.list;
9734                 while (sp) {
9735                         fdprintf(preverrout_fd, "%s%s",
9736                                 pfx,
9737                                 /* always quote if matches reserved word: */
9738                                 findkwd(sp->text)
9739                                 ? single_quote(sp->text)
9740                                 : maybe_single_quote(sp->text)
9741                         );
9742                         sp = sp->next;
9743                         pfx = " ";
9744                 }
9745                 safe_write(preverrout_fd, "\n", 1);
9746         }
9747
9748         cmd_is_exec = 0;
9749         spclbltin = -1;
9750
9751         /* Now locate the command. */
9752         if (argc) {
9753                 int cmd_flag = DO_ERR;
9754 #if ENABLE_ASH_CMDCMD
9755                 const char *oldpath = path + 5;
9756 #endif
9757                 path += 5;
9758                 for (;;) {
9759                         find_command(argv[0], &cmdentry, cmd_flag, path);
9760                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9761                                 flush_stdout_stderr();
9762                                 status = 127;
9763                                 goto bail;
9764                         }
9765
9766                         /* implement bltin and command here */
9767                         if (cmdentry.cmdtype != CMDBUILTIN)
9768                                 break;
9769                         if (spclbltin < 0)
9770                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9771                         if (cmdentry.u.cmd == EXECCMD)
9772                                 cmd_is_exec = 1;
9773 #if ENABLE_ASH_CMDCMD
9774                         if (cmdentry.u.cmd == COMMANDCMD) {
9775                                 path = oldpath;
9776                                 nargv = parse_command_args(argv, &path);
9777                                 if (!nargv)
9778                                         break;
9779                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9780                                  * nargv => "PROG". path is updated if -p.
9781                                  */
9782                                 argc -= nargv - argv;
9783                                 argv = nargv;
9784                                 cmd_flag |= DO_NOFUNC;
9785                         } else
9786 #endif
9787                                 break;
9788                 }
9789         }
9790
9791         if (status) {
9792  bail:
9793                 exitstatus = status;
9794
9795                 /* We have a redirection error. */
9796                 if (spclbltin > 0)
9797                         raise_exception(EXERROR);
9798
9799                 goto out;
9800         }
9801
9802         /* Execute the command. */
9803         switch (cmdentry.cmdtype) {
9804         default: {
9805
9806 #if ENABLE_FEATURE_SH_NOFORK
9807 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9808  *     around run_nofork_applet() call.
9809  * (2) Should this check also be done in forkshell()?
9810  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9811  */
9812                 /* find_command() encodes applet_no as (-2 - applet_no) */
9813                 int applet_no = (- cmdentry.u.index - 2);
9814                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9815                         listsetvar(varlist.list, VEXPORT|VSTACK);
9816                         /* run <applet>_main() */
9817                         status = run_nofork_applet(applet_no, argv);
9818                         break;
9819                 }
9820 #endif
9821                 /* Can we avoid forking off? For example, very last command
9822                  * in a script or a subshell does not need forking,
9823                  * we can just exec it.
9824                  */
9825                 if (!(flags & EV_EXIT) || may_have_traps) {
9826                         /* No, forking off a child is necessary */
9827                         INT_OFF;
9828                         get_tty_state();
9829                         jp = makejob(/*cmd,*/ 1);
9830                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9831                                 /* parent */
9832                                 status = waitforjob(jp);
9833                                 INT_ON;
9834                                 TRACE(("forked child exited with %d\n", status));
9835                                 break;
9836                         }
9837                         /* child */
9838                         FORCE_INT_ON;
9839                         /* fall through to exec'ing external program */
9840                 }
9841                 listsetvar(varlist.list, VEXPORT|VSTACK);
9842                 shellexec(argv[0], argv, path, cmdentry.u.index);
9843                 /* NOTREACHED */
9844         } /* default */
9845         case CMDBUILTIN:
9846                 cmdenviron = varlist.list;
9847                 if (cmdenviron) {
9848                         struct strlist *list = cmdenviron;
9849                         int i = VNOSET;
9850                         if (spclbltin > 0 || argc == 0) {
9851                                 i = 0;
9852                                 if (cmd_is_exec && argc > 1)
9853                                         i = VEXPORT;
9854                         }
9855                         listsetvar(list, i);
9856                 }
9857                 /* Tight loop with builtins only:
9858                  * "while kill -0 $child; do true; done"
9859                  * will never exit even if $child died, unless we do this
9860                  * to reap the zombie and make kill detect that it's gone: */
9861                 dowait(DOWAIT_NONBLOCK, NULL);
9862
9863                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9864                         if (exception_type == EXERROR && spclbltin <= 0) {
9865                                 FORCE_INT_ON;
9866                                 goto readstatus;
9867                         }
9868  raise:
9869                         longjmp(exception_handler->loc, 1);
9870                 }
9871                 goto readstatus;
9872
9873         case CMDFUNCTION:
9874                 listsetvar(varlist.list, 0);
9875                 /* See above for the rationale */
9876                 dowait(DOWAIT_NONBLOCK, NULL);
9877                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9878                         goto raise;
9879  readstatus:
9880                 status = exitstatus;
9881                 break;
9882         } /* switch */
9883
9884  out:
9885         if (cmd->ncmd.redirect)
9886                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9887         if (lastarg) {
9888                 /* dsl: I think this is intended to be used to support
9889                  * '_' in 'vi' command mode during line editing...
9890                  * However I implemented that within libedit itself.
9891                  */
9892                 setvar0("_", lastarg);
9893         }
9894         popstackmark(&smark);
9895
9896         return status;
9897 }
9898
9899 static int
9900 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9901 {
9902         char *volatile savecmdname;
9903         struct jmploc *volatile savehandler;
9904         struct jmploc jmploc;
9905         int status;
9906         int i;
9907
9908         savecmdname = commandname;
9909         savehandler = exception_handler;
9910         i = setjmp(jmploc.loc);
9911         if (i)
9912                 goto cmddone;
9913         exception_handler = &jmploc;
9914         commandname = argv[0];
9915         argptr = argv + 1;
9916         optptr = NULL;                  /* initialize nextopt */
9917         if (cmd == EVALCMD)
9918                 status = evalcmd(argc, argv, flags);
9919         else
9920                 status = (*cmd->builtin)(argc, argv);
9921         flush_stdout_stderr();
9922         status |= ferror(stdout);
9923         exitstatus = status;
9924  cmddone:
9925         clearerr(stdout);
9926         commandname = savecmdname;
9927         exception_handler = savehandler;
9928
9929         return i;
9930 }
9931
9932 static int
9933 goodname(const char *p)
9934 {
9935         return endofname(p)[0] == '\0';
9936 }
9937
9938
9939 /*
9940  * Search for a command.  This is called before we fork so that the
9941  * location of the command will be available in the parent as well as
9942  * the child.  The check for "goodname" is an overly conservative
9943  * check that the name will not be subject to expansion.
9944  */
9945 static void
9946 prehash(union node *n)
9947 {
9948         struct cmdentry entry;
9949
9950         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9951                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9952 }
9953
9954
9955 /* ============ Builtin commands
9956  *
9957  * Builtin commands whose functions are closely tied to evaluation
9958  * are implemented here.
9959  */
9960
9961 /*
9962  * Handle break and continue commands.  Break, continue, and return are
9963  * all handled by setting the evalskip flag.  The evaluation routines
9964  * above all check this flag, and if it is set they start skipping
9965  * commands rather than executing them.  The variable skipcount is
9966  * the number of loops to break/continue, or the number of function
9967  * levels to return.  (The latter is always 1.)  It should probably
9968  * be an error to break out of more loops than exist, but it isn't
9969  * in the standard shell so we don't make it one here.
9970  */
9971 static int FAST_FUNC
9972 breakcmd(int argc UNUSED_PARAM, char **argv)
9973 {
9974         int n = argv[1] ? number(argv[1]) : 1;
9975
9976         if (n <= 0)
9977                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9978         if (n > loopnest)
9979                 n = loopnest;
9980         if (n > 0) {
9981                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9982                 skipcount = n;
9983         }
9984         return 0;
9985 }
9986
9987
9988 /*
9989  * This implements the input routines used by the parser.
9990  */
9991
9992 enum {
9993         INPUT_PUSH_FILE = 1,
9994         INPUT_NOFILE_OK = 2,
9995 };
9996
9997 static smallint checkkwd;
9998 /* values of checkkwd variable */
9999 #define CHKALIAS        0x1
10000 #define CHKKWD          0x2
10001 #define CHKNL           0x4
10002
10003 /*
10004  * Push a string back onto the input at this current parsefile level.
10005  * We handle aliases this way.
10006  */
10007 #if !ENABLE_ASH_ALIAS
10008 #define pushstring(s, ap) pushstring(s)
10009 #endif
10010 static void
10011 pushstring(char *s, struct alias *ap)
10012 {
10013         struct strpush *sp;
10014         int len;
10015
10016         len = strlen(s);
10017         INT_OFF;
10018         if (g_parsefile->strpush) {
10019                 sp = ckzalloc(sizeof(*sp));
10020                 sp->prev = g_parsefile->strpush;
10021         } else {
10022                 sp = &(g_parsefile->basestrpush);
10023         }
10024         g_parsefile->strpush = sp;
10025         sp->prev_string = g_parsefile->next_to_pgetc;
10026         sp->prev_left_in_line = g_parsefile->left_in_line;
10027         sp->unget = g_parsefile->unget;
10028         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10029 #if ENABLE_ASH_ALIAS
10030         sp->ap = ap;
10031         if (ap) {
10032                 ap->flag |= ALIASINUSE;
10033                 sp->string = s;
10034         }
10035 #endif
10036         g_parsefile->next_to_pgetc = s;
10037         g_parsefile->left_in_line = len;
10038         g_parsefile->unget = 0;
10039         INT_ON;
10040 }
10041
10042 static void
10043 popstring(void)
10044 {
10045         struct strpush *sp = g_parsefile->strpush;
10046
10047         INT_OFF;
10048 #if ENABLE_ASH_ALIAS
10049         if (sp->ap) {
10050                 if (g_parsefile->next_to_pgetc[-1] == ' '
10051                  || g_parsefile->next_to_pgetc[-1] == '\t'
10052                 ) {
10053                         checkkwd |= CHKALIAS;
10054                 }
10055                 if (sp->string != sp->ap->val) {
10056                         free(sp->string);
10057                 }
10058                 sp->ap->flag &= ~ALIASINUSE;
10059                 if (sp->ap->flag & ALIASDEAD) {
10060                         unalias(sp->ap->name);
10061                 }
10062         }
10063 #endif
10064         g_parsefile->next_to_pgetc = sp->prev_string;
10065         g_parsefile->left_in_line = sp->prev_left_in_line;
10066         g_parsefile->unget = sp->unget;
10067         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10068         g_parsefile->strpush = sp->prev;
10069         if (sp != &(g_parsefile->basestrpush))
10070                 free(sp);
10071         INT_ON;
10072 }
10073
10074 static int
10075 preadfd(void)
10076 {
10077         int nr;
10078         char *buf = g_parsefile->buf;
10079
10080         g_parsefile->next_to_pgetc = buf;
10081 #if ENABLE_FEATURE_EDITING
10082  retry:
10083         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10084                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10085         else {
10086                 int timeout = -1;
10087 # if ENABLE_ASH_IDLE_TIMEOUT
10088                 if (iflag) {
10089                         const char *tmout_var = lookupvar("TMOUT");
10090                         if (tmout_var) {
10091                                 timeout = atoi(tmout_var) * 1000;
10092                                 if (timeout <= 0)
10093                                         timeout = -1;
10094                         }
10095                 }
10096 # endif
10097 # if ENABLE_FEATURE_TAB_COMPLETION
10098                 line_input_state->path_lookup = pathval();
10099 # endif
10100                 reinit_unicode_for_ash();
10101                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10102                 if (nr == 0) {
10103                         /* ^C pressed, "convert" to SIGINT */
10104                         write(STDOUT_FILENO, "^C", 2);
10105                         if (trap[SIGINT]) {
10106                                 buf[0] = '\n';
10107                                 buf[1] = '\0';
10108                                 raise(SIGINT);
10109                                 return 1;
10110                         }
10111                         exitstatus = 128 + SIGINT;
10112                         bb_putchar('\n');
10113                         goto retry;
10114                 }
10115                 if (nr < 0) {
10116                         if (errno == 0) {
10117                                 /* Ctrl+D pressed */
10118                                 nr = 0;
10119                         }
10120 # if ENABLE_ASH_IDLE_TIMEOUT
10121                         else if (errno == EAGAIN && timeout > 0) {
10122                                 puts("\007timed out waiting for input: auto-logout");
10123                                 exitshell();
10124                         }
10125 # endif
10126                 }
10127         }
10128 #else
10129         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10130 #endif
10131
10132 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10133         if (nr < 0) {
10134                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10135                         int flags = fcntl(0, F_GETFL);
10136                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10137                                 flags &= ~O_NONBLOCK;
10138                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10139                                         out2str("sh: turning off NDELAY mode\n");
10140                                         goto retry;
10141                                 }
10142                         }
10143                 }
10144         }
10145 #endif
10146         return nr;
10147 }
10148
10149 /*
10150  * Refill the input buffer and return the next input character:
10151  *
10152  * 1) If a string was pushed back on the input, pop it;
10153  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10154  *    or we are reading from a string so we can't refill the buffer,
10155  *    return EOF.
10156  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10157  * 4) Process input up to the next newline, deleting nul characters.
10158  */
10159 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10160 #define pgetc_debug(...) ((void)0)
10161 static int pgetc(void);
10162 static int
10163 preadbuffer(void)
10164 {
10165         char *q;
10166         int more;
10167
10168         if (g_parsefile->strpush) {
10169 #if ENABLE_ASH_ALIAS
10170                 if (g_parsefile->left_in_line == -1
10171                  && g_parsefile->strpush->ap
10172                  && g_parsefile->next_to_pgetc[-1] != ' '
10173                  && g_parsefile->next_to_pgetc[-1] != '\t'
10174                 ) {
10175                         pgetc_debug("preadbuffer PEOA");
10176                         return PEOA;
10177                 }
10178 #endif
10179                 popstring();
10180                 return pgetc();
10181         }
10182         /* on both branches above g_parsefile->left_in_line < 0.
10183          * "pgetc" needs refilling.
10184          */
10185
10186         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10187          * pungetc() may increment it a few times.
10188          * Assuming it won't increment it to less than -90.
10189          */
10190         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10191                 pgetc_debug("preadbuffer PEOF1");
10192                 /* even in failure keep left_in_line and next_to_pgetc
10193                  * in lock step, for correct multi-layer pungetc.
10194                  * left_in_line was decremented before preadbuffer(),
10195                  * must inc next_to_pgetc: */
10196                 g_parsefile->next_to_pgetc++;
10197                 return PEOF;
10198         }
10199
10200         more = g_parsefile->left_in_buffer;
10201         if (more <= 0) {
10202                 flush_stdout_stderr();
10203  again:
10204                 more = preadfd();
10205                 if (more <= 0) {
10206                         /* don't try reading again */
10207                         g_parsefile->left_in_line = -99;
10208                         pgetc_debug("preadbuffer PEOF2");
10209                         g_parsefile->next_to_pgetc++;
10210                         return PEOF;
10211                 }
10212         }
10213
10214         /* Find out where's the end of line.
10215          * Set g_parsefile->left_in_line
10216          * and g_parsefile->left_in_buffer acordingly.
10217          * NUL chars are deleted.
10218          */
10219         q = g_parsefile->next_to_pgetc;
10220         for (;;) {
10221                 char c;
10222
10223                 more--;
10224
10225                 c = *q;
10226                 if (c == '\0') {
10227                         memmove(q, q + 1, more);
10228                 } else {
10229                         q++;
10230                         if (c == '\n') {
10231                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10232                                 break;
10233                         }
10234                 }
10235
10236                 if (more <= 0) {
10237                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10238                         if (g_parsefile->left_in_line < 0)
10239                                 goto again;
10240                         break;
10241                 }
10242         }
10243         g_parsefile->left_in_buffer = more;
10244
10245         if (vflag) {
10246                 char save = *q;
10247                 *q = '\0';
10248                 out2str(g_parsefile->next_to_pgetc);
10249                 *q = save;
10250         }
10251
10252         pgetc_debug("preadbuffer at %d:%p'%s'",
10253                         g_parsefile->left_in_line,
10254                         g_parsefile->next_to_pgetc,
10255                         g_parsefile->next_to_pgetc);
10256         return (unsigned char)*g_parsefile->next_to_pgetc++;
10257 }
10258
10259 static void
10260 nlprompt(void)
10261 {
10262         g_parsefile->linno++;
10263         setprompt_if(doprompt, 2);
10264 }
10265 static void
10266 nlnoprompt(void)
10267 {
10268         g_parsefile->linno++;
10269         needprompt = doprompt;
10270 }
10271
10272 static int
10273 pgetc(void)
10274 {
10275         int c;
10276
10277         pgetc_debug("pgetc at %d:%p'%s'",
10278                         g_parsefile->left_in_line,
10279                         g_parsefile->next_to_pgetc,
10280                         g_parsefile->next_to_pgetc);
10281         if (g_parsefile->unget)
10282                 return g_parsefile->lastc[--g_parsefile->unget];
10283
10284         if (--g_parsefile->left_in_line >= 0)
10285                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10286         else
10287                 c = preadbuffer();
10288
10289         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10290         g_parsefile->lastc[0] = c;
10291
10292         return c;
10293 }
10294
10295 #if ENABLE_ASH_ALIAS
10296 static int
10297 pgetc_without_PEOA(void)
10298 {
10299         int c;
10300         do {
10301                 pgetc_debug("pgetc at %d:%p'%s'",
10302                                 g_parsefile->left_in_line,
10303                                 g_parsefile->next_to_pgetc,
10304                                 g_parsefile->next_to_pgetc);
10305                 c = pgetc();
10306         } while (c == PEOA);
10307         return c;
10308 }
10309 #else
10310 # define pgetc_without_PEOA() pgetc()
10311 #endif
10312
10313 /*
10314  * Read a line from the script.
10315  */
10316 static char *
10317 pfgets(char *line, int len)
10318 {
10319         char *p = line;
10320         int nleft = len;
10321         int c;
10322
10323         while (--nleft > 0) {
10324                 c = pgetc_without_PEOA();
10325                 if (c == PEOF) {
10326                         if (p == line)
10327                                 return NULL;
10328                         break;
10329                 }
10330                 *p++ = c;
10331                 if (c == '\n')
10332                         break;
10333         }
10334         *p = '\0';
10335         return line;
10336 }
10337
10338 /*
10339  * Undo a call to pgetc.  Only two characters may be pushed back.
10340  * PEOF may be pushed back.
10341  */
10342 static void
10343 pungetc(void)
10344 {
10345         g_parsefile->unget++;
10346 }
10347
10348 /* This one eats backslash+newline */
10349 static int
10350 pgetc_eatbnl(void)
10351 {
10352         int c;
10353
10354         while ((c = pgetc()) == '\\') {
10355                 if (pgetc() != '\n') {
10356                         pungetc();
10357                         break;
10358                 }
10359
10360                 nlprompt();
10361         }
10362
10363         return c;
10364 }
10365
10366 /*
10367  * To handle the "." command, a stack of input files is used.  Pushfile
10368  * adds a new entry to the stack and popfile restores the previous level.
10369  */
10370 static void
10371 pushfile(void)
10372 {
10373         struct parsefile *pf;
10374
10375         pf = ckzalloc(sizeof(*pf));
10376         pf->prev = g_parsefile;
10377         pf->pf_fd = -1;
10378         /*pf->strpush = NULL; - ckzalloc did it */
10379         /*pf->basestrpush.prev = NULL;*/
10380         /*pf->unget = 0;*/
10381         g_parsefile = pf;
10382 }
10383
10384 static void
10385 popfile(void)
10386 {
10387         struct parsefile *pf = g_parsefile;
10388
10389         if (pf == &basepf)
10390                 return;
10391
10392         INT_OFF;
10393         if (pf->pf_fd >= 0)
10394                 close(pf->pf_fd);
10395         free(pf->buf);
10396         while (pf->strpush)
10397                 popstring();
10398         g_parsefile = pf->prev;
10399         free(pf);
10400         INT_ON;
10401 }
10402
10403 /*
10404  * Return to top level.
10405  */
10406 static void
10407 popallfiles(void)
10408 {
10409         while (g_parsefile != &basepf)
10410                 popfile();
10411 }
10412
10413 /*
10414  * Close the file(s) that the shell is reading commands from.  Called
10415  * after a fork is done.
10416  */
10417 static void
10418 closescript(void)
10419 {
10420         popallfiles();
10421         if (g_parsefile->pf_fd > 0) {
10422                 close(g_parsefile->pf_fd);
10423                 g_parsefile->pf_fd = 0;
10424         }
10425 }
10426
10427 /*
10428  * Like setinputfile, but takes an open file descriptor.  Call this with
10429  * interrupts off.
10430  */
10431 static void
10432 setinputfd(int fd, int push)
10433 {
10434         if (push) {
10435                 pushfile();
10436                 g_parsefile->buf = NULL;
10437         }
10438         g_parsefile->pf_fd = fd;
10439         if (g_parsefile->buf == NULL)
10440                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10441         g_parsefile->left_in_buffer = 0;
10442         g_parsefile->left_in_line = 0;
10443         g_parsefile->linno = 1;
10444 }
10445
10446 /*
10447  * Set the input to take input from a file.  If push is set, push the
10448  * old input onto the stack first.
10449  */
10450 static int
10451 setinputfile(const char *fname, int flags)
10452 {
10453         int fd;
10454
10455         INT_OFF;
10456         fd = open(fname, O_RDONLY);
10457         if (fd < 0) {
10458                 if (flags & INPUT_NOFILE_OK)
10459                         goto out;
10460                 exitstatus = 127;
10461                 ash_msg_and_raise_error("can't open '%s'", fname);
10462         }
10463         if (fd < 10)
10464                 fd = savefd(fd);
10465         else
10466                 close_on_exec_on(fd);
10467         setinputfd(fd, flags & INPUT_PUSH_FILE);
10468  out:
10469         INT_ON;
10470         return fd;
10471 }
10472
10473 /*
10474  * Like setinputfile, but takes input from a string.
10475  */
10476 static void
10477 setinputstring(char *string)
10478 {
10479         INT_OFF;
10480         pushfile();
10481         g_parsefile->next_to_pgetc = string;
10482         g_parsefile->left_in_line = strlen(string);
10483         g_parsefile->buf = NULL;
10484         g_parsefile->linno = 1;
10485         INT_ON;
10486 }
10487
10488
10489 /*
10490  * Routines to check for mail.
10491  */
10492
10493 #if ENABLE_ASH_MAIL
10494
10495 /* Hash of mtimes of mailboxes */
10496 static unsigned mailtime_hash;
10497 /* Set if MAIL or MAILPATH is changed. */
10498 static smallint mail_var_path_changed;
10499
10500 /*
10501  * Print appropriate message(s) if mail has arrived.
10502  * If mail_var_path_changed is set,
10503  * then the value of MAIL has mail_var_path_changed,
10504  * so we just update the values.
10505  */
10506 static void
10507 chkmail(void)
10508 {
10509         const char *mpath;
10510         char *p;
10511         char *q;
10512         unsigned new_hash;
10513         struct stackmark smark;
10514         struct stat statb;
10515
10516         setstackmark(&smark);
10517         mpath = mpathset() ? mpathval() : mailval();
10518         new_hash = 0;
10519         for (;;) {
10520                 p = path_advance(&mpath, nullstr);
10521                 if (p == NULL)
10522                         break;
10523                 if (*p == '\0')
10524                         continue;
10525                 for (q = p; *q; q++)
10526                         continue;
10527 #if DEBUG
10528                 if (q[-1] != '/')
10529                         abort();
10530 #endif
10531                 q[-1] = '\0';                   /* delete trailing '/' */
10532                 if (stat(p, &statb) < 0) {
10533                         continue;
10534                 }
10535                 /* Very simplistic "hash": just a sum of all mtimes */
10536                 new_hash += (unsigned)statb.st_mtime;
10537         }
10538         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10539                 if (mailtime_hash != 0)
10540                         out2str("you have mail\n");
10541                 mailtime_hash = new_hash;
10542         }
10543         mail_var_path_changed = 0;
10544         popstackmark(&smark);
10545 }
10546
10547 static void FAST_FUNC
10548 changemail(const char *val UNUSED_PARAM)
10549 {
10550         mail_var_path_changed = 1;
10551 }
10552
10553 #endif /* ASH_MAIL */
10554
10555
10556 /* ============ ??? */
10557
10558 /*
10559  * Set the shell parameters.
10560  */
10561 static void
10562 setparam(char **argv)
10563 {
10564         char **newparam;
10565         char **ap;
10566         int nparam;
10567
10568         for (nparam = 0; argv[nparam]; nparam++)
10569                 continue;
10570         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10571         while (*argv) {
10572                 *ap++ = ckstrdup(*argv++);
10573         }
10574         *ap = NULL;
10575         freeparam(&shellparam);
10576         shellparam.malloced = 1;
10577         shellparam.nparam = nparam;
10578         shellparam.p = newparam;
10579 #if ENABLE_ASH_GETOPTS
10580         shellparam.optind = 1;
10581         shellparam.optoff = -1;
10582 #endif
10583 }
10584
10585 /*
10586  * Process shell options.  The global variable argptr contains a pointer
10587  * to the argument list; we advance it past the options.
10588  *
10589  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10590  * For a non-interactive shell, an error condition encountered
10591  * by a special built-in ... shall cause the shell to write a diagnostic message
10592  * to standard error and exit as shown in the following table:
10593  * Error                                           Special Built-In
10594  * ...
10595  * Utility syntax error (option or operand error)  Shall exit
10596  * ...
10597  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10598  * we see that bash does not do that (set "finishes" with error code 1 instead,
10599  * and shell continues), and people rely on this behavior!
10600  * Testcase:
10601  * set -o barfoo 2>/dev/null
10602  * echo $?
10603  *
10604  * Oh well. Let's mimic that.
10605  */
10606 static int
10607 plus_minus_o(char *name, int val)
10608 {
10609         int i;
10610
10611         if (name) {
10612                 for (i = 0; i < NOPTS; i++) {
10613                         if (strcmp(name, optnames(i)) == 0) {
10614                                 optlist[i] = val;
10615                                 return 0;
10616                         }
10617                 }
10618                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10619                 return 1;
10620         }
10621         for (i = 0; i < NOPTS; i++) {
10622                 if (val) {
10623                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10624                 } else {
10625                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10626                 }
10627         }
10628         return 0;
10629 }
10630 static void
10631 setoption(int flag, int val)
10632 {
10633         int i;
10634
10635         for (i = 0; i < NOPTS; i++) {
10636                 if (optletters(i) == flag) {
10637                         optlist[i] = val;
10638                         return;
10639                 }
10640         }
10641         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10642         /* NOTREACHED */
10643 }
10644 static int
10645 options(int cmdline)
10646 {
10647         char *p;
10648         int val;
10649         int c;
10650
10651         if (cmdline)
10652                 minusc = NULL;
10653         while ((p = *argptr) != NULL) {
10654                 c = *p++;
10655                 if (c != '-' && c != '+')
10656                         break;
10657                 argptr++;
10658                 val = 0; /* val = 0 if c == '+' */
10659                 if (c == '-') {
10660                         val = 1;
10661                         if (p[0] == '\0' || LONE_DASH(p)) {
10662                                 if (!cmdline) {
10663                                         /* "-" means turn off -x and -v */
10664                                         if (p[0] == '\0')
10665                                                 xflag = vflag = 0;
10666                                         /* "--" means reset params */
10667                                         else if (*argptr == NULL)
10668                                                 setparam(argptr);
10669                                 }
10670                                 break;    /* "-" or "--" terminates options */
10671                         }
10672                 }
10673                 /* first char was + or - */
10674                 while ((c = *p++) != '\0') {
10675                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10676                         if (c == 'c' && cmdline) {
10677                                 minusc = p;     /* command is after shell args */
10678                         } else if (c == 'o') {
10679                                 if (plus_minus_o(*argptr, val)) {
10680                                         /* it already printed err message */
10681                                         return 1; /* error */
10682                                 }
10683                                 if (*argptr)
10684                                         argptr++;
10685                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10686                                 isloginsh = 1;
10687                         /* bash does not accept +-login, we also won't */
10688                         } else if (cmdline && val && (c == '-')) { /* long options */
10689                                 if (strcmp(p, "login") == 0)
10690                                         isloginsh = 1;
10691                                 break;
10692                         } else {
10693                                 setoption(c, val);
10694                         }
10695                 }
10696         }
10697         return 0;
10698 }
10699
10700 /*
10701  * The shift builtin command.
10702  */
10703 static int FAST_FUNC
10704 shiftcmd(int argc UNUSED_PARAM, char **argv)
10705 {
10706         int n;
10707         char **ap1, **ap2;
10708
10709         n = 1;
10710         if (argv[1])
10711                 n = number(argv[1]);
10712         if (n > shellparam.nparam)
10713                 n = 0; /* bash compat, was = shellparam.nparam; */
10714         INT_OFF;
10715         shellparam.nparam -= n;
10716         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10717                 if (shellparam.malloced)
10718                         free(*ap1);
10719         }
10720         ap2 = shellparam.p;
10721         while ((*ap2++ = *ap1++) != NULL)
10722                 continue;
10723 #if ENABLE_ASH_GETOPTS
10724         shellparam.optind = 1;
10725         shellparam.optoff = -1;
10726 #endif
10727         INT_ON;
10728         return 0;
10729 }
10730
10731 /*
10732  * POSIX requires that 'set' (but not export or readonly) output the
10733  * variables in lexicographic order - by the locale's collating order (sigh).
10734  * Maybe we could keep them in an ordered balanced binary tree
10735  * instead of hashed lists.
10736  * For now just roll 'em through qsort for printing...
10737  */
10738 static int
10739 showvars(const char *sep_prefix, int on, int off)
10740 {
10741         const char *sep;
10742         char **ep, **epend;
10743
10744         ep = listvars(on, off, &epend);
10745         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10746
10747         sep = *sep_prefix ? " " : sep_prefix;
10748
10749         for (; ep < epend; ep++) {
10750                 const char *p;
10751                 const char *q;
10752
10753                 p = strchrnul(*ep, '=');
10754                 q = nullstr;
10755                 if (*p)
10756                         q = single_quote(++p);
10757                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10758         }
10759         return 0;
10760 }
10761
10762 /*
10763  * The set command builtin.
10764  */
10765 static int FAST_FUNC
10766 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10767 {
10768         int retval;
10769
10770         if (!argv[1])
10771                 return showvars(nullstr, 0, VUNSET);
10772
10773         INT_OFF;
10774         retval = options(/*cmdline:*/ 0);
10775         if (retval == 0) { /* if no parse error... */
10776                 optschanged();
10777                 if (*argptr != NULL) {
10778                         setparam(argptr);
10779                 }
10780         }
10781         INT_ON;
10782         return retval;
10783 }
10784
10785 #if ENABLE_ASH_RANDOM_SUPPORT
10786 static void FAST_FUNC
10787 change_random(const char *value)
10788 {
10789         uint32_t t;
10790
10791         if (value == NULL) {
10792                 /* "get", generate */
10793                 t = next_random(&random_gen);
10794                 /* set without recursion */
10795                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10796                 vrandom.flags &= ~VNOFUNC;
10797         } else {
10798                 /* set/reset */
10799                 t = strtoul(value, NULL, 10);
10800                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10801         }
10802 }
10803 #endif
10804
10805 #if ENABLE_ASH_GETOPTS
10806 static int
10807 getopts(char *optstr, char *optvar, char **optfirst)
10808 {
10809         char *p, *q;
10810         char c = '?';
10811         int done = 0;
10812         char sbuf[2];
10813         char **optnext;
10814         int ind = shellparam.optind;
10815         int off = shellparam.optoff;
10816
10817         sbuf[1] = '\0';
10818
10819         shellparam.optind = -1;
10820         optnext = optfirst + ind - 1;
10821
10822         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10823                 p = NULL;
10824         else
10825                 p = optnext[-1] + off;
10826         if (p == NULL || *p == '\0') {
10827                 /* Current word is done, advance */
10828                 p = *optnext;
10829                 if (p == NULL || *p != '-' || *++p == '\0') {
10830  atend:
10831                         p = NULL;
10832                         done = 1;
10833                         goto out;
10834                 }
10835                 optnext++;
10836                 if (LONE_DASH(p))        /* check for "--" */
10837                         goto atend;
10838         }
10839
10840         c = *p++;
10841         for (q = optstr; *q != c;) {
10842                 if (*q == '\0') {
10843                         if (optstr[0] == ':') {
10844                                 sbuf[0] = c;
10845                                 /*sbuf[1] = '\0'; - already is */
10846                                 setvar0("OPTARG", sbuf);
10847                         } else {
10848                                 fprintf(stderr, "Illegal option -%c\n", c);
10849                                 unsetvar("OPTARG");
10850                         }
10851                         c = '?';
10852                         goto out;
10853                 }
10854                 if (*++q == ':')
10855                         q++;
10856         }
10857
10858         if (*++q == ':') {
10859                 if (*p == '\0' && (p = *optnext) == NULL) {
10860                         if (optstr[0] == ':') {
10861                                 sbuf[0] = c;
10862                                 /*sbuf[1] = '\0'; - already is */
10863                                 setvar0("OPTARG", sbuf);
10864                                 c = ':';
10865                         } else {
10866                                 fprintf(stderr, "No arg for -%c option\n", c);
10867                                 unsetvar("OPTARG");
10868                                 c = '?';
10869                         }
10870                         goto out;
10871                 }
10872
10873                 if (p == *optnext)
10874                         optnext++;
10875                 setvar0("OPTARG", p);
10876                 p = NULL;
10877         } else
10878                 setvar0("OPTARG", nullstr);
10879  out:
10880         ind = optnext - optfirst + 1;
10881         setvar("OPTIND", itoa(ind), VNOFUNC);
10882         sbuf[0] = c;
10883         /*sbuf[1] = '\0'; - already is */
10884         setvar0(optvar, sbuf);
10885
10886         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10887         shellparam.optind = ind;
10888
10889         return done;
10890 }
10891
10892 /*
10893  * The getopts builtin.  Shellparam.optnext points to the next argument
10894  * to be processed.  Shellparam.optptr points to the next character to
10895  * be processed in the current argument.  If shellparam.optnext is NULL,
10896  * then it's the first time getopts has been called.
10897  */
10898 static int FAST_FUNC
10899 getoptscmd(int argc, char **argv)
10900 {
10901         char **optbase;
10902
10903         if (argc < 3)
10904                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10905         if (argc == 3) {
10906                 optbase = shellparam.p;
10907                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10908                         shellparam.optind = 1;
10909                         shellparam.optoff = -1;
10910                 }
10911         } else {
10912                 optbase = &argv[3];
10913                 if ((unsigned)shellparam.optind > argc - 2) {
10914                         shellparam.optind = 1;
10915                         shellparam.optoff = -1;
10916                 }
10917         }
10918
10919         return getopts(argv[1], argv[2], optbase);
10920 }
10921 #endif /* ASH_GETOPTS */
10922
10923
10924 /* ============ Shell parser */
10925
10926 struct heredoc {
10927         struct heredoc *next;   /* next here document in list */
10928         union node *here;       /* redirection node */
10929         char *eofmark;          /* string indicating end of input */
10930         smallint striptabs;     /* if set, strip leading tabs */
10931 };
10932
10933 static smallint tokpushback;           /* last token pushed back */
10934 static smallint quoteflag;             /* set if (part of) last token was quoted */
10935 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10936 static struct heredoc *heredoclist;    /* list of here documents to read */
10937 static char *wordtext;                 /* text of last word returned by readtoken */
10938 static struct nodelist *backquotelist;
10939 static union node *redirnode;
10940 static struct heredoc *heredoc;
10941
10942 static const char *
10943 tokname(char *buf, int tok)
10944 {
10945         if (tok < TSEMI)
10946                 return tokname_array[tok];
10947         sprintf(buf, "\"%s\"", tokname_array[tok]);
10948         return buf;
10949 }
10950
10951 /* raise_error_unexpected_syntax:
10952  * Called when an unexpected token is read during the parse.  The argument
10953  * is the token that is expected, or -1 if more than one type of token can
10954  * occur at this point.
10955  */
10956 static void raise_error_unexpected_syntax(int) NORETURN;
10957 static void
10958 raise_error_unexpected_syntax(int token)
10959 {
10960         char msg[64];
10961         char buf[16];
10962         int l;
10963
10964         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10965         if (token >= 0)
10966                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10967         raise_error_syntax(msg);
10968         /* NOTREACHED */
10969 }
10970
10971 #define EOFMARKLEN 79
10972
10973 /* parsing is heavily cross-recursive, need these forward decls */
10974 static union node *andor(void);
10975 static union node *pipeline(void);
10976 static union node *parse_command(void);
10977 static void parseheredoc(void);
10978 static int peektoken(void);
10979 static int readtoken(void);
10980
10981 static union node *
10982 list(int nlflag)
10983 {
10984         union node *n1, *n2, *n3;
10985         int tok;
10986
10987         n1 = NULL;
10988         for (;;) {
10989                 switch (peektoken()) {
10990                 case TNL:
10991                         if (!(nlflag & 1))
10992                                 break;
10993                         parseheredoc();
10994                         return n1;
10995
10996                 case TEOF:
10997                         if (!n1 && (nlflag & 1))
10998                                 n1 = NODE_EOF;
10999                         parseheredoc();
11000                         return n1;
11001                 }
11002
11003                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11004                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11005                         return n1;
11006                 nlflag |= 2;
11007
11008                 n2 = andor();
11009                 tok = readtoken();
11010                 if (tok == TBACKGND) {
11011                         if (n2->type == NPIPE) {
11012                                 n2->npipe.pipe_backgnd = 1;
11013                         } else {
11014                                 if (n2->type != NREDIR) {
11015                                         n3 = stzalloc(sizeof(struct nredir));
11016                                         n3->nredir.n = n2;
11017                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11018                                         n2 = n3;
11019                                 }
11020                                 n2->type = NBACKGND;
11021                         }
11022                 }
11023                 if (n1 == NULL) {
11024                         n1 = n2;
11025                 } else {
11026                         n3 = stzalloc(sizeof(struct nbinary));
11027                         n3->type = NSEMI;
11028                         n3->nbinary.ch1 = n1;
11029                         n3->nbinary.ch2 = n2;
11030                         n1 = n3;
11031                 }
11032                 switch (tok) {
11033                 case TNL:
11034                 case TEOF:
11035                         tokpushback = 1;
11036                         /* fall through */
11037                 case TBACKGND:
11038                 case TSEMI:
11039                         break;
11040                 default:
11041                         if ((nlflag & 1))
11042                                 raise_error_unexpected_syntax(-1);
11043                         tokpushback = 1;
11044                         return n1;
11045                 }
11046         }
11047 }
11048
11049 static union node *
11050 andor(void)
11051 {
11052         union node *n1, *n2, *n3;
11053         int t;
11054
11055         n1 = pipeline();
11056         for (;;) {
11057                 t = readtoken();
11058                 if (t == TAND) {
11059                         t = NAND;
11060                 } else if (t == TOR) {
11061                         t = NOR;
11062                 } else {
11063                         tokpushback = 1;
11064                         return n1;
11065                 }
11066                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11067                 n2 = pipeline();
11068                 n3 = stzalloc(sizeof(struct nbinary));
11069                 n3->type = t;
11070                 n3->nbinary.ch1 = n1;
11071                 n3->nbinary.ch2 = n2;
11072                 n1 = n3;
11073         }
11074 }
11075
11076 static union node *
11077 pipeline(void)
11078 {
11079         union node *n1, *n2, *pipenode;
11080         struct nodelist *lp, *prev;
11081         int negate;
11082
11083         negate = 0;
11084         TRACE(("pipeline: entered\n"));
11085         if (readtoken() == TNOT) {
11086                 negate = !negate;
11087                 checkkwd = CHKKWD | CHKALIAS;
11088         } else
11089                 tokpushback = 1;
11090         n1 = parse_command();
11091         if (readtoken() == TPIPE) {
11092                 pipenode = stzalloc(sizeof(struct npipe));
11093                 pipenode->type = NPIPE;
11094                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11095                 lp = stzalloc(sizeof(struct nodelist));
11096                 pipenode->npipe.cmdlist = lp;
11097                 lp->n = n1;
11098                 do {
11099                         prev = lp;
11100                         lp = stzalloc(sizeof(struct nodelist));
11101                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11102                         lp->n = parse_command();
11103                         prev->next = lp;
11104                 } while (readtoken() == TPIPE);
11105                 lp->next = NULL;
11106                 n1 = pipenode;
11107         }
11108         tokpushback = 1;
11109         if (negate) {
11110                 n2 = stzalloc(sizeof(struct nnot));
11111                 n2->type = NNOT;
11112                 n2->nnot.com = n1;
11113                 return n2;
11114         }
11115         return n1;
11116 }
11117
11118 static union node *
11119 makename(void)
11120 {
11121         union node *n;
11122
11123         n = stzalloc(sizeof(struct narg));
11124         n->type = NARG;
11125         /*n->narg.next = NULL; - stzalloc did it */
11126         n->narg.text = wordtext;
11127         n->narg.backquote = backquotelist;
11128         return n;
11129 }
11130
11131 static void
11132 fixredir(union node *n, const char *text, int err)
11133 {
11134         int fd;
11135
11136         TRACE(("Fix redir %s %d\n", text, err));
11137         if (!err)
11138                 n->ndup.vname = NULL;
11139
11140         fd = bb_strtou(text, NULL, 10);
11141         if (!errno && fd >= 0)
11142                 n->ndup.dupfd = fd;
11143         else if (LONE_DASH(text))
11144                 n->ndup.dupfd = -1;
11145         else {
11146                 if (err)
11147                         raise_error_syntax("bad fd number");
11148                 n->ndup.vname = makename();
11149         }
11150 }
11151
11152 /*
11153  * Returns true if the text contains nothing to expand (no dollar signs
11154  * or backquotes).
11155  */
11156 static int
11157 noexpand(const char *text)
11158 {
11159         unsigned char c;
11160
11161         while ((c = *text++) != '\0') {
11162                 if (c == CTLQUOTEMARK)
11163                         continue;
11164                 if (c == CTLESC)
11165                         text++;
11166                 else if (SIT(c, BASESYNTAX) == CCTL)
11167                         return 0;
11168         }
11169         return 1;
11170 }
11171
11172 static void
11173 parsefname(void)
11174 {
11175         union node *n = redirnode;
11176
11177         if (readtoken() != TWORD)
11178                 raise_error_unexpected_syntax(-1);
11179         if (n->type == NHERE) {
11180                 struct heredoc *here = heredoc;
11181                 struct heredoc *p;
11182                 int i;
11183
11184                 if (quoteflag == 0)
11185                         n->type = NXHERE;
11186                 TRACE(("Here document %d\n", n->type));
11187                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11188                         raise_error_syntax("illegal eof marker for << redirection");
11189                 rmescapes(wordtext, 0);
11190                 here->eofmark = wordtext;
11191                 here->next = NULL;
11192                 if (heredoclist == NULL)
11193                         heredoclist = here;
11194                 else {
11195                         for (p = heredoclist; p->next; p = p->next)
11196                                 continue;
11197                         p->next = here;
11198                 }
11199         } else if (n->type == NTOFD || n->type == NFROMFD) {
11200                 fixredir(n, wordtext, 0);
11201         } else {
11202                 n->nfile.fname = makename();
11203         }
11204 }
11205
11206 static union node *
11207 simplecmd(void)
11208 {
11209         union node *args, **app;
11210         union node *n = NULL;
11211         union node *vars, **vpp;
11212         union node **rpp, *redir;
11213         int savecheckkwd;
11214 #if BASH_TEST2
11215         smallint double_brackets_flag = 0;
11216 #endif
11217         IF_BASH_FUNCTION(smallint function_flag = 0;)
11218
11219         args = NULL;
11220         app = &args;
11221         vars = NULL;
11222         vpp = &vars;
11223         redir = NULL;
11224         rpp = &redir;
11225
11226         savecheckkwd = CHKALIAS;
11227         for (;;) {
11228                 int t;
11229                 checkkwd = savecheckkwd;
11230                 t = readtoken();
11231                 switch (t) {
11232 #if BASH_FUNCTION
11233                 case TFUNCTION:
11234                         if (peektoken() != TWORD)
11235                                 raise_error_unexpected_syntax(TWORD);
11236                         function_flag = 1;
11237                         break;
11238 #endif
11239 #if BASH_TEST2
11240                 case TAND: /* "&&" */
11241                 case TOR: /* "||" */
11242                         if (!double_brackets_flag) {
11243                                 tokpushback = 1;
11244                                 goto out;
11245                         }
11246                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11247 #endif
11248                 case TWORD:
11249                         n = stzalloc(sizeof(struct narg));
11250                         n->type = NARG;
11251                         /*n->narg.next = NULL; - stzalloc did it */
11252                         n->narg.text = wordtext;
11253 #if BASH_TEST2
11254                         if (strcmp("[[", wordtext) == 0)
11255                                 double_brackets_flag = 1;
11256                         else if (strcmp("]]", wordtext) == 0)
11257                                 double_brackets_flag = 0;
11258 #endif
11259                         n->narg.backquote = backquotelist;
11260                         if (savecheckkwd && isassignment(wordtext)) {
11261                                 *vpp = n;
11262                                 vpp = &n->narg.next;
11263                         } else {
11264                                 *app = n;
11265                                 app = &n->narg.next;
11266                                 savecheckkwd = 0;
11267                         }
11268 #if BASH_FUNCTION
11269                         if (function_flag) {
11270                                 checkkwd = CHKNL | CHKKWD;
11271                                 switch (peektoken()) {
11272                                 case TBEGIN:
11273                                 case TIF:
11274                                 case TCASE:
11275                                 case TUNTIL:
11276                                 case TWHILE:
11277                                 case TFOR:
11278                                         goto do_func;
11279                                 case TLP:
11280                                         function_flag = 0;
11281                                         break;
11282                                 case TWORD:
11283                                         if (strcmp("[[", wordtext) == 0)
11284                                                 goto do_func;
11285                                         /* fall through */
11286                                 default:
11287                                         raise_error_unexpected_syntax(-1);
11288                                 }
11289                         }
11290 #endif
11291                         break;
11292                 case TREDIR:
11293                         *rpp = n = redirnode;
11294                         rpp = &n->nfile.next;
11295                         parsefname();   /* read name of redirection file */
11296                         break;
11297                 case TLP:
11298  IF_BASH_FUNCTION(do_func:)
11299                         if (args && app == &args->narg.next
11300                          && !vars && !redir
11301                         ) {
11302                                 struct builtincmd *bcmd;
11303                                 const char *name;
11304
11305                                 /* We have a function */
11306                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11307                                         raise_error_unexpected_syntax(TRP);
11308                                 name = n->narg.text;
11309                                 if (!goodname(name)
11310                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11311                                 ) {
11312                                         raise_error_syntax("bad function name");
11313                                 }
11314                                 n->type = NDEFUN;
11315                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11316                                 n->narg.next = parse_command();
11317                                 return n;
11318                         }
11319                         IF_BASH_FUNCTION(function_flag = 0;)
11320                         /* fall through */
11321                 default:
11322                         tokpushback = 1;
11323                         goto out;
11324                 }
11325         }
11326  out:
11327         *app = NULL;
11328         *vpp = NULL;
11329         *rpp = NULL;
11330         n = stzalloc(sizeof(struct ncmd));
11331         n->type = NCMD;
11332         n->ncmd.args = args;
11333         n->ncmd.assign = vars;
11334         n->ncmd.redirect = redir;
11335         return n;
11336 }
11337
11338 static union node *
11339 parse_command(void)
11340 {
11341         union node *n1, *n2;
11342         union node *ap, **app;
11343         union node *cp, **cpp;
11344         union node *redir, **rpp;
11345         union node **rpp2;
11346         int t;
11347
11348         redir = NULL;
11349         rpp2 = &redir;
11350
11351         switch (readtoken()) {
11352         default:
11353                 raise_error_unexpected_syntax(-1);
11354                 /* NOTREACHED */
11355         case TIF:
11356                 n1 = stzalloc(sizeof(struct nif));
11357                 n1->type = NIF;
11358                 n1->nif.test = list(0);
11359                 if (readtoken() != TTHEN)
11360                         raise_error_unexpected_syntax(TTHEN);
11361                 n1->nif.ifpart = list(0);
11362                 n2 = n1;
11363                 while (readtoken() == TELIF) {
11364                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11365                         n2 = n2->nif.elsepart;
11366                         n2->type = NIF;
11367                         n2->nif.test = list(0);
11368                         if (readtoken() != TTHEN)
11369                                 raise_error_unexpected_syntax(TTHEN);
11370                         n2->nif.ifpart = list(0);
11371                 }
11372                 if (lasttoken == TELSE)
11373                         n2->nif.elsepart = list(0);
11374                 else {
11375                         n2->nif.elsepart = NULL;
11376                         tokpushback = 1;
11377                 }
11378                 t = TFI;
11379                 break;
11380         case TWHILE:
11381         case TUNTIL: {
11382                 int got;
11383                 n1 = stzalloc(sizeof(struct nbinary));
11384                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11385                 n1->nbinary.ch1 = list(0);
11386                 got = readtoken();
11387                 if (got != TDO) {
11388                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11389                                         got == TWORD ? wordtext : ""));
11390                         raise_error_unexpected_syntax(TDO);
11391                 }
11392                 n1->nbinary.ch2 = list(0);
11393                 t = TDONE;
11394                 break;
11395         }
11396         case TFOR:
11397                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11398                         raise_error_syntax("bad for loop variable");
11399                 n1 = stzalloc(sizeof(struct nfor));
11400                 n1->type = NFOR;
11401                 n1->nfor.var = wordtext;
11402                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11403                 if (readtoken() == TIN) {
11404                         app = &ap;
11405                         while (readtoken() == TWORD) {
11406                                 n2 = stzalloc(sizeof(struct narg));
11407                                 n2->type = NARG;
11408                                 /*n2->narg.next = NULL; - stzalloc did it */
11409                                 n2->narg.text = wordtext;
11410                                 n2->narg.backquote = backquotelist;
11411                                 *app = n2;
11412                                 app = &n2->narg.next;
11413                         }
11414                         *app = NULL;
11415                         n1->nfor.args = ap;
11416                         if (lasttoken != TNL && lasttoken != TSEMI)
11417                                 raise_error_unexpected_syntax(-1);
11418                 } else {
11419                         n2 = stzalloc(sizeof(struct narg));
11420                         n2->type = NARG;
11421                         /*n2->narg.next = NULL; - stzalloc did it */
11422                         n2->narg.text = (char *)dolatstr;
11423                         /*n2->narg.backquote = NULL;*/
11424                         n1->nfor.args = n2;
11425                         /*
11426                          * Newline or semicolon here is optional (but note
11427                          * that the original Bourne shell only allowed NL).
11428                          */
11429                         if (lasttoken != TSEMI)
11430                                 tokpushback = 1;
11431                 }
11432                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11433                 if (readtoken() != TDO)
11434                         raise_error_unexpected_syntax(TDO);
11435                 n1->nfor.body = list(0);
11436                 t = TDONE;
11437                 break;
11438         case TCASE:
11439                 n1 = stzalloc(sizeof(struct ncase));
11440                 n1->type = NCASE;
11441                 if (readtoken() != TWORD)
11442                         raise_error_unexpected_syntax(TWORD);
11443                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11444                 n2->type = NARG;
11445                 /*n2->narg.next = NULL; - stzalloc did it */
11446                 n2->narg.text = wordtext;
11447                 n2->narg.backquote = backquotelist;
11448                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11449                 if (readtoken() != TIN)
11450                         raise_error_unexpected_syntax(TIN);
11451                 cpp = &n1->ncase.cases;
11452  next_case:
11453                 checkkwd = CHKNL | CHKKWD;
11454                 t = readtoken();
11455                 while (t != TESAC) {
11456                         if (lasttoken == TLP)
11457                                 readtoken();
11458                         *cpp = cp = stzalloc(sizeof(struct nclist));
11459                         cp->type = NCLIST;
11460                         app = &cp->nclist.pattern;
11461                         for (;;) {
11462                                 *app = ap = stzalloc(sizeof(struct narg));
11463                                 ap->type = NARG;
11464                                 /*ap->narg.next = NULL; - stzalloc did it */
11465                                 ap->narg.text = wordtext;
11466                                 ap->narg.backquote = backquotelist;
11467                                 if (readtoken() != TPIPE)
11468                                         break;
11469                                 app = &ap->narg.next;
11470                                 readtoken();
11471                         }
11472                         //ap->narg.next = NULL;
11473                         if (lasttoken != TRP)
11474                                 raise_error_unexpected_syntax(TRP);
11475                         cp->nclist.body = list(2);
11476
11477                         cpp = &cp->nclist.next;
11478
11479                         checkkwd = CHKNL | CHKKWD;
11480                         t = readtoken();
11481                         if (t != TESAC) {
11482                                 if (t != TENDCASE)
11483                                         raise_error_unexpected_syntax(TENDCASE);
11484                                 goto next_case;
11485                         }
11486                 }
11487                 *cpp = NULL;
11488                 goto redir;
11489         case TLP:
11490                 n1 = stzalloc(sizeof(struct nredir));
11491                 n1->type = NSUBSHELL;
11492                 n1->nredir.n = list(0);
11493                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11494                 t = TRP;
11495                 break;
11496         case TBEGIN:
11497                 n1 = list(0);
11498                 t = TEND;
11499                 break;
11500         IF_BASH_FUNCTION(case TFUNCTION:)
11501         case TWORD:
11502         case TREDIR:
11503                 tokpushback = 1;
11504                 return simplecmd();
11505         }
11506
11507         if (readtoken() != t)
11508                 raise_error_unexpected_syntax(t);
11509
11510  redir:
11511         /* Now check for redirection which may follow command */
11512         checkkwd = CHKKWD | CHKALIAS;
11513         rpp = rpp2;
11514         while (readtoken() == TREDIR) {
11515                 *rpp = n2 = redirnode;
11516                 rpp = &n2->nfile.next;
11517                 parsefname();
11518         }
11519         tokpushback = 1;
11520         *rpp = NULL;
11521         if (redir) {
11522                 if (n1->type != NSUBSHELL) {
11523                         n2 = stzalloc(sizeof(struct nredir));
11524                         n2->type = NREDIR;
11525                         n2->nredir.n = n1;
11526                         n1 = n2;
11527                 }
11528                 n1->nredir.redirect = redir;
11529         }
11530         return n1;
11531 }
11532
11533 #if BASH_DOLLAR_SQUOTE
11534 static int
11535 decode_dollar_squote(void)
11536 {
11537         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11538         int c, cnt;
11539         char *p;
11540         char buf[4];
11541
11542         c = pgetc();
11543         p = strchr(C_escapes, c);
11544         if (p) {
11545                 buf[0] = c;
11546                 p = buf;
11547                 cnt = 3;
11548                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11549                         do {
11550                                 c = pgetc();
11551                                 *++p = c;
11552                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11553                         pungetc();
11554                 } else if (c == 'x') { /* \xHH */
11555                         do {
11556                                 c = pgetc();
11557                                 *++p = c;
11558                         } while (isxdigit(c) && --cnt);
11559                         pungetc();
11560                         if (cnt == 3) { /* \x but next char is "bad" */
11561                                 c = 'x';
11562                                 goto unrecognized;
11563                         }
11564                 } else { /* simple seq like \\ or \t */
11565                         p++;
11566                 }
11567                 *p = '\0';
11568                 p = buf;
11569                 c = bb_process_escape_sequence((void*)&p);
11570         } else { /* unrecognized "\z": print both chars unless ' or " */
11571                 if (c != '\'' && c != '"') {
11572  unrecognized:
11573                         c |= 0x100; /* "please encode \, then me" */
11574                 }
11575         }
11576         return c;
11577 }
11578 #endif
11579
11580 /*
11581  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11582  * is not NULL, read a here document.  In the latter case, eofmark is the
11583  * word which marks the end of the document and striptabs is true if
11584  * leading tabs should be stripped from the document.  The argument c
11585  * is the first character of the input token or document.
11586  *
11587  * Because C does not have internal subroutines, I have simulated them
11588  * using goto's to implement the subroutine linkage.  The following macros
11589  * will run code that appears at the end of readtoken1.
11590  */
11591 #define CHECKEND()      {goto checkend; checkend_return:;}
11592 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11593 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11594 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11595 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11596 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11597 static int
11598 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11599 {
11600         /* NB: syntax parameter fits into smallint */
11601         /* c parameter is an unsigned char or PEOF or PEOA */
11602         char *out;
11603         size_t len;
11604         char line[EOFMARKLEN + 1];
11605         struct nodelist *bqlist;
11606         smallint quotef;
11607         smallint dblquote;
11608         smallint oldstyle;
11609         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11610         smallint pssyntax;   /* we are expanding a prompt string */
11611         int varnest;         /* levels of variables expansion */
11612         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11613         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11614         int dqvarnest;       /* levels of variables expansion within double quotes */
11615
11616         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11617
11618         startlinno = g_parsefile->linno;
11619         bqlist = NULL;
11620         quotef = 0;
11621         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11622         pssyntax = (syntax == PSSYNTAX);
11623         if (pssyntax)
11624                 syntax = DQSYNTAX;
11625         dblquote = (syntax == DQSYNTAX);
11626         varnest = 0;
11627         IF_FEATURE_SH_MATH(arinest = 0;)
11628         IF_FEATURE_SH_MATH(parenlevel = 0;)
11629         dqvarnest = 0;
11630
11631         STARTSTACKSTR(out);
11632  loop:
11633         /* For each line, until end of word */
11634         CHECKEND();     /* set c to PEOF if at end of here document */
11635         for (;;) {      /* until end of line or end of word */
11636                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11637                 switch (SIT(c, syntax)) {
11638                 case CNL:       /* '\n' */
11639                         if (syntax == BASESYNTAX)
11640                                 goto endword;   /* exit outer loop */
11641                         USTPUTC(c, out);
11642                         nlprompt();
11643                         c = pgetc();
11644                         goto loop;              /* continue outer loop */
11645                 case CWORD:
11646                         USTPUTC(c, out);
11647                         break;
11648                 case CCTL:
11649 #if BASH_DOLLAR_SQUOTE
11650                         if (c == '\\' && bash_dollar_squote) {
11651                                 c = decode_dollar_squote();
11652                                 if (c == '\0') {
11653                                         /* skip $'\000', $'\x00' (like bash) */
11654                                         break;
11655                                 }
11656                                 if (c & 0x100) {
11657                                         /* Unknown escape. Encode as '\z' */
11658                                         c = (unsigned char)c;
11659                                         if (eofmark == NULL || dblquote)
11660                                                 USTPUTC(CTLESC, out);
11661                                         USTPUTC('\\', out);
11662                                 }
11663                         }
11664 #endif
11665                         if (eofmark == NULL || dblquote)
11666                                 USTPUTC(CTLESC, out);
11667                         USTPUTC(c, out);
11668                         break;
11669                 case CBACK:     /* backslash */
11670                         c = pgetc_without_PEOA();
11671                         if (c == PEOF) {
11672                                 USTPUTC(CTLESC, out);
11673                                 USTPUTC('\\', out);
11674                                 pungetc();
11675                         } else if (c == '\n') {
11676                                 nlprompt();
11677                         } else {
11678                                 if (c == '$' && pssyntax) {
11679                                         USTPUTC(CTLESC, out);
11680                                         USTPUTC('\\', out);
11681                                 }
11682                                 /* Backslash is retained if we are in "str" and next char isn't special */
11683                                 if (dblquote
11684                                  && c != '\\'
11685                                  && c != '`'
11686                                  && c != '$'
11687                                  && (c != '"' || eofmark != NULL)
11688                                 ) {
11689                                         USTPUTC('\\', out);
11690                                 }
11691                                 USTPUTC(CTLESC, out);
11692                                 USTPUTC(c, out);
11693                                 quotef = 1;
11694                         }
11695                         break;
11696                 case CSQUOTE:
11697                         syntax = SQSYNTAX;
11698  quotemark:
11699                         if (eofmark == NULL) {
11700                                 USTPUTC(CTLQUOTEMARK, out);
11701                         }
11702                         break;
11703                 case CDQUOTE:
11704                         syntax = DQSYNTAX;
11705                         dblquote = 1;
11706                         goto quotemark;
11707                 case CENDQUOTE:
11708                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11709                         if (eofmark != NULL && varnest == 0) {
11710                                 USTPUTC(c, out);
11711                         } else {
11712                                 if (dqvarnest == 0) {
11713                                         syntax = BASESYNTAX;
11714                                         dblquote = 0;
11715                                 }
11716                                 quotef = 1;
11717                                 goto quotemark;
11718                         }
11719                         break;
11720                 case CVAR:      /* '$' */
11721                         PARSESUB();             /* parse substitution */
11722                         break;
11723                 case CENDVAR:   /* '}' */
11724                         if (varnest > 0) {
11725                                 varnest--;
11726                                 if (dqvarnest > 0) {
11727                                         dqvarnest--;
11728                                 }
11729                                 c = CTLENDVAR;
11730                         }
11731                         USTPUTC(c, out);
11732                         break;
11733 #if ENABLE_FEATURE_SH_MATH
11734                 case CLP:       /* '(' in arithmetic */
11735                         parenlevel++;
11736                         USTPUTC(c, out);
11737                         break;
11738                 case CRP:       /* ')' in arithmetic */
11739                         if (parenlevel > 0) {
11740                                 parenlevel--;
11741                         } else {
11742                                 if (pgetc_eatbnl() == ')') {
11743                                         c = CTLENDARI;
11744                                         if (--arinest == 0) {
11745                                                 syntax = prevsyntax;
11746                                         }
11747                                 } else {
11748                                         /*
11749                                          * unbalanced parens
11750                                          * (don't 2nd guess - no error)
11751                                          */
11752                                         pungetc();
11753                                 }
11754                         }
11755                         USTPUTC(c, out);
11756                         break;
11757 #endif
11758                 case CBQUOTE:   /* '`' */
11759                         PARSEBACKQOLD();
11760                         break;
11761                 case CENDFILE:
11762                         goto endword;           /* exit outer loop */
11763                 case CIGN:
11764                         break;
11765                 default:
11766                         if (varnest == 0) {
11767 #if BASH_REDIR_OUTPUT
11768                                 if (c == '&') {
11769 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11770                                         if (pgetc() == '>')
11771                                                 c = 0x100 + '>'; /* flag &> */
11772                                         pungetc();
11773                                 }
11774 #endif
11775                                 goto endword;   /* exit outer loop */
11776                         }
11777                         IF_ASH_ALIAS(if (c != PEOA))
11778                                 USTPUTC(c, out);
11779                 }
11780                 c = pgetc();
11781         } /* for (;;) */
11782  endword:
11783
11784 #if ENABLE_FEATURE_SH_MATH
11785         if (syntax == ARISYNTAX)
11786                 raise_error_syntax("missing '))'");
11787 #endif
11788         if (syntax != BASESYNTAX && eofmark == NULL)
11789                 raise_error_syntax("unterminated quoted string");
11790         if (varnest != 0) {
11791                 startlinno = g_parsefile->linno;
11792                 /* { */
11793                 raise_error_syntax("missing '}'");
11794         }
11795         USTPUTC('\0', out);
11796         len = out - (char *)stackblock();
11797         out = stackblock();
11798         if (eofmark == NULL) {
11799                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11800                  && quotef == 0
11801                 ) {
11802                         if (isdigit_str9(out)) {
11803                                 PARSEREDIR(); /* passed as params: out, c */
11804                                 lasttoken = TREDIR;
11805                                 return lasttoken;
11806                         }
11807                         /* else: non-number X seen, interpret it
11808                          * as "NNNX>file" = "NNNX >file" */
11809                 }
11810                 pungetc();
11811         }
11812         quoteflag = quotef;
11813         backquotelist = bqlist;
11814         grabstackblock(len);
11815         wordtext = out;
11816         lasttoken = TWORD;
11817         return lasttoken;
11818 /* end of readtoken routine */
11819
11820 /*
11821  * Check to see whether we are at the end of the here document.  When this
11822  * is called, c is set to the first character of the next input line.  If
11823  * we are at the end of the here document, this routine sets the c to PEOF.
11824  */
11825 checkend: {
11826         if (eofmark) {
11827 #if ENABLE_ASH_ALIAS
11828                 if (c == PEOA)
11829                         c = pgetc_without_PEOA();
11830 #endif
11831                 if (striptabs) {
11832                         while (c == '\t') {
11833                                 c = pgetc_without_PEOA();
11834                         }
11835                 }
11836                 if (c == *eofmark) {
11837                         if (pfgets(line, sizeof(line)) != NULL) {
11838                                 char *p, *q;
11839                                 int cc;
11840
11841                                 p = line;
11842                                 for (q = eofmark + 1;; p++, q++) {
11843                                         cc = *p;
11844                                         if (cc == '\n')
11845                                                 cc = 0;
11846                                         if (!*q || cc != *q)
11847                                                 break;
11848                                 }
11849                                 if (cc == *q) {
11850                                         c = PEOF;
11851                                         nlnoprompt();
11852                                 } else {
11853                                         pushstring(line, NULL);
11854                                 }
11855                         }
11856                 }
11857         }
11858         goto checkend_return;
11859 }
11860
11861 /*
11862  * Parse a redirection operator.  The variable "out" points to a string
11863  * specifying the fd to be redirected.  The variable "c" contains the
11864  * first character of the redirection operator.
11865  */
11866 parseredir: {
11867         /* out is already checked to be a valid number or "" */
11868         int fd = (*out == '\0' ? -1 : atoi(out));
11869         union node *np;
11870
11871         np = stzalloc(sizeof(struct nfile));
11872         if (c == '>') {
11873                 np->nfile.fd = 1;
11874                 c = pgetc();
11875                 if (c == '>')
11876                         np->type = NAPPEND;
11877                 else if (c == '|')
11878                         np->type = NCLOBBER;
11879                 else if (c == '&')
11880                         np->type = NTOFD;
11881                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11882                 else {
11883                         np->type = NTO;
11884                         pungetc();
11885                 }
11886         }
11887 #if BASH_REDIR_OUTPUT
11888         else if (c == 0x100 + '>') { /* this flags &> redirection */
11889                 np->nfile.fd = 1;
11890                 pgetc(); /* this is '>', no need to check */
11891                 np->type = NTO2;
11892         }
11893 #endif
11894         else { /* c == '<' */
11895                 /*np->nfile.fd = 0; - stzalloc did it */
11896                 c = pgetc();
11897                 switch (c) {
11898                 case '<':
11899                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11900                                 np = stzalloc(sizeof(struct nhere));
11901                                 /*np->nfile.fd = 0; - stzalloc did it */
11902                         }
11903                         np->type = NHERE;
11904                         heredoc = stzalloc(sizeof(struct heredoc));
11905                         heredoc->here = np;
11906                         c = pgetc();
11907                         if (c == '-') {
11908                                 heredoc->striptabs = 1;
11909                         } else {
11910                                 /*heredoc->striptabs = 0; - stzalloc did it */
11911                                 pungetc();
11912                         }
11913                         break;
11914
11915                 case '&':
11916                         np->type = NFROMFD;
11917                         break;
11918
11919                 case '>':
11920                         np->type = NFROMTO;
11921                         break;
11922
11923                 default:
11924                         np->type = NFROM;
11925                         pungetc();
11926                         break;
11927                 }
11928         }
11929         if (fd >= 0)
11930                 np->nfile.fd = fd;
11931         redirnode = np;
11932         goto parseredir_return;
11933 }
11934
11935 /*
11936  * Parse a substitution.  At this point, we have read the dollar sign
11937  * and nothing else.
11938  */
11939
11940 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11941  * (assuming ascii char codes, as the original implementation did) */
11942 #define is_special(c) \
11943         (((unsigned)(c) - 33 < 32) \
11944                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11945 parsesub: {
11946         unsigned char subtype;
11947         int typeloc;
11948
11949         c = pgetc_eatbnl();
11950         if (c > 255 /* PEOA or PEOF */
11951          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11952         ) {
11953 #if BASH_DOLLAR_SQUOTE
11954                 if (syntax != DQSYNTAX && c == '\'')
11955                         bash_dollar_squote = 1;
11956                 else
11957 #endif
11958                         USTPUTC('$', out);
11959                 pungetc();
11960         } else if (c == '(') {
11961                 /* $(command) or $((arith)) */
11962                 if (pgetc_eatbnl() == '(') {
11963 #if ENABLE_FEATURE_SH_MATH
11964                         PARSEARITH();
11965 #else
11966                         raise_error_syntax("support for $((arith)) is disabled");
11967 #endif
11968                 } else {
11969                         pungetc();
11970                         PARSEBACKQNEW();
11971                 }
11972         } else {
11973                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11974                 USTPUTC(CTLVAR, out);
11975                 typeloc = out - (char *)stackblock();
11976                 STADJUST(1, out);
11977                 subtype = VSNORMAL;
11978                 if (c == '{') {
11979                         c = pgetc_eatbnl();
11980                         subtype = 0;
11981                 }
11982  varname:
11983                 if (is_name(c)) {
11984                         /* $[{[#]]NAME[}] */
11985                         do {
11986                                 STPUTC(c, out);
11987                                 c = pgetc_eatbnl();
11988                         } while (is_in_name(c));
11989                 } else if (isdigit(c)) {
11990                         /* $[{[#]]NUM[}] */
11991                         do {
11992                                 STPUTC(c, out);
11993                                 c = pgetc_eatbnl();
11994                         } while (isdigit(c));
11995                 } else if (is_special(c)) {
11996                         /* $[{[#]]<specialchar>[}] */
11997                         int cc = c;
11998
11999                         c = pgetc_eatbnl();
12000                         if (!subtype && cc == '#') {
12001                                 subtype = VSLENGTH;
12002                                 if (c == '_' || isalnum(c))
12003                                         goto varname;
12004                                 cc = c;
12005                                 c = pgetc_eatbnl();
12006                                 if (cc == '}' || c != '}') {
12007                                         pungetc();
12008                                         subtype = 0;
12009                                         c = cc;
12010                                         cc = '#';
12011                                 }
12012                         }
12013                         USTPUTC(cc, out);
12014                 } else {
12015                         goto badsub;
12016                 }
12017                 if (c != '}' && subtype == VSLENGTH) {
12018                         /* ${#VAR didn't end with } */
12019                         goto badsub;
12020                 }
12021
12022                 if (subtype == 0) {
12023                         static const char types[] ALIGN1 = "}-+?=";
12024                         /* ${VAR...} but not $VAR or ${#VAR} */
12025                         /* c == first char after VAR */
12026                         switch (c) {
12027                         case ':':
12028                                 c = pgetc_eatbnl();
12029 #if BASH_SUBSTR
12030                                 /* This check is only needed to not misinterpret
12031                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12032                                  * constructs.
12033                                  */
12034                                 if (!strchr(types, c)) {
12035                                         subtype = VSSUBSTR;
12036                                         pungetc();
12037                                         break; /* "goto badsub" is bigger (!) */
12038                                 }
12039 #endif
12040                                 subtype = VSNUL;
12041                                 /*FALLTHROUGH*/
12042                         default: {
12043                                 const char *p = strchr(types, c);
12044                                 if (p == NULL)
12045                                         break;
12046                                 subtype |= p - types + VSNORMAL;
12047                                 break;
12048                         }
12049                         case '%':
12050                         case '#': {
12051                                 int cc = c;
12052                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12053                                 c = pgetc_eatbnl();
12054                                 if (c != cc)
12055                                         goto badsub;
12056                                 subtype++;
12057                                 break;
12058                         }
12059 #if BASH_PATTERN_SUBST
12060                         case '/':
12061                                 /* ${v/[/]pattern/repl} */
12062 //TODO: encode pattern and repl separately.
12063 // Currently ${v/$var_with_slash/repl} is horribly broken
12064                                 subtype = VSREPLACE;
12065                                 c = pgetc_eatbnl();
12066                                 if (c != '/')
12067                                         goto badsub;
12068                                 subtype++; /* VSREPLACEALL */
12069                                 break;
12070 #endif
12071                         }
12072                 } else {
12073  badsub:
12074                         pungetc();
12075                 }
12076                 ((unsigned char *)stackblock())[typeloc] = subtype;
12077                 if (subtype != VSNORMAL) {
12078                         varnest++;
12079                         if (dblquote)
12080                                 dqvarnest++;
12081                 }
12082                 STPUTC('=', out);
12083         }
12084         goto parsesub_return;
12085 }
12086
12087 /*
12088  * Called to parse command substitutions.  Newstyle is set if the command
12089  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12090  * list of commands (passed by reference), and savelen is the number of
12091  * characters on the top of the stack which must be preserved.
12092  */
12093 parsebackq: {
12094         struct nodelist **nlpp;
12095         union node *n;
12096         char *str;
12097         size_t savelen;
12098         smallint saveprompt = 0;
12099
12100         str = NULL;
12101         savelen = out - (char *)stackblock();
12102         if (savelen > 0) {
12103                 /*
12104                  * FIXME: this can allocate very large block on stack and SEGV.
12105                  * Example:
12106                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12107                  * allocates 100kb for every command subst. With about
12108                  * a hundred command substitutions stack overflows.
12109                  * With larger prepended string, SEGV happens sooner.
12110                  */
12111                 str = alloca(savelen);
12112                 memcpy(str, stackblock(), savelen);
12113         }
12114
12115         if (oldstyle) {
12116                 /* We must read until the closing backquote, giving special
12117                  * treatment to some slashes, and then push the string and
12118                  * reread it as input, interpreting it normally.
12119                  */
12120                 char *pout;
12121                 size_t psavelen;
12122                 char *pstr;
12123
12124                 STARTSTACKSTR(pout);
12125                 for (;;) {
12126                         int pc;
12127
12128                         setprompt_if(needprompt, 2);
12129                         pc = pgetc();
12130                         switch (pc) {
12131                         case '`':
12132                                 goto done;
12133
12134                         case '\\':
12135                                 pc = pgetc();
12136                                 if (pc == '\n') {
12137                                         nlprompt();
12138                                         /*
12139                                          * If eating a newline, avoid putting
12140                                          * the newline into the new character
12141                                          * stream (via the STPUTC after the
12142                                          * switch).
12143                                          */
12144                                         continue;
12145                                 }
12146                                 if (pc != '\\' && pc != '`' && pc != '$'
12147                                  && (!dblquote || pc != '"')
12148                                 ) {
12149                                         STPUTC('\\', pout);
12150                                 }
12151                                 if (pc <= 255 /* not PEOA or PEOF */) {
12152                                         break;
12153                                 }
12154                                 /* fall through */
12155
12156                         case PEOF:
12157                         IF_ASH_ALIAS(case PEOA:)
12158                                 startlinno = g_parsefile->linno;
12159                                 raise_error_syntax("EOF in backquote substitution");
12160
12161                         case '\n':
12162                                 nlnoprompt();
12163                                 break;
12164
12165                         default:
12166                                 break;
12167                         }
12168                         STPUTC(pc, pout);
12169                 }
12170  done:
12171                 STPUTC('\0', pout);
12172                 psavelen = pout - (char *)stackblock();
12173                 if (psavelen > 0) {
12174                         pstr = grabstackstr(pout);
12175                         setinputstring(pstr);
12176                 }
12177         }
12178         nlpp = &bqlist;
12179         while (*nlpp)
12180                 nlpp = &(*nlpp)->next;
12181         *nlpp = stzalloc(sizeof(**nlpp));
12182         /* (*nlpp)->next = NULL; - stzalloc did it */
12183
12184         if (oldstyle) {
12185                 saveprompt = doprompt;
12186                 doprompt = 0;
12187         }
12188
12189         n = list(2);
12190
12191         if (oldstyle)
12192                 doprompt = saveprompt;
12193         else if (readtoken() != TRP)
12194                 raise_error_unexpected_syntax(TRP);
12195
12196         (*nlpp)->n = n;
12197         if (oldstyle) {
12198                 /*
12199                  * Start reading from old file again, ignoring any pushed back
12200                  * tokens left from the backquote parsing
12201                  */
12202                 popfile();
12203                 tokpushback = 0;
12204         }
12205         while (stackblocksize() <= savelen)
12206                 growstackblock();
12207         STARTSTACKSTR(out);
12208         if (str) {
12209                 memcpy(out, str, savelen);
12210                 STADJUST(savelen, out);
12211         }
12212         USTPUTC(CTLBACKQ, out);
12213         if (oldstyle)
12214                 goto parsebackq_oldreturn;
12215         goto parsebackq_newreturn;
12216 }
12217
12218 #if ENABLE_FEATURE_SH_MATH
12219 /*
12220  * Parse an arithmetic expansion (indicate start of one and set state)
12221  */
12222 parsearith: {
12223         if (++arinest == 1) {
12224                 prevsyntax = syntax;
12225                 syntax = ARISYNTAX;
12226         }
12227         USTPUTC(CTLARI, out);
12228         goto parsearith_return;
12229 }
12230 #endif
12231 } /* end of readtoken */
12232
12233 /*
12234  * Read the next input token.
12235  * If the token is a word, we set backquotelist to the list of cmds in
12236  *      backquotes.  We set quoteflag to true if any part of the word was
12237  *      quoted.
12238  * If the token is TREDIR, then we set redirnode to a structure containing
12239  *      the redirection.
12240  * In all cases, the variable startlinno is set to the number of the line
12241  *      on which the token starts.
12242  *
12243  * [Change comment:  here documents and internal procedures]
12244  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12245  *  word parsing code into a separate routine.  In this case, readtoken
12246  *  doesn't need to have any internal procedures, but parseword does.
12247  *  We could also make parseoperator in essence the main routine, and
12248  *  have parseword (readtoken1?) handle both words and redirection.]
12249  */
12250 #define NEW_xxreadtoken
12251 #ifdef NEW_xxreadtoken
12252 /* singles must be first! */
12253 static const char xxreadtoken_chars[7] ALIGN1 = {
12254         '\n', '(', ')', /* singles */
12255         '&', '|', ';',  /* doubles */
12256         0
12257 };
12258
12259 #define xxreadtoken_singles 3
12260 #define xxreadtoken_doubles 3
12261
12262 static const char xxreadtoken_tokens[] ALIGN1 = {
12263         TNL, TLP, TRP,          /* only single occurrence allowed */
12264         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12265         TEOF,                   /* corresponds to trailing nul */
12266         TAND, TOR, TENDCASE     /* if double occurrence */
12267 };
12268
12269 static int
12270 xxreadtoken(void)
12271 {
12272         int c;
12273
12274         if (tokpushback) {
12275                 tokpushback = 0;
12276                 return lasttoken;
12277         }
12278         setprompt_if(needprompt, 2);
12279         startlinno = g_parsefile->linno;
12280         for (;;) {                      /* until token or start of word found */
12281                 c = pgetc();
12282                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12283                         continue;
12284
12285                 if (c == '#') {
12286                         while ((c = pgetc()) != '\n' && c != PEOF)
12287                                 continue;
12288                         pungetc();
12289                 } else if (c == '\\') {
12290                         if (pgetc() != '\n') {
12291                                 pungetc();
12292                                 break; /* return readtoken1(...) */
12293                         }
12294                         nlprompt();
12295                 } else {
12296                         const char *p;
12297
12298                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12299                         if (c != PEOF) {
12300                                 if (c == '\n') {
12301                                         nlnoprompt();
12302                                 }
12303
12304                                 p = strchr(xxreadtoken_chars, c);
12305                                 if (p == NULL)
12306                                         break; /* return readtoken1(...) */
12307
12308                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12309                                         int cc = pgetc();
12310                                         if (cc == c) {    /* double occurrence? */
12311                                                 p += xxreadtoken_doubles + 1;
12312                                         } else {
12313                                                 pungetc();
12314 #if BASH_REDIR_OUTPUT
12315                                                 if (c == '&' && cc == '>') /* &> */
12316                                                         break; /* return readtoken1(...) */
12317 #endif
12318                                         }
12319                                 }
12320                         }
12321                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12322                         return lasttoken;
12323                 }
12324         } /* for (;;) */
12325
12326         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12327 }
12328 #else /* old xxreadtoken */
12329 #define RETURN(token)   return lasttoken = token
12330 static int
12331 xxreadtoken(void)
12332 {
12333         int c;
12334
12335         if (tokpushback) {
12336                 tokpushback = 0;
12337                 return lasttoken;
12338         }
12339         setprompt_if(needprompt, 2);
12340         startlinno = g_parsefile->linno;
12341         for (;;) {      /* until token or start of word found */
12342                 c = pgetc();
12343                 switch (c) {
12344                 case ' ': case '\t':
12345                 IF_ASH_ALIAS(case PEOA:)
12346                         continue;
12347                 case '#':
12348                         while ((c = pgetc()) != '\n' && c != PEOF)
12349                                 continue;
12350                         pungetc();
12351                         continue;
12352                 case '\\':
12353                         if (pgetc() == '\n') {
12354                                 nlprompt();
12355                                 continue;
12356                         }
12357                         pungetc();
12358                         goto breakloop;
12359                 case '\n':
12360                         nlnoprompt();
12361                         RETURN(TNL);
12362                 case PEOF:
12363                         RETURN(TEOF);
12364                 case '&':
12365                         if (pgetc() == '&')
12366                                 RETURN(TAND);
12367                         pungetc();
12368                         RETURN(TBACKGND);
12369                 case '|':
12370                         if (pgetc() == '|')
12371                                 RETURN(TOR);
12372                         pungetc();
12373                         RETURN(TPIPE);
12374                 case ';':
12375                         if (pgetc() == ';')
12376                                 RETURN(TENDCASE);
12377                         pungetc();
12378                         RETURN(TSEMI);
12379                 case '(':
12380                         RETURN(TLP);
12381                 case ')':
12382                         RETURN(TRP);
12383                 default:
12384                         goto breakloop;
12385                 }
12386         }
12387  breakloop:
12388         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12389 #undef RETURN
12390 }
12391 #endif /* old xxreadtoken */
12392
12393 static int
12394 readtoken(void)
12395 {
12396         int t;
12397         int kwd = checkkwd;
12398 #if DEBUG
12399         smallint alreadyseen = tokpushback;
12400 #endif
12401
12402 #if ENABLE_ASH_ALIAS
12403  top:
12404 #endif
12405
12406         t = xxreadtoken();
12407
12408         /*
12409          * eat newlines
12410          */
12411         if (kwd & CHKNL) {
12412                 while (t == TNL) {
12413                         parseheredoc();
12414                         t = xxreadtoken();
12415                 }
12416         }
12417
12418         if (t != TWORD || quoteflag) {
12419                 goto out;
12420         }
12421
12422         /*
12423          * check for keywords
12424          */
12425         if (kwd & CHKKWD) {
12426                 const char *const *pp;
12427
12428                 pp = findkwd(wordtext);
12429                 if (pp) {
12430                         lasttoken = t = pp - tokname_array;
12431                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12432                         goto out;
12433                 }
12434         }
12435
12436         if (checkkwd & CHKALIAS) {
12437 #if ENABLE_ASH_ALIAS
12438                 struct alias *ap;
12439                 ap = lookupalias(wordtext, 1);
12440                 if (ap != NULL) {
12441                         if (*ap->val) {
12442                                 pushstring(ap->val, ap);
12443                         }
12444                         goto top;
12445                 }
12446 #endif
12447         }
12448  out:
12449         checkkwd = 0;
12450 #if DEBUG
12451         if (!alreadyseen)
12452                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12453         else
12454                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12455 #endif
12456         return t;
12457 }
12458
12459 static int
12460 peektoken(void)
12461 {
12462         int t;
12463
12464         t = readtoken();
12465         tokpushback = 1;
12466         return t;
12467 }
12468
12469 /*
12470  * Read and parse a command.  Returns NODE_EOF on end of file.
12471  * (NULL is a valid parse tree indicating a blank line.)
12472  */
12473 static union node *
12474 parsecmd(int interact)
12475 {
12476         tokpushback = 0;
12477         checkkwd = 0;
12478         heredoclist = 0;
12479         doprompt = interact;
12480         setprompt_if(doprompt, doprompt);
12481         needprompt = 0;
12482         return list(1);
12483 }
12484
12485 /*
12486  * Input any here documents.
12487  */
12488 static void
12489 parseheredoc(void)
12490 {
12491         struct heredoc *here;
12492         union node *n;
12493
12494         here = heredoclist;
12495         heredoclist = NULL;
12496
12497         while (here) {
12498                 setprompt_if(needprompt, 2);
12499                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12500                                 here->eofmark, here->striptabs);
12501                 n = stzalloc(sizeof(struct narg));
12502                 n->narg.type = NARG;
12503                 /*n->narg.next = NULL; - stzalloc did it */
12504                 n->narg.text = wordtext;
12505                 n->narg.backquote = backquotelist;
12506                 here->here->nhere.doc = n;
12507                 here = here->next;
12508         }
12509 }
12510
12511
12512 /*
12513  * called by editline -- any expansions to the prompt should be added here.
12514  */
12515 static const char *
12516 expandstr(const char *ps)
12517 {
12518         union node n;
12519         int saveprompt;
12520
12521         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12522          * and token processing _can_ alter it (delete NULs etc). */
12523         setinputstring((char *)ps);
12524
12525         saveprompt = doprompt;
12526         doprompt = 0;
12527         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12528         doprompt = saveprompt;
12529
12530         popfile();
12531
12532         n.narg.type = NARG;
12533         n.narg.next = NULL;
12534         n.narg.text = wordtext;
12535         n.narg.backquote = backquotelist;
12536
12537         expandarg(&n, NULL, EXP_QUOTED);
12538         return stackblock();
12539 }
12540
12541 /*
12542  * Execute a command or commands contained in a string.
12543  */
12544 static int
12545 evalstring(char *s, int flags)
12546 {
12547         struct jmploc *volatile savehandler;
12548         struct jmploc jmploc;
12549         int ex;
12550
12551         union node *n;
12552         struct stackmark smark;
12553         int status;
12554
12555         s = sstrdup(s);
12556         setinputstring(s);
12557         setstackmark(&smark);
12558
12559         status = 0;
12560         /* On exception inside execution loop, we must popfile().
12561          * Try interactively:
12562          *      readonly a=a
12563          *      command eval "a=b"  # throws "is read only" error
12564          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12565          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12566          */
12567         savehandler = exception_handler;
12568         ex = setjmp(jmploc.loc);
12569         if (ex)
12570                 goto out;
12571         exception_handler = &jmploc;
12572
12573         while ((n = parsecmd(0)) != NODE_EOF) {
12574                 int i;
12575
12576                 i = evaltree(n, flags);
12577                 if (n)
12578                         status = i;
12579                 popstackmark(&smark);
12580                 if (evalskip)
12581                         break;
12582         }
12583  out:
12584         popstackmark(&smark);
12585         popfile();
12586         stunalloc(s);
12587
12588         exception_handler = savehandler;
12589         if (ex)
12590                 longjmp(exception_handler->loc, ex);
12591
12592         return status;
12593 }
12594
12595 /*
12596  * The eval command.
12597  */
12598 static int FAST_FUNC
12599 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12600 {
12601         char *p;
12602         char *concat;
12603
12604         if (argv[1]) {
12605                 p = argv[1];
12606                 argv += 2;
12607                 if (argv[0]) {
12608                         STARTSTACKSTR(concat);
12609                         for (;;) {
12610                                 concat = stack_putstr(p, concat);
12611                                 p = *argv++;
12612                                 if (p == NULL)
12613                                         break;
12614                                 STPUTC(' ', concat);
12615                         }
12616                         STPUTC('\0', concat);
12617                         p = grabstackstr(concat);
12618                 }
12619                 return evalstring(p, flags & EV_TESTED);
12620         }
12621         return 0;
12622 }
12623
12624 /*
12625  * Read and execute commands.
12626  * "Top" is nonzero for the top level command loop;
12627  * it turns on prompting if the shell is interactive.
12628  */
12629 static int
12630 cmdloop(int top)
12631 {
12632         union node *n;
12633         struct stackmark smark;
12634         int inter;
12635         int status = 0;
12636         int numeof = 0;
12637
12638         TRACE(("cmdloop(%d) called\n", top));
12639         for (;;) {
12640                 int skip;
12641
12642                 setstackmark(&smark);
12643 #if JOBS
12644                 if (doing_jobctl)
12645                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12646 #endif
12647                 inter = 0;
12648                 if (iflag && top) {
12649                         inter++;
12650                         chkmail();
12651                 }
12652                 n = parsecmd(inter);
12653 #if DEBUG
12654                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12655                         showtree(n);
12656 #endif
12657                 if (n == NODE_EOF) {
12658                         if (!top || numeof >= 50)
12659                                 break;
12660                         if (!stoppedjobs()) {
12661                                 if (!Iflag)
12662                                         break;
12663                                 out2str("\nUse \"exit\" to leave shell.\n");
12664                         }
12665                         numeof++;
12666                 } else if (nflag == 0) {
12667                         int i;
12668
12669                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12670                         job_warning >>= 1;
12671                         numeof = 0;
12672                         i = evaltree(n, 0);
12673                         if (n)
12674                                 status = i;
12675                 }
12676                 popstackmark(&smark);
12677                 skip = evalskip;
12678
12679                 if (skip) {
12680                         evalskip &= ~SKIPFUNC;
12681                         break;
12682                 }
12683         }
12684         return status;
12685 }
12686
12687 /*
12688  * Take commands from a file.  To be compatible we should do a path
12689  * search for the file, which is necessary to find sub-commands.
12690  */
12691 static char *
12692 find_dot_file(char *name)
12693 {
12694         char *fullname;
12695         const char *path = pathval();
12696         struct stat statb;
12697
12698         /* don't try this for absolute or relative paths */
12699         if (strchr(name, '/'))
12700                 return name;
12701
12702         while ((fullname = path_advance(&path, name)) != NULL) {
12703                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12704                         /*
12705                          * Don't bother freeing here, since it will
12706                          * be freed by the caller.
12707                          */
12708                         return fullname;
12709                 }
12710                 if (fullname != name)
12711                         stunalloc(fullname);
12712         }
12713
12714         /* not found in the PATH */
12715         ash_msg_and_raise_error("%s: not found", name);
12716         /* NOTREACHED */
12717 }
12718
12719 static int FAST_FUNC
12720 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12721 {
12722         /* "false; . empty_file; echo $?" should print 0, not 1: */
12723         int status = 0;
12724         char *fullname;
12725         char **argv;
12726         char *args_need_save;
12727         struct strlist *sp;
12728         volatile struct shparam saveparam;
12729
12730         for (sp = cmdenviron; sp; sp = sp->next)
12731                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12732
12733         nextopt(nullstr); /* handle possible "--" */
12734         argv = argptr;
12735
12736         if (!argv[0]) {
12737                 /* bash says: "bash: .: filename argument required" */
12738                 return 2; /* bash compat */
12739         }
12740
12741         /* This aborts if file isn't found, which is POSIXly correct.
12742          * bash returns exitcode 1 instead.
12743          */
12744         fullname = find_dot_file(argv[0]);
12745         argv++;
12746         args_need_save = argv[0];
12747         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12748                 int argc;
12749                 saveparam = shellparam;
12750                 shellparam.malloced = 0;
12751                 argc = 1;
12752                 while (argv[argc])
12753                         argc++;
12754                 shellparam.nparam = argc;
12755                 shellparam.p = argv;
12756         };
12757
12758         /* This aborts if file can't be opened, which is POSIXly correct.
12759          * bash returns exitcode 1 instead.
12760          */
12761         setinputfile(fullname, INPUT_PUSH_FILE);
12762         commandname = fullname;
12763         status = cmdloop(0);
12764         popfile();
12765
12766         if (args_need_save) {
12767                 freeparam(&shellparam);
12768                 shellparam = saveparam;
12769         };
12770
12771         return status;
12772 }
12773
12774 static int FAST_FUNC
12775 exitcmd(int argc UNUSED_PARAM, char **argv)
12776 {
12777         if (stoppedjobs())
12778                 return 0;
12779         if (argv[1])
12780                 exitstatus = number(argv[1]);
12781         raise_exception(EXEXIT);
12782         /* NOTREACHED */
12783 }
12784
12785 /*
12786  * Read a file containing shell functions.
12787  */
12788 static void
12789 readcmdfile(char *name)
12790 {
12791         setinputfile(name, INPUT_PUSH_FILE);
12792         cmdloop(0);
12793         popfile();
12794 }
12795
12796
12797 /* ============ find_command inplementation */
12798
12799 /*
12800  * Resolve a command name.  If you change this routine, you may have to
12801  * change the shellexec routine as well.
12802  */
12803 static void
12804 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12805 {
12806         struct tblentry *cmdp;
12807         int idx;
12808         int prev;
12809         char *fullname;
12810         struct stat statb;
12811         int e;
12812         int updatetbl;
12813         struct builtincmd *bcmd;
12814
12815         /* If name contains a slash, don't use PATH or hash table */
12816         if (strchr(name, '/') != NULL) {
12817                 entry->u.index = -1;
12818                 if (act & DO_ABS) {
12819                         while (stat(name, &statb) < 0) {
12820 #ifdef SYSV
12821                                 if (errno == EINTR)
12822                                         continue;
12823 #endif
12824                                 entry->cmdtype = CMDUNKNOWN;
12825                                 return;
12826                         }
12827                 }
12828                 entry->cmdtype = CMDNORMAL;
12829                 return;
12830         }
12831
12832 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12833
12834         updatetbl = (path == pathval());
12835         if (!updatetbl) {
12836                 act |= DO_ALTPATH;
12837                 if (strstr(path, "%builtin") != NULL)
12838                         act |= DO_ALTBLTIN;
12839         }
12840
12841         /* If name is in the table, check answer will be ok */
12842         cmdp = cmdlookup(name, 0);
12843         if (cmdp != NULL) {
12844                 int bit;
12845
12846                 switch (cmdp->cmdtype) {
12847                 default:
12848 #if DEBUG
12849                         abort();
12850 #endif
12851                 case CMDNORMAL:
12852                         bit = DO_ALTPATH;
12853                         break;
12854                 case CMDFUNCTION:
12855                         bit = DO_NOFUNC;
12856                         break;
12857                 case CMDBUILTIN:
12858                         bit = DO_ALTBLTIN;
12859                         break;
12860                 }
12861                 if (act & bit) {
12862                         updatetbl = 0;
12863                         cmdp = NULL;
12864                 } else if (cmdp->rehash == 0)
12865                         /* if not invalidated by cd, we're done */
12866                         goto success;
12867         }
12868
12869         /* If %builtin not in path, check for builtin next */
12870         bcmd = find_builtin(name);
12871         if (bcmd) {
12872                 if (IS_BUILTIN_REGULAR(bcmd))
12873                         goto builtin_success;
12874                 if (act & DO_ALTPATH) {
12875                         if (!(act & DO_ALTBLTIN))
12876                                 goto builtin_success;
12877                 } else if (builtinloc <= 0) {
12878                         goto builtin_success;
12879                 }
12880         }
12881
12882 #if ENABLE_FEATURE_SH_STANDALONE
12883         {
12884                 int applet_no = find_applet_by_name(name);
12885                 if (applet_no >= 0) {
12886                         entry->cmdtype = CMDNORMAL;
12887                         entry->u.index = -2 - applet_no;
12888                         return;
12889                 }
12890         }
12891 #endif
12892
12893         /* We have to search path. */
12894         prev = -1;              /* where to start */
12895         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12896                 if (cmdp->cmdtype == CMDBUILTIN)
12897                         prev = builtinloc;
12898                 else
12899                         prev = cmdp->param.index;
12900         }
12901
12902         e = ENOENT;
12903         idx = -1;
12904  loop:
12905         while ((fullname = path_advance(&path, name)) != NULL) {
12906                 stunalloc(fullname);
12907                 /* NB: code below will still use fullname
12908                  * despite it being "unallocated" */
12909                 idx++;
12910                 if (pathopt) {
12911                         if (prefix(pathopt, "builtin")) {
12912                                 if (bcmd)
12913                                         goto builtin_success;
12914                                 continue;
12915                         }
12916                         if ((act & DO_NOFUNC)
12917                          || !prefix(pathopt, "func")
12918                         ) {     /* ignore unimplemented options */
12919                                 continue;
12920                         }
12921                 }
12922                 /* if rehash, don't redo absolute path names */
12923                 if (fullname[0] == '/' && idx <= prev) {
12924                         if (idx < prev)
12925                                 continue;
12926                         TRACE(("searchexec \"%s\": no change\n", name));
12927                         goto success;
12928                 }
12929                 while (stat(fullname, &statb) < 0) {
12930 #ifdef SYSV
12931                         if (errno == EINTR)
12932                                 continue;
12933 #endif
12934                         if (errno != ENOENT && errno != ENOTDIR)
12935                                 e = errno;
12936                         goto loop;
12937                 }
12938                 e = EACCES;     /* if we fail, this will be the error */
12939                 if (!S_ISREG(statb.st_mode))
12940                         continue;
12941                 if (pathopt) {          /* this is a %func directory */
12942                         stalloc(strlen(fullname) + 1);
12943                         /* NB: stalloc will return space pointed by fullname
12944                          * (because we don't have any intervening allocations
12945                          * between stunalloc above and this stalloc) */
12946                         readcmdfile(fullname);
12947                         cmdp = cmdlookup(name, 0);
12948                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12949                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12950                         stunalloc(fullname);
12951                         goto success;
12952                 }
12953                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12954                 if (!updatetbl) {
12955                         entry->cmdtype = CMDNORMAL;
12956                         entry->u.index = idx;
12957                         return;
12958                 }
12959                 INT_OFF;
12960                 cmdp = cmdlookup(name, 1);
12961                 cmdp->cmdtype = CMDNORMAL;
12962                 cmdp->param.index = idx;
12963                 INT_ON;
12964                 goto success;
12965         }
12966
12967         /* We failed.  If there was an entry for this command, delete it */
12968         if (cmdp && updatetbl)
12969                 delete_cmd_entry();
12970         if (act & DO_ERR)
12971                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12972         entry->cmdtype = CMDUNKNOWN;
12973         return;
12974
12975  builtin_success:
12976         if (!updatetbl) {
12977                 entry->cmdtype = CMDBUILTIN;
12978                 entry->u.cmd = bcmd;
12979                 return;
12980         }
12981         INT_OFF;
12982         cmdp = cmdlookup(name, 1);
12983         cmdp->cmdtype = CMDBUILTIN;
12984         cmdp->param.cmd = bcmd;
12985         INT_ON;
12986  success:
12987         cmdp->rehash = 0;
12988         entry->cmdtype = cmdp->cmdtype;
12989         entry->u = cmdp->param;
12990 }
12991
12992
12993 /*
12994  * The trap builtin.
12995  */
12996 static int FAST_FUNC
12997 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12998 {
12999         char *action;
13000         char **ap;
13001         int signo, exitcode;
13002
13003         nextopt(nullstr);
13004         ap = argptr;
13005         if (!*ap) {
13006                 for (signo = 0; signo < NSIG; signo++) {
13007                         char *tr = trap_ptr[signo];
13008                         if (tr) {
13009                                 /* note: bash adds "SIG", but only if invoked
13010                                  * as "bash". If called as "sh", or if set -o posix,
13011                                  * then it prints short signal names.
13012                                  * We are printing short names: */
13013                                 out1fmt("trap -- %s %s\n",
13014                                                 single_quote(tr),
13015                                                 get_signame(signo));
13016                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13017                  * In this case, we will exit very soon, no need to free(). */
13018                                 /* if (trap_ptr != trap && tp[0]) */
13019                                 /*      free(tr); */
13020                         }
13021                 }
13022                 /*
13023                 if (trap_ptr != trap) {
13024                         free(trap_ptr);
13025                         trap_ptr = trap;
13026                 }
13027                 */
13028                 return 0;
13029         }
13030
13031         action = NULL;
13032         if (ap[1])
13033                 action = *ap++;
13034         exitcode = 0;
13035         while (*ap) {
13036                 signo = get_signum(*ap);
13037                 if (signo < 0 || signo >= NSIG) {
13038                         /* Mimic bash message exactly */
13039                         ash_msg("%s: invalid signal specification", *ap);
13040                         exitcode = 1;
13041                         goto next;
13042                 }
13043                 INT_OFF;
13044                 if (action) {
13045                         if (LONE_DASH(action))
13046                                 action = NULL;
13047                         else {
13048                                 if (action[0]) /* not NULL and not "" and not "-" */
13049                                         may_have_traps = 1;
13050                                 action = ckstrdup(action);
13051                         }
13052                 }
13053                 free(trap[signo]);
13054                 trap[signo] = action;
13055                 if (signo != 0)
13056                         setsignal(signo);
13057                 INT_ON;
13058  next:
13059                 ap++;
13060         }
13061         return exitcode;
13062 }
13063
13064
13065 /* ============ Builtins */
13066
13067 #if ENABLE_ASH_HELP
13068 static int FAST_FUNC
13069 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13070 {
13071         unsigned col;
13072         unsigned i;
13073
13074         out1fmt(
13075                 "Built-in commands:\n"
13076                 "------------------\n");
13077         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13078                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13079                                         builtintab[i].name + 1);
13080                 if (col > 60) {
13081                         out1fmt("\n");
13082                         col = 0;
13083                 }
13084         }
13085 # if ENABLE_FEATURE_SH_STANDALONE
13086         {
13087                 const char *a = applet_names;
13088                 while (*a) {
13089                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13090                         if (col > 60) {
13091                                 out1fmt("\n");
13092                                 col = 0;
13093                         }
13094                         while (*a++ != '\0')
13095                                 continue;
13096                 }
13097         }
13098 # endif
13099         newline_and_flush(stdout);
13100         return EXIT_SUCCESS;
13101 }
13102 #endif
13103
13104 #if MAX_HISTORY
13105 static int FAST_FUNC
13106 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13107 {
13108         show_history(line_input_state);
13109         return EXIT_SUCCESS;
13110 }
13111 #endif
13112
13113 /*
13114  * The export and readonly commands.
13115  */
13116 static int FAST_FUNC
13117 exportcmd(int argc UNUSED_PARAM, char **argv)
13118 {
13119         struct var *vp;
13120         char *name;
13121         const char *p;
13122         char **aptr;
13123         char opt;
13124         int flag;
13125         int flag_off;
13126
13127         /* "readonly" in bash accepts, but ignores -n.
13128          * We do the same: it saves a conditional in nextopt's param.
13129          */
13130         flag_off = 0;
13131         while ((opt = nextopt("np")) != '\0') {
13132                 if (opt == 'n')
13133                         flag_off = VEXPORT;
13134         }
13135         flag = VEXPORT;
13136         if (argv[0][0] == 'r') {
13137                 flag = VREADONLY;
13138                 flag_off = 0; /* readonly ignores -n */
13139         }
13140         flag_off = ~flag_off;
13141
13142         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13143         {
13144                 aptr = argptr;
13145                 name = *aptr;
13146                 if (name) {
13147                         do {
13148                                 p = strchr(name, '=');
13149                                 if (p != NULL) {
13150                                         p++;
13151                                 } else {
13152                                         vp = *findvar(hashvar(name), name);
13153                                         if (vp) {
13154                                                 vp->flags = ((vp->flags | flag) & flag_off);
13155                                                 continue;
13156                                         }
13157                                 }
13158                                 setvar(name, p, (flag & flag_off));
13159                         } while ((name = *++aptr) != NULL);
13160                         return 0;
13161                 }
13162         }
13163
13164         /* No arguments. Show the list of exported or readonly vars.
13165          * -n is ignored.
13166          */
13167         showvars(argv[0], flag, 0);
13168         return 0;
13169 }
13170
13171 /*
13172  * Delete a function if it exists.
13173  */
13174 static void
13175 unsetfunc(const char *name)
13176 {
13177         struct tblentry *cmdp;
13178
13179         cmdp = cmdlookup(name, 0);
13180         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13181                 delete_cmd_entry();
13182 }
13183
13184 /*
13185  * The unset builtin command.  We unset the function before we unset the
13186  * variable to allow a function to be unset when there is a readonly variable
13187  * with the same name.
13188  */
13189 static int FAST_FUNC
13190 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13191 {
13192         char **ap;
13193         int i;
13194         int flag = 0;
13195
13196         while ((i = nextopt("vf")) != 0) {
13197                 flag = i;
13198         }
13199
13200         for (ap = argptr; *ap; ap++) {
13201                 if (flag != 'f') {
13202                         unsetvar(*ap);
13203                         continue;
13204                 }
13205                 if (flag != 'v')
13206                         unsetfunc(*ap);
13207         }
13208         return 0;
13209 }
13210
13211 static const unsigned char timescmd_str[] ALIGN1 = {
13212         ' ',  offsetof(struct tms, tms_utime),
13213         '\n', offsetof(struct tms, tms_stime),
13214         ' ',  offsetof(struct tms, tms_cutime),
13215         '\n', offsetof(struct tms, tms_cstime),
13216         0
13217 };
13218 static int FAST_FUNC
13219 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13220 {
13221         unsigned long clk_tck, s, t;
13222         const unsigned char *p;
13223         struct tms buf;
13224
13225         clk_tck = bb_clk_tck();
13226         times(&buf);
13227
13228         p = timescmd_str;
13229         do {
13230                 t = *(clock_t *)(((char *) &buf) + p[1]);
13231                 s = t / clk_tck;
13232                 t = t % clk_tck;
13233                 out1fmt("%lum%lu.%03lus%c",
13234                         s / 60, s % 60,
13235                         (t * 1000) / clk_tck,
13236                         p[0]);
13237                 p += 2;
13238         } while (*p);
13239
13240         return 0;
13241 }
13242
13243 #if ENABLE_FEATURE_SH_MATH
13244 /*
13245  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13246  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13247  *
13248  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13249  */
13250 static int FAST_FUNC
13251 letcmd(int argc UNUSED_PARAM, char **argv)
13252 {
13253         arith_t i;
13254
13255         argv++;
13256         if (!*argv)
13257                 ash_msg_and_raise_error("expression expected");
13258         do {
13259                 i = ash_arith(*argv);
13260         } while (*++argv);
13261
13262         return !i;
13263 }
13264 #endif
13265
13266 /*
13267  * The read builtin. Options:
13268  *      -r              Do not interpret '\' specially
13269  *      -s              Turn off echo (tty only)
13270  *      -n NCHARS       Read NCHARS max
13271  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13272  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13273  *      -u FD           Read from given FD instead of fd 0
13274  * This uses unbuffered input, which may be avoidable in some cases.
13275  * TODO: bash also has:
13276  *      -a ARRAY        Read into array[0],[1],etc
13277  *      -d DELIM        End on DELIM char, not newline
13278  *      -e              Use line editing (tty only)
13279  */
13280 static int FAST_FUNC
13281 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13282 {
13283         char *opt_n = NULL;
13284         char *opt_p = NULL;
13285         char *opt_t = NULL;
13286         char *opt_u = NULL;
13287         int read_flags = 0;
13288         const char *r;
13289         int i;
13290
13291         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13292                 switch (i) {
13293                 case 'p':
13294                         opt_p = optionarg;
13295                         break;
13296                 case 'n':
13297                         opt_n = optionarg;
13298                         break;
13299                 case 's':
13300                         read_flags |= BUILTIN_READ_SILENT;
13301                         break;
13302                 case 't':
13303                         opt_t = optionarg;
13304                         break;
13305                 case 'r':
13306                         read_flags |= BUILTIN_READ_RAW;
13307                         break;
13308                 case 'u':
13309                         opt_u = optionarg;
13310                         break;
13311                 default:
13312                         break;
13313                 }
13314         }
13315
13316         /* "read -s" needs to save/restore termios, can't allow ^C
13317          * to jump out of it.
13318          */
13319  again:
13320         INT_OFF;
13321         r = shell_builtin_read(setvar0,
13322                 argptr,
13323                 bltinlookup("IFS"), /* can be NULL */
13324                 read_flags,
13325                 opt_n,
13326                 opt_p,
13327                 opt_t,
13328                 opt_u
13329         );
13330         INT_ON;
13331
13332         if ((uintptr_t)r == 1 && errno == EINTR) {
13333                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13334                 if (pending_sig == 0)
13335                         goto again;
13336         }
13337
13338         if ((uintptr_t)r > 1)
13339                 ash_msg_and_raise_error(r);
13340
13341         return (uintptr_t)r;
13342 }
13343
13344 static int FAST_FUNC
13345 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13346 {
13347         static const char permuser[3] ALIGN1 = "ogu";
13348
13349         mode_t mask;
13350         int symbolic_mode = 0;
13351
13352         while (nextopt("S") != '\0') {
13353                 symbolic_mode = 1;
13354         }
13355
13356         INT_OFF;
13357         mask = umask(0);
13358         umask(mask);
13359         INT_ON;
13360
13361         if (*argptr == NULL) {
13362                 if (symbolic_mode) {
13363                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13364                         char *p = buf;
13365                         int i;
13366
13367                         i = 2;
13368                         for (;;) {
13369                                 *p++ = ',';
13370                                 *p++ = permuser[i];
13371                                 *p++ = '=';
13372                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13373                                 if (!(mask & 0400)) *p++ = 'r';
13374                                 if (!(mask & 0200)) *p++ = 'w';
13375                                 if (!(mask & 0100)) *p++ = 'x';
13376                                 mask <<= 3;
13377                                 if (--i < 0)
13378                                         break;
13379                         }
13380                         *p = '\0';
13381                         puts(buf + 1);
13382                 } else {
13383                         out1fmt("%04o\n", mask);
13384                 }
13385         } else {
13386                 char *modestr = *argptr;
13387                 /* numeric umasks are taken as-is */
13388                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13389                 if (!isdigit(modestr[0]))
13390                         mask ^= 0777;
13391                 mask = bb_parse_mode(modestr, mask);
13392                 if ((unsigned)mask > 0777) {
13393                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13394                 }
13395                 if (!isdigit(modestr[0]))
13396                         mask ^= 0777;
13397                 umask(mask);
13398         }
13399         return 0;
13400 }
13401
13402 static int FAST_FUNC
13403 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13404 {
13405         return shell_builtin_ulimit(argv);
13406 }
13407
13408 /* ============ main() and helpers */
13409
13410 /*
13411  * Called to exit the shell.
13412  */
13413 static void
13414 exitshell(void)
13415 {
13416         struct jmploc loc;
13417         char *p;
13418         int status;
13419
13420 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13421         save_history(line_input_state);
13422 #endif
13423         status = exitstatus;
13424         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13425         if (setjmp(loc.loc)) {
13426                 if (exception_type == EXEXIT)
13427                         status = exitstatus;
13428                 goto out;
13429         }
13430         exception_handler = &loc;
13431         p = trap[0];
13432         if (p) {
13433                 trap[0] = NULL;
13434                 evalskip = 0;
13435                 evalstring(p, 0);
13436                 /*free(p); - we'll exit soon */
13437         }
13438  out:
13439         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13440          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13441          */
13442         setjobctl(0);
13443         flush_stdout_stderr();
13444         _exit(status);
13445         /* NOTREACHED */
13446 }
13447
13448 static void
13449 init(void)
13450 {
13451         /* we will never free this */
13452         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13453
13454         sigmode[SIGCHLD - 1] = S_DFL;
13455         setsignal(SIGCHLD);
13456
13457         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13458          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13459          */
13460         signal(SIGHUP, SIG_DFL);
13461
13462         {
13463                 char **envp;
13464                 const char *p;
13465                 struct stat st1, st2;
13466
13467                 initvar();
13468                 for (envp = environ; envp && *envp; envp++) {
13469                         p = endofname(*envp);
13470                         if (p != *envp && *p == '=') {
13471                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13472                         }
13473                 }
13474
13475                 setvareq((char*)defoptindvar, VTEXTFIXED);
13476
13477                 setvar0("PPID", utoa(getppid()));
13478 #if BASH_SHLVL_VAR
13479                 p = lookupvar("SHLVL");
13480                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13481 #endif
13482 #if BASH_HOSTNAME_VAR
13483                 if (!lookupvar("HOSTNAME")) {
13484                         struct utsname uts;
13485                         uname(&uts);
13486                         setvar0("HOSTNAME", uts.nodename);
13487                 }
13488 #endif
13489                 p = lookupvar("PWD");
13490                 if (p) {
13491                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13492                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13493                         ) {
13494                                 p = NULL;
13495                         }
13496                 }
13497                 setpwd(p, 0);
13498         }
13499 }
13500
13501
13502 //usage:#define ash_trivial_usage
13503 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13504 //usage:#define ash_full_usage "\n\n"
13505 //usage:        "Unix shell interpreter"
13506
13507 /*
13508  * Process the shell command line arguments.
13509  */
13510 static void
13511 procargs(char **argv)
13512 {
13513         int i;
13514         const char *xminusc;
13515         char **xargv;
13516
13517         xargv = argv;
13518         arg0 = xargv[0];
13519         /* if (xargv[0]) - mmm, this is always true! */
13520                 xargv++;
13521         for (i = 0; i < NOPTS; i++)
13522                 optlist[i] = 2;
13523         argptr = xargv;
13524         if (options(/*cmdline:*/ 1)) {
13525                 /* it already printed err message */
13526                 raise_exception(EXERROR);
13527         }
13528         xargv = argptr;
13529         xminusc = minusc;
13530         if (*xargv == NULL) {
13531                 if (xminusc)
13532                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13533                 sflag = 1;
13534         }
13535         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13536                 iflag = 1;
13537         if (mflag == 2)
13538                 mflag = iflag;
13539         for (i = 0; i < NOPTS; i++)
13540                 if (optlist[i] == 2)
13541                         optlist[i] = 0;
13542 #if DEBUG == 2
13543         debug = 1;
13544 #endif
13545         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13546         if (xminusc) {
13547                 minusc = *xargv++;
13548                 if (*xargv)
13549                         goto setarg0;
13550         } else if (!sflag) {
13551                 setinputfile(*xargv, 0);
13552  setarg0:
13553                 arg0 = *xargv++;
13554                 commandname = arg0;
13555         }
13556
13557         shellparam.p = xargv;
13558 #if ENABLE_ASH_GETOPTS
13559         shellparam.optind = 1;
13560         shellparam.optoff = -1;
13561 #endif
13562         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13563         while (*xargv) {
13564                 shellparam.nparam++;
13565                 xargv++;
13566         }
13567         optschanged();
13568 }
13569
13570 /*
13571  * Read /etc/profile, ~/.profile, $ENV.
13572  */
13573 static void
13574 read_profile(const char *name)
13575 {
13576         name = expandstr(name);
13577         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13578                 return;
13579         cmdloop(0);
13580         popfile();
13581 }
13582
13583 /*
13584  * This routine is called when an error or an interrupt occurs in an
13585  * interactive shell and control is returned to the main command loop.
13586  * (In dash, this function is auto-generated by build machinery).
13587  */
13588 static void
13589 reset(void)
13590 {
13591         /* from eval.c: */
13592         evalskip = 0;
13593         loopnest = 0;
13594
13595         /* from expand.c: */
13596         ifsfree();
13597
13598         /* from input.c: */
13599         g_parsefile->left_in_buffer = 0;
13600         g_parsefile->left_in_line = 0;      /* clear input buffer */
13601         popallfiles();
13602
13603         /* from redir.c: */
13604         while (redirlist)
13605                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13606 }
13607
13608 #if PROFILE
13609 static short profile_buf[16384];
13610 extern int etext();
13611 #endif
13612
13613 /*
13614  * Main routine.  We initialize things, parse the arguments, execute
13615  * profiles if we're a login shell, and then call cmdloop to execute
13616  * commands.  The setjmp call sets up the location to jump to when an
13617  * exception occurs.  When an exception occurs the variable "state"
13618  * is used to figure out how far we had gotten.
13619  */
13620 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13621 int ash_main(int argc UNUSED_PARAM, char **argv)
13622 {
13623         volatile smallint state;
13624         struct jmploc jmploc;
13625         struct stackmark smark;
13626
13627         /* Initialize global data */
13628         INIT_G_misc();
13629         INIT_G_memstack();
13630         INIT_G_var();
13631 #if ENABLE_ASH_ALIAS
13632         INIT_G_alias();
13633 #endif
13634         INIT_G_cmdtable();
13635
13636 #if PROFILE
13637         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13638 #endif
13639
13640 #if ENABLE_FEATURE_EDITING
13641         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13642 #endif
13643         state = 0;
13644         if (setjmp(jmploc.loc)) {
13645                 smallint e;
13646                 smallint s;
13647
13648                 reset();
13649
13650                 e = exception_type;
13651                 s = state;
13652                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13653                         exitshell();
13654                 }
13655                 if (e == EXINT) {
13656                         newline_and_flush(stderr);
13657                 }
13658
13659                 popstackmark(&smark);
13660                 FORCE_INT_ON; /* enable interrupts */
13661                 if (s == 1)
13662                         goto state1;
13663                 if (s == 2)
13664                         goto state2;
13665                 if (s == 3)
13666                         goto state3;
13667                 goto state4;
13668         }
13669         exception_handler = &jmploc;
13670         rootpid = getpid();
13671
13672         init();
13673         setstackmark(&smark);
13674         procargs(argv);
13675 #if DEBUG
13676         TRACE(("Shell args: "));
13677         trace_puts_args(argv);
13678 #endif
13679
13680         if (argv[0] && argv[0][0] == '-')
13681                 isloginsh = 1;
13682         if (isloginsh) {
13683                 const char *hp;
13684
13685                 state = 1;
13686                 read_profile("/etc/profile");
13687  state1:
13688                 state = 2;
13689                 hp = lookupvar("HOME");
13690                 if (hp)
13691                         read_profile("$HOME/.profile");
13692         }
13693  state2:
13694         state = 3;
13695         if (
13696 #ifndef linux
13697          getuid() == geteuid() && getgid() == getegid() &&
13698 #endif
13699          iflag
13700         ) {
13701                 const char *shinit = lookupvar("ENV");
13702                 if (shinit != NULL && *shinit != '\0')
13703                         read_profile(shinit);
13704         }
13705         popstackmark(&smark);
13706  state3:
13707         state = 4;
13708         if (minusc) {
13709                 /* evalstring pushes parsefile stack.
13710                  * Ensure we don't falsely claim that 0 (stdin)
13711                  * is one of stacked source fds.
13712                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13713                 // if (!sflag) g_parsefile->pf_fd = -1;
13714                 // ^^ not necessary since now we special-case fd 0
13715                 // in is_hidden_fd() to not be considered "hidden fd"
13716                 evalstring(minusc, 0);
13717         }
13718
13719         if (sflag || minusc == NULL) {
13720 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13721                 if (iflag) {
13722                         const char *hp = lookupvar("HISTFILE");
13723                         if (!hp) {
13724                                 hp = lookupvar("HOME");
13725                                 if (hp) {
13726                                         INT_OFF;
13727                                         hp = concat_path_file(hp, ".ash_history");
13728                                         setvar0("HISTFILE", hp);
13729                                         free((char*)hp);
13730                                         INT_ON;
13731                                         hp = lookupvar("HISTFILE");
13732                                 }
13733                         }
13734                         if (hp)
13735                                 line_input_state->hist_file = hp;
13736 # if ENABLE_FEATURE_SH_HISTFILESIZE
13737                         hp = lookupvar("HISTFILESIZE");
13738                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13739 # endif
13740                 }
13741 #endif
13742  state4: /* XXX ??? - why isn't this before the "if" statement */
13743                 cmdloop(1);
13744         }
13745 #if PROFILE
13746         monitor(0);
13747 #endif
13748 #ifdef GPROF
13749         {
13750                 extern void _mcleanup(void);
13751                 _mcleanup();
13752         }
13753 #endif
13754         TRACE(("End of main reached\n"));
13755         exitshell();
13756         /* NOTREACHED */
13757 }
13758
13759
13760 /*-
13761  * Copyright (c) 1989, 1991, 1993, 1994
13762  *      The Regents of the University of California.  All rights reserved.
13763  *
13764  * This code is derived from software contributed to Berkeley by
13765  * Kenneth Almquist.
13766  *
13767  * Redistribution and use in source and binary forms, with or without
13768  * modification, are permitted provided that the following conditions
13769  * are met:
13770  * 1. Redistributions of source code must retain the above copyright
13771  *    notice, this list of conditions and the following disclaimer.
13772  * 2. Redistributions in binary form must reproduce the above copyright
13773  *    notice, this list of conditions and the following disclaimer in the
13774  *    documentation and/or other materials provided with the distribution.
13775  * 3. Neither the name of the University nor the names of its contributors
13776  *    may be used to endorse or promote products derived from this software
13777  *    without specific prior written permission.
13778  *
13779  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13780  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13781  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13782  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13783  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13784  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13785  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13786  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13787  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13788  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13789  * SUCH DAMAGE.
13790  */