hush: rename a few functions
[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"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:         Tha 'ash' shell adds about 60k in the default configuration and is
24 //config:         the most complete and most pedantically correct shell included with
25 //config:         busybox. This shell is actually a derivative of the Debian 'dash'
26 //config:         shell (by Herbert Xu), which was created by porting the 'ash' shell
27 //config:         (written by Kenneth Almquist) from NetBSD.
28 //config:
29 //config:# ash options
30 //config:# note: Don't remove !NOMMU part in the next line; it would break
31 //config:# menuconfig's indenting.
32 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
33 //config:
34 //config:config ASH_OPTIMIZE_FOR_SIZE
35 //config:       bool "Optimize for size instead of speed"
36 //config:       default y
37 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
38 //config:
39 //config:config ASH_INTERNAL_GLOB
40 //config:       bool "Use internal glob() implementation"
41 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
42 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
43 //config:       help
44 //config:         Do not use glob() function from libc, use internal implementation.
45 //config:         Use this if you are getting "glob.h: No such file or directory"
46 //config:         or similar build errors.
47 //config:         Note that as of now (2017-01), uclibc and musl glob() both have bugs
48 //config:         which would break ash if you select N here.
49 //config:
50 //config:config ASH_BASH_COMPAT
51 //config:       bool "bash-compatible extensions"
52 //config:       default y
53 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
54 //config:
55 //config:config ASH_JOB_CONTROL
56 //config:       bool "Job control"
57 //config:       default y
58 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
59 //config:
60 //config:config ASH_ALIAS
61 //config:       bool "Alias support"
62 //config:       default y
63 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
64 //config:
65 //config:config ASH_RANDOM_SUPPORT
66 //config:       bool "Pseudorandom generator and $RANDOM variable"
67 //config:       default y
68 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
69 //config:       help
70 //config:         Enable pseudorandom generator and dynamic variable "$RANDOM".
71 //config:         Each read of "$RANDOM" will generate a new pseudorandom value.
72 //config:         You can reset the generator by using a specified start value.
73 //config:         After "unset RANDOM" the generator will switch off and this
74 //config:         variable will no longer have special treatment.
75 //config:
76 //config:config ASH_EXPAND_PRMT
77 //config:       bool "Expand prompt string"
78 //config:       default y
79 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
80 //config:       help
81 //config:         $PS# may contain volatile content, such as backquote commands.
82 //config:         This option recreates the prompt string from the environment
83 //config:         variable each time it is displayed.
84 //config:
85 //config:config ASH_IDLE_TIMEOUT
86 //config:       bool "Idle timeout variable $TMOUT"
87 //config:       default y
88 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
89 //config:       help
90 //config:         Enable bash-like auto-logout after $TMOUT seconds of idle time.
91 //config:
92 //config:config ASH_MAIL
93 //config:       bool "Check for new mail in interactive shell"
94 //config:       default y
95 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
96 //config:       help
97 //config:         Enable "check for new mail" function:
98 //config:         if set, $MAIL file and $MAILPATH list of files
99 //config:         are checked for mtime changes, and "you have mail"
100 //config:         message is printed if change is detected.
101 //config:
102 //config:config ASH_ECHO
103 //config:       bool "echo builtin"
104 //config:       default y
105 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
106 //config:
107 //config:config ASH_PRINTF
108 //config:       bool "printf builtin"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:
112 //config:config ASH_TEST
113 //config:       bool "test builtin"
114 //config:       default y
115 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
116 //config:
117 //config:config ASH_HELP
118 //config:       bool "help builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_GETOPTS
123 //config:       bool "getopts builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_CMDCMD
128 //config:       bool "command builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:       help
132 //config:         Enable support for the 'command' builtin, which allows
133 //config:         you to run the specified command or builtin,
134 //config:         even when there is a function with the same name.
135 //config:
136 //config:endif # ash options
137
138 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
139 //                      APPLET_ODDNAME:name  main location    suid_type     help
140 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
142
143 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
146 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
147
148 /*
149  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
150  * DEBUG=2 to compile in and turn on debugging.
151  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
152  * debugging info is written to ./trace, quit signal generates core dump.
153  */
154 #define DEBUG 0
155 /* Tweak debug output verbosity here */
156 #define DEBUG_TIME 0
157 #define DEBUG_PID 1
158 #define DEBUG_SIG 1
159 #define DEBUG_INTONOFF 0
160
161 #define PROFILE 0
162
163 #define JOBS ENABLE_ASH_JOB_CONTROL
164
165 #include <setjmp.h>
166 #include <fnmatch.h>
167 #include <sys/times.h>
168 #include <sys/utsname.h> /* for setting $HOSTNAME */
169 #include "busybox.h" /* for applet_names */
170
171 /* So far, all bash compat is controlled by one config option */
172 /* Separate defines document which part of code implements what */
173 /* function keyword */
174 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
175 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
176 /* &>file */
177 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
178 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
179 /* $'...' */
180 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
181 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
182 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
183 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
184 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
185 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
186 /* [[ EXPR ]] */
187 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
188 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
189 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
190 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
191 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
192
193 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
194 /* Bionic at least up to version 24 has no glob() */
195 # undef  ENABLE_ASH_INTERNAL_GLOB
196 # define ENABLE_ASH_INTERNAL_GLOB 1
197 #endif
198
199 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
200 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
201 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
202 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
203 # error glob() should unbackslash them and match. uClibc does not unbackslash,
204 # error fails to match dirname, subsequently not expanding <pattern> in it.
205 // Testcase:
206 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
207 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
208 #endif
209
210 #if !ENABLE_ASH_INTERNAL_GLOB
211 # include <glob.h>
212 #endif
213
214 #include "unicode.h"
215 #include "shell_common.h"
216 #if ENABLE_FEATURE_SH_MATH
217 # include "math.h"
218 #endif
219 #if ENABLE_ASH_RANDOM_SUPPORT
220 # include "random.h"
221 #else
222 # define CLEAR_RANDOM_T(rnd) ((void)0)
223 #endif
224
225 #include "NUM_APPLETS.h"
226 #if NUM_APPLETS == 1
227 /* STANDALONE does not make sense, and won't compile */
228 # undef CONFIG_FEATURE_SH_STANDALONE
229 # undef ENABLE_FEATURE_SH_STANDALONE
230 # undef IF_FEATURE_SH_STANDALONE
231 # undef IF_NOT_FEATURE_SH_STANDALONE
232 # define ENABLE_FEATURE_SH_STANDALONE 0
233 # define IF_FEATURE_SH_STANDALONE(...)
234 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
235 #endif
236
237 #ifndef PIPE_BUF
238 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
239 #endif
240
241 #if !BB_MMU
242 # error "Do not even bother, ash will not run on NOMMU machine"
243 #endif
244
245
246 /* ============ Hash table sizes. Configurable. */
247
248 #define VTABSIZE 39
249 #define ATABSIZE 39
250 #define CMDTABLESIZE 31         /* should be prime */
251
252
253 /* ============ Shell options */
254
255 static const char *const optletters_optnames[] = {
256         "e"   "errexit",
257         "f"   "noglob",
258         "I"   "ignoreeof",
259         "i"   "interactive",
260         "m"   "monitor",
261         "n"   "noexec",
262         "s"   "stdin",
263         "x"   "xtrace",
264         "v"   "verbose",
265         "C"   "noclobber",
266         "a"   "allexport",
267         "b"   "notify",
268         "u"   "nounset",
269         "\0"  "vi"
270 #if BASH_PIPEFAIL
271         ,"\0"  "pipefail"
272 #endif
273 #if DEBUG
274         ,"\0"  "nolog"
275         ,"\0"  "debug"
276 #endif
277 };
278
279 #define optletters(n)  optletters_optnames[n][0]
280 #define optnames(n)   (optletters_optnames[n] + 1)
281
282 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
283
284
285 /* ============ Misc data */
286
287 #define msg_illnum "Illegal number: %s"
288
289 /*
290  * We enclose jmp_buf in a structure so that we can declare pointers to
291  * jump locations.  The global variable handler contains the location to
292  * jump to when an exception occurs, and the global variable exception_type
293  * contains a code identifying the exception.  To implement nested
294  * exception handlers, the user should save the value of handler on entry
295  * to an inner scope, set handler to point to a jmploc structure for the
296  * inner scope, and restore handler on exit from the scope.
297  */
298 struct jmploc {
299         jmp_buf loc;
300 };
301
302 struct globals_misc {
303         uint8_t exitstatus;     /* exit status of last command */
304         uint8_t back_exitstatus;/* exit status of backquoted command */
305         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
306         int rootpid;            /* pid of main shell */
307         /* shell level: 0 for the main shell, 1 for its children, and so on */
308         int shlvl;
309 #define rootshell (!shlvl)
310         char *minusc;  /* argument to -c option */
311
312         char *curdir; // = nullstr;     /* current working directory */
313         char *physdir; // = nullstr;    /* physical working directory */
314
315         char *arg0; /* value of $0 */
316
317         struct jmploc *exception_handler;
318
319         volatile int suppress_int; /* counter */
320         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
321         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
322         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
323         smallint exception_type; /* kind of exception (0..5) */
324         /* exceptions */
325 #define EXINT 0         /* SIGINT received */
326 #define EXERROR 1       /* a generic error */
327 #define EXEXIT 4        /* exit the shell */
328
329         smallint isloginsh;
330         char nullstr[1];        /* zero length string */
331
332         char optlist[NOPTS];
333 #define eflag optlist[0]
334 #define fflag optlist[1]
335 #define Iflag optlist[2]
336 #define iflag optlist[3]
337 #define mflag optlist[4]
338 #define nflag optlist[5]
339 #define sflag optlist[6]
340 #define xflag optlist[7]
341 #define vflag optlist[8]
342 #define Cflag optlist[9]
343 #define aflag optlist[10]
344 #define bflag optlist[11]
345 #define uflag optlist[12]
346 #define viflag optlist[13]
347 #if BASH_PIPEFAIL
348 # define pipefail optlist[14]
349 #else
350 # define pipefail 0
351 #endif
352 #if DEBUG
353 # define nolog optlist[14 + BASH_PIPEFAIL]
354 # define debug optlist[15 + BASH_PIPEFAIL]
355 #endif
356
357         /* trap handler commands */
358         /*
359          * Sigmode records the current value of the signal handlers for the various
360          * modes.  A value of zero means that the current handler is not known.
361          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
362          */
363         char sigmode[NSIG - 1];
364 #define S_DFL      1            /* default signal handling (SIG_DFL) */
365 #define S_CATCH    2            /* signal is caught */
366 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
367 #define S_HARD_IGN 4            /* signal is ignored permanently */
368
369         /* indicates specified signal received */
370         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
371         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
372         char *trap[NSIG];
373         char **trap_ptr;        /* used only by "trap hack" */
374
375         /* Rarely referenced stuff */
376 #if ENABLE_ASH_RANDOM_SUPPORT
377         random_t random_gen;
378 #endif
379         pid_t backgndpid;        /* pid of last background process */
380 };
381 extern struct globals_misc *const ash_ptr_to_globals_misc;
382 #define G_misc (*ash_ptr_to_globals_misc)
383 #define exitstatus        (G_misc.exitstatus )
384 #define back_exitstatus   (G_misc.back_exitstatus )
385 #define job_warning       (G_misc.job_warning)
386 #define rootpid     (G_misc.rootpid    )
387 #define shlvl       (G_misc.shlvl      )
388 #define minusc      (G_misc.minusc     )
389 #define curdir      (G_misc.curdir     )
390 #define physdir     (G_misc.physdir    )
391 #define arg0        (G_misc.arg0       )
392 #define exception_handler (G_misc.exception_handler)
393 #define exception_type    (G_misc.exception_type   )
394 #define suppress_int      (G_misc.suppress_int     )
395 #define pending_int       (G_misc.pending_int      )
396 #define got_sigchld       (G_misc.got_sigchld      )
397 #define pending_sig       (G_misc.pending_sig      )
398 #define isloginsh   (G_misc.isloginsh  )
399 #define nullstr     (G_misc.nullstr    )
400 #define optlist     (G_misc.optlist    )
401 #define sigmode     (G_misc.sigmode    )
402 #define gotsig      (G_misc.gotsig     )
403 #define may_have_traps    (G_misc.may_have_traps   )
404 #define trap        (G_misc.trap       )
405 #define trap_ptr    (G_misc.trap_ptr   )
406 #define random_gen  (G_misc.random_gen )
407 #define backgndpid  (G_misc.backgndpid )
408 #define INIT_G_misc() do { \
409         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
410         barrier(); \
411         curdir = nullstr; \
412         physdir = nullstr; \
413         trap_ptr = trap; \
414 } while (0)
415
416
417 /* ============ DEBUG */
418 #if DEBUG
419 static void trace_printf(const char *fmt, ...);
420 static void trace_vprintf(const char *fmt, va_list va);
421 # define TRACE(param)    trace_printf param
422 # define TRACEV(param)   trace_vprintf param
423 # define close(fd) do { \
424         int dfd = (fd); \
425         if (close(dfd) < 0) \
426                 bb_error_msg("bug on %d: closing %d(0x%x)", \
427                         __LINE__, dfd, dfd); \
428 } while (0)
429 #else
430 # define TRACE(param)
431 # define TRACEV(param)
432 #endif
433
434
435 /* ============ Utility functions */
436 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
437 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
438
439 static int
440 isdigit_str9(const char *str)
441 {
442         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
443         while (--maxlen && isdigit(*str))
444                 str++;
445         return (*str == '\0');
446 }
447
448 static const char *
449 var_end(const char *var)
450 {
451         while (*var)
452                 if (*var++ == '=')
453                         break;
454         return var;
455 }
456
457
458 /* ============ Interrupts / exceptions */
459
460 static void exitshell(void) NORETURN;
461
462 /*
463  * These macros allow the user to suspend the handling of interrupt signals
464  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
465  * much more efficient and portable.  (But hacking the kernel is so much
466  * more fun than worrying about efficiency and portability. :-))
467  */
468 #if DEBUG_INTONOFF
469 # define INT_OFF do { \
470         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
471         suppress_int++; \
472         barrier(); \
473 } while (0)
474 #else
475 # define INT_OFF do { \
476         suppress_int++; \
477         barrier(); \
478 } while (0)
479 #endif
480
481 /*
482  * Called to raise an exception.  Since C doesn't include exceptions, we
483  * just do a longjmp to the exception handler.  The type of exception is
484  * stored in the global variable "exception_type".
485  */
486 static void raise_exception(int) NORETURN;
487 static void
488 raise_exception(int e)
489 {
490 #if DEBUG
491         if (exception_handler == NULL)
492                 abort();
493 #endif
494         INT_OFF;
495         exception_type = e;
496         longjmp(exception_handler->loc, 1);
497 }
498 #if DEBUG
499 #define raise_exception(e) do { \
500         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
501         raise_exception(e); \
502 } while (0)
503 #endif
504
505 /*
506  * Called when a SIGINT is received.  (If the user specifies
507  * that SIGINT is to be trapped or ignored using the trap builtin, then
508  * this routine is not called.)  Suppressint is nonzero when interrupts
509  * are held using the INT_OFF macro.  (The test for iflag is just
510  * defensive programming.)
511  */
512 static void raise_interrupt(void) NORETURN;
513 static void
514 raise_interrupt(void)
515 {
516         pending_int = 0;
517         /* Signal is not automatically unmasked after it is raised,
518          * do it ourself - unmask all signals */
519         sigprocmask_allsigs(SIG_UNBLOCK);
520         /* pending_sig = 0; - now done in signal_handler() */
521
522         if (!(rootshell && iflag)) {
523                 /* Kill ourself with SIGINT */
524                 signal(SIGINT, SIG_DFL);
525                 raise(SIGINT);
526         }
527         /* bash: ^C even on empty command line sets $? */
528         exitstatus = SIGINT + 128;
529         raise_exception(EXINT);
530         /* NOTREACHED */
531 }
532 #if DEBUG
533 #define raise_interrupt() do { \
534         TRACE(("raising interrupt on line %d\n", __LINE__)); \
535         raise_interrupt(); \
536 } while (0)
537 #endif
538
539 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
540 int_on(void)
541 {
542         barrier();
543         if (--suppress_int == 0 && pending_int) {
544                 raise_interrupt();
545         }
546 }
547 #if DEBUG_INTONOFF
548 # define INT_ON do { \
549         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
550         int_on(); \
551 } while (0)
552 #else
553 # define INT_ON int_on()
554 #endif
555 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
556 force_int_on(void)
557 {
558         barrier();
559         suppress_int = 0;
560         if (pending_int)
561                 raise_interrupt();
562 }
563 #define FORCE_INT_ON force_int_on()
564
565 #define SAVE_INT(v) ((v) = suppress_int)
566
567 #define RESTORE_INT(v) do { \
568         barrier(); \
569         suppress_int = (v); \
570         if (suppress_int == 0 && pending_int) \
571                 raise_interrupt(); \
572 } while (0)
573
574
575 /* ============ Stdout/stderr output */
576
577 static void
578 outstr(const char *p, FILE *file)
579 {
580         INT_OFF;
581         fputs(p, file);
582         INT_ON;
583 }
584
585 static void
586 flush_stdout_stderr(void)
587 {
588         INT_OFF;
589         fflush_all();
590         INT_ON;
591 }
592
593 /* Was called outcslow(c,FILE*), but c was always '\n' */
594 static void
595 newline_and_flush(FILE *dest)
596 {
597         INT_OFF;
598         putc('\n', dest);
599         fflush(dest);
600         INT_ON;
601 }
602
603 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
604 static int
605 out1fmt(const char *fmt, ...)
606 {
607         va_list ap;
608         int r;
609
610         INT_OFF;
611         va_start(ap, fmt);
612         r = vprintf(fmt, ap);
613         va_end(ap);
614         INT_ON;
615         return r;
616 }
617
618 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
619 static int
620 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
621 {
622         va_list ap;
623         int ret;
624
625         va_start(ap, fmt);
626         INT_OFF;
627         ret = vsnprintf(outbuf, length, fmt, ap);
628         va_end(ap);
629         INT_ON;
630         return ret;
631 }
632
633 static void
634 out1str(const char *p)
635 {
636         outstr(p, stdout);
637 }
638
639 static void
640 out2str(const char *p)
641 {
642         outstr(p, stderr);
643         flush_stdout_stderr();
644 }
645
646
647 /* ============ Parser structures */
648
649 /* control characters in argument strings */
650 #define CTL_FIRST CTLESC
651 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
652 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
653 #define CTLENDVAR    ((unsigned char)'\203')
654 #define CTLBACKQ     ((unsigned char)'\204')
655 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
656 #define CTLENDARI    ((unsigned char)'\207')
657 #define CTLQUOTEMARK ((unsigned char)'\210')
658 #define CTL_LAST CTLQUOTEMARK
659
660 /* variable substitution byte (follows CTLVAR) */
661 #define VSTYPE  0x0f            /* type of variable substitution */
662 #define VSNUL   0x10            /* colon--treat the empty string as unset */
663
664 /* values of VSTYPE field */
665 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
666 #define VSMINUS         0x2     /* ${var-text} */
667 #define VSPLUS          0x3     /* ${var+text} */
668 #define VSQUESTION      0x4     /* ${var?message} */
669 #define VSASSIGN        0x5     /* ${var=text} */
670 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
671 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
672 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
673 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
674 #define VSLENGTH        0xa     /* ${#var} */
675 #if BASH_SUBSTR
676 #define VSSUBSTR        0xc     /* ${var:position:length} */
677 #endif
678 #if BASH_PATTERN_SUBST
679 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
680 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
681 #endif
682
683 static const char dolatstr[] ALIGN1 = {
684         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
685 };
686 #define DOLATSTRLEN 6
687
688 #define NCMD      0
689 #define NPIPE     1
690 #define NREDIR    2
691 #define NBACKGND  3
692 #define NSUBSHELL 4
693 #define NAND      5
694 #define NOR       6
695 #define NSEMI     7
696 #define NIF       8
697 #define NWHILE    9
698 #define NUNTIL   10
699 #define NFOR     11
700 #define NCASE    12
701 #define NCLIST   13
702 #define NDEFUN   14
703 #define NARG     15
704 #define NTO      16
705 #if BASH_REDIR_OUTPUT
706 #define NTO2     17
707 #endif
708 #define NCLOBBER 18
709 #define NFROM    19
710 #define NFROMTO  20
711 #define NAPPEND  21
712 #define NTOFD    22
713 #define NFROMFD  23
714 #define NHERE    24
715 #define NXHERE   25
716 #define NNOT     26
717 #define N_NUMBER 27
718
719 union node;
720
721 struct ncmd {
722         smallint type; /* Nxxxx */
723         union node *assign;
724         union node *args;
725         union node *redirect;
726 };
727
728 struct npipe {
729         smallint type;
730         smallint pipe_backgnd;
731         struct nodelist *cmdlist;
732 };
733
734 struct nredir {
735         smallint type;
736         union node *n;
737         union node *redirect;
738 };
739
740 struct nbinary {
741         smallint type;
742         union node *ch1;
743         union node *ch2;
744 };
745
746 struct nif {
747         smallint type;
748         union node *test;
749         union node *ifpart;
750         union node *elsepart;
751 };
752
753 struct nfor {
754         smallint type;
755         union node *args;
756         union node *body;
757         char *var;
758 };
759
760 struct ncase {
761         smallint type;
762         union node *expr;
763         union node *cases;
764 };
765
766 struct nclist {
767         smallint type;
768         union node *next;
769         union node *pattern;
770         union node *body;
771 };
772
773 struct narg {
774         smallint type;
775         union node *next;
776         char *text;
777         struct nodelist *backquote;
778 };
779
780 /* nfile and ndup layout must match!
781  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
782  * that it is actually NTO2 (>&file), and change its type.
783  */
784 struct nfile {
785         smallint type;
786         union node *next;
787         int fd;
788         int _unused_dupfd;
789         union node *fname;
790         char *expfname;
791 };
792
793 struct ndup {
794         smallint type;
795         union node *next;
796         int fd;
797         int dupfd;
798         union node *vname;
799         char *_unused_expfname;
800 };
801
802 struct nhere {
803         smallint type;
804         union node *next;
805         int fd;
806         union node *doc;
807 };
808
809 struct nnot {
810         smallint type;
811         union node *com;
812 };
813
814 union node {
815         smallint type;
816         struct ncmd ncmd;
817         struct npipe npipe;
818         struct nredir nredir;
819         struct nbinary nbinary;
820         struct nif nif;
821         struct nfor nfor;
822         struct ncase ncase;
823         struct nclist nclist;
824         struct narg narg;
825         struct nfile nfile;
826         struct ndup ndup;
827         struct nhere nhere;
828         struct nnot nnot;
829 };
830
831 /*
832  * NODE_EOF is returned by parsecmd when it encounters an end of file.
833  * It must be distinct from NULL.
834  */
835 #define NODE_EOF ((union node *) -1L)
836
837 struct nodelist {
838         struct nodelist *next;
839         union node *n;
840 };
841
842 struct funcnode {
843         int count;
844         union node n;
845 };
846
847 /*
848  * Free a parse tree.
849  */
850 static void
851 freefunc(struct funcnode *f)
852 {
853         if (f && --f->count < 0)
854                 free(f);
855 }
856
857
858 /* ============ Debugging output */
859
860 #if DEBUG
861
862 static FILE *tracefile;
863
864 static void
865 trace_printf(const char *fmt, ...)
866 {
867         va_list va;
868
869         if (debug != 1)
870                 return;
871         if (DEBUG_TIME)
872                 fprintf(tracefile, "%u ", (int) time(NULL));
873         if (DEBUG_PID)
874                 fprintf(tracefile, "[%u] ", (int) getpid());
875         if (DEBUG_SIG)
876                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
877         va_start(va, fmt);
878         vfprintf(tracefile, fmt, va);
879         va_end(va);
880 }
881
882 static void
883 trace_vprintf(const char *fmt, va_list va)
884 {
885         if (debug != 1)
886                 return;
887         vfprintf(tracefile, fmt, va);
888         fprintf(tracefile, "\n");
889 }
890
891 static void
892 trace_puts(const char *s)
893 {
894         if (debug != 1)
895                 return;
896         fputs(s, tracefile);
897 }
898
899 static void
900 trace_puts_quoted(char *s)
901 {
902         char *p;
903         char c;
904
905         if (debug != 1)
906                 return;
907         putc('"', tracefile);
908         for (p = s; *p; p++) {
909                 switch ((unsigned char)*p) {
910                 case '\n': c = 'n'; goto backslash;
911                 case '\t': c = 't'; goto backslash;
912                 case '\r': c = 'r'; goto backslash;
913                 case '\"': c = '\"'; goto backslash;
914                 case '\\': c = '\\'; goto backslash;
915                 case CTLESC: c = 'e'; goto backslash;
916                 case CTLVAR: c = 'v'; goto backslash;
917                 case CTLBACKQ: c = 'q'; goto backslash;
918  backslash:
919                         putc('\\', tracefile);
920                         putc(c, tracefile);
921                         break;
922                 default:
923                         if (*p >= ' ' && *p <= '~')
924                                 putc(*p, tracefile);
925                         else {
926                                 putc('\\', tracefile);
927                                 putc((*p >> 6) & 03, tracefile);
928                                 putc((*p >> 3) & 07, tracefile);
929                                 putc(*p & 07, tracefile);
930                         }
931                         break;
932                 }
933         }
934         putc('"', tracefile);
935 }
936
937 static void
938 trace_puts_args(char **ap)
939 {
940         if (debug != 1)
941                 return;
942         if (!*ap)
943                 return;
944         while (1) {
945                 trace_puts_quoted(*ap);
946                 if (!*++ap) {
947                         putc('\n', tracefile);
948                         break;
949                 }
950                 putc(' ', tracefile);
951         }
952 }
953
954 static void
955 opentrace(void)
956 {
957         char s[100];
958 #ifdef O_APPEND
959         int flags;
960 #endif
961
962         if (debug != 1) {
963                 if (tracefile)
964                         fflush(tracefile);
965                 /* leave open because libedit might be using it */
966                 return;
967         }
968         strcpy(s, "./trace");
969         if (tracefile) {
970                 if (!freopen(s, "a", tracefile)) {
971                         fprintf(stderr, "Can't re-open %s\n", s);
972                         debug = 0;
973                         return;
974                 }
975         } else {
976                 tracefile = fopen(s, "a");
977                 if (tracefile == NULL) {
978                         fprintf(stderr, "Can't open %s\n", s);
979                         debug = 0;
980                         return;
981                 }
982         }
983 #ifdef O_APPEND
984         flags = fcntl(fileno(tracefile), F_GETFL);
985         if (flags >= 0)
986                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
987 #endif
988         setlinebuf(tracefile);
989         fputs("\nTracing started.\n", tracefile);
990 }
991
992 static void
993 indent(int amount, char *pfx, FILE *fp)
994 {
995         int i;
996
997         for (i = 0; i < amount; i++) {
998                 if (pfx && i == amount - 1)
999                         fputs(pfx, fp);
1000                 putc('\t', fp);
1001         }
1002 }
1003
1004 /* little circular references here... */
1005 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1006
1007 static void
1008 sharg(union node *arg, FILE *fp)
1009 {
1010         char *p;
1011         struct nodelist *bqlist;
1012         unsigned char subtype;
1013
1014         if (arg->type != NARG) {
1015                 out1fmt("<node type %d>\n", arg->type);
1016                 abort();
1017         }
1018         bqlist = arg->narg.backquote;
1019         for (p = arg->narg.text; *p; p++) {
1020                 switch ((unsigned char)*p) {
1021                 case CTLESC:
1022                         p++;
1023                         putc(*p, fp);
1024                         break;
1025                 case CTLVAR:
1026                         putc('$', fp);
1027                         putc('{', fp);
1028                         subtype = *++p;
1029                         if (subtype == VSLENGTH)
1030                                 putc('#', fp);
1031
1032                         while (*p != '=') {
1033                                 putc(*p, fp);
1034                                 p++;
1035                         }
1036
1037                         if (subtype & VSNUL)
1038                                 putc(':', fp);
1039
1040                         switch (subtype & VSTYPE) {
1041                         case VSNORMAL:
1042                                 putc('}', fp);
1043                                 break;
1044                         case VSMINUS:
1045                                 putc('-', fp);
1046                                 break;
1047                         case VSPLUS:
1048                                 putc('+', fp);
1049                                 break;
1050                         case VSQUESTION:
1051                                 putc('?', fp);
1052                                 break;
1053                         case VSASSIGN:
1054                                 putc('=', fp);
1055                                 break;
1056                         case VSTRIMLEFT:
1057                                 putc('#', fp);
1058                                 break;
1059                         case VSTRIMLEFTMAX:
1060                                 putc('#', fp);
1061                                 putc('#', fp);
1062                                 break;
1063                         case VSTRIMRIGHT:
1064                                 putc('%', fp);
1065                                 break;
1066                         case VSTRIMRIGHTMAX:
1067                                 putc('%', fp);
1068                                 putc('%', fp);
1069                                 break;
1070                         case VSLENGTH:
1071                                 break;
1072                         default:
1073                                 out1fmt("<subtype %d>", subtype);
1074                         }
1075                         break;
1076                 case CTLENDVAR:
1077                         putc('}', fp);
1078                         break;
1079                 case CTLBACKQ:
1080                         putc('$', fp);
1081                         putc('(', fp);
1082                         shtree(bqlist->n, -1, NULL, fp);
1083                         putc(')', fp);
1084                         break;
1085                 default:
1086                         putc(*p, fp);
1087                         break;
1088                 }
1089         }
1090 }
1091
1092 static void
1093 shcmd(union node *cmd, FILE *fp)
1094 {
1095         union node *np;
1096         int first;
1097         const char *s;
1098         int dftfd;
1099
1100         first = 1;
1101         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1102                 if (!first)
1103                         putc(' ', fp);
1104                 sharg(np, fp);
1105                 first = 0;
1106         }
1107         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1108                 if (!first)
1109                         putc(' ', fp);
1110                 dftfd = 0;
1111                 switch (np->nfile.type) {
1112                 case NTO:      s = ">>"+1; dftfd = 1; break;
1113                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1114                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1115 #if BASH_REDIR_OUTPUT
1116                 case NTO2:
1117 #endif
1118                 case NTOFD:    s = ">&"; dftfd = 1; break;
1119                 case NFROM:    s = "<"; break;
1120                 case NFROMFD:  s = "<&"; break;
1121                 case NFROMTO:  s = "<>"; break;
1122                 default:       s = "*error*"; break;
1123                 }
1124                 if (np->nfile.fd != dftfd)
1125                         fprintf(fp, "%d", np->nfile.fd);
1126                 fputs(s, fp);
1127                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1128                         fprintf(fp, "%d", np->ndup.dupfd);
1129                 } else {
1130                         sharg(np->nfile.fname, fp);
1131                 }
1132                 first = 0;
1133         }
1134 }
1135
1136 static void
1137 shtree(union node *n, int ind, char *pfx, FILE *fp)
1138 {
1139         struct nodelist *lp;
1140         const char *s;
1141
1142         if (n == NULL)
1143                 return;
1144
1145         indent(ind, pfx, fp);
1146
1147         if (n == NODE_EOF) {
1148                 fputs("<EOF>", fp);
1149                 return;
1150         }
1151
1152         switch (n->type) {
1153         case NSEMI:
1154                 s = "; ";
1155                 goto binop;
1156         case NAND:
1157                 s = " && ";
1158                 goto binop;
1159         case NOR:
1160                 s = " || ";
1161  binop:
1162                 shtree(n->nbinary.ch1, ind, NULL, fp);
1163                 /* if (ind < 0) */
1164                         fputs(s, fp);
1165                 shtree(n->nbinary.ch2, ind, NULL, fp);
1166                 break;
1167         case NCMD:
1168                 shcmd(n, fp);
1169                 if (ind >= 0)
1170                         putc('\n', fp);
1171                 break;
1172         case NPIPE:
1173                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1174                         shtree(lp->n, 0, NULL, fp);
1175                         if (lp->next)
1176                                 fputs(" | ", fp);
1177                 }
1178                 if (n->npipe.pipe_backgnd)
1179                         fputs(" &", fp);
1180                 if (ind >= 0)
1181                         putc('\n', fp);
1182                 break;
1183         default:
1184                 fprintf(fp, "<node type %d>", n->type);
1185                 if (ind >= 0)
1186                         putc('\n', fp);
1187                 break;
1188         }
1189 }
1190
1191 static void
1192 showtree(union node *n)
1193 {
1194         trace_puts("showtree called\n");
1195         shtree(n, 1, NULL, stderr);
1196 }
1197
1198 #endif /* DEBUG */
1199
1200
1201 /* ============ Parser data */
1202
1203 /*
1204  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1205  */
1206 struct strlist {
1207         struct strlist *next;
1208         char *text;
1209 };
1210
1211 struct alias;
1212
1213 struct strpush {
1214         struct strpush *prev;   /* preceding string on stack */
1215         char *prev_string;
1216         int prev_left_in_line;
1217 #if ENABLE_ASH_ALIAS
1218         struct alias *ap;       /* if push was associated with an alias */
1219 #endif
1220         char *string;           /* remember the string since it may change */
1221
1222         /* Remember last two characters for pungetc. */
1223         int lastc[2];
1224
1225         /* Number of outstanding calls to pungetc. */
1226         int unget;
1227 };
1228
1229 struct parsefile {
1230         struct parsefile *prev; /* preceding file on stack */
1231         int linno;              /* current line */
1232         int pf_fd;              /* file descriptor (or -1 if string) */
1233         int left_in_line;       /* number of chars left in this line */
1234         int left_in_buffer;     /* number of chars left in this buffer past the line */
1235         char *next_to_pgetc;    /* next char in buffer */
1236         char *buf;              /* input buffer */
1237         struct strpush *strpush; /* for pushing strings at this level */
1238         struct strpush basestrpush; /* so pushing one is fast */
1239
1240         /* Remember last two characters for pungetc. */
1241         int lastc[2];
1242
1243         /* Number of outstanding calls to pungetc. */
1244         int unget;
1245 };
1246
1247 static struct parsefile basepf;        /* top level input file */
1248 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1249 static int startlinno;                 /* line # where last token started */
1250 static char *commandname;              /* currently executing command */
1251 static struct strlist *cmdenviron;     /* environment for builtin command */
1252
1253
1254 /* ============ Message printing */
1255
1256 static void
1257 ash_vmsg(const char *msg, va_list ap)
1258 {
1259         fprintf(stderr, "%s: ", arg0);
1260         if (commandname) {
1261                 if (strcmp(arg0, commandname))
1262                         fprintf(stderr, "%s: ", commandname);
1263                 if (!iflag || g_parsefile->pf_fd > 0)
1264                         fprintf(stderr, "line %d: ", startlinno);
1265         }
1266         vfprintf(stderr, msg, ap);
1267         newline_and_flush(stderr);
1268 }
1269
1270 /*
1271  * Exverror is called to raise the error exception.  If the second argument
1272  * is not NULL then error prints an error message using printf style
1273  * formatting.  It then raises the error exception.
1274  */
1275 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1276 static void
1277 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1278 {
1279 #if DEBUG
1280         if (msg) {
1281                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1282                 TRACEV((msg, ap));
1283         } else
1284                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1285         if (msg)
1286 #endif
1287                 ash_vmsg(msg, ap);
1288
1289         flush_stdout_stderr();
1290         raise_exception(cond);
1291         /* NOTREACHED */
1292 }
1293
1294 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1295 static void
1296 ash_msg_and_raise_error(const char *msg, ...)
1297 {
1298         va_list ap;
1299
1300         exitstatus = 2;
1301
1302         va_start(ap, msg);
1303         ash_vmsg_and_raise(EXERROR, msg, ap);
1304         /* NOTREACHED */
1305         va_end(ap);
1306 }
1307
1308 static void raise_error_syntax(const char *) NORETURN;
1309 static void
1310 raise_error_syntax(const char *msg)
1311 {
1312         ash_msg_and_raise_error("syntax error: %s", msg);
1313         /* NOTREACHED */
1314 }
1315
1316 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1317 static void
1318 ash_msg_and_raise(int cond, const char *msg, ...)
1319 {
1320         va_list ap;
1321
1322         va_start(ap, msg);
1323         ash_vmsg_and_raise(cond, msg, ap);
1324         /* NOTREACHED */
1325         va_end(ap);
1326 }
1327
1328 /*
1329  * error/warning routines for external builtins
1330  */
1331 static void
1332 ash_msg(const char *fmt, ...)
1333 {
1334         va_list ap;
1335
1336         va_start(ap, fmt);
1337         ash_vmsg(fmt, ap);
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * Return a string describing an error.  The returned string may be a
1343  * pointer to a static buffer that will be overwritten on the next call.
1344  * Action describes the operation that got the error.
1345  */
1346 static const char *
1347 errmsg(int e, const char *em)
1348 {
1349         if (e == ENOENT || e == ENOTDIR) {
1350                 return em;
1351         }
1352         return strerror(e);
1353 }
1354
1355
1356 /* ============ Memory allocation */
1357
1358 #if 0
1359 /* I consider these wrappers nearly useless:
1360  * ok, they return you to nearest exception handler, but
1361  * how much memory do you leak in the process, making
1362  * memory starvation worse?
1363  */
1364 static void *
1365 ckrealloc(void * p, size_t nbytes)
1366 {
1367         p = realloc(p, nbytes);
1368         if (!p)
1369                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1370         return p;
1371 }
1372
1373 static void *
1374 ckmalloc(size_t nbytes)
1375 {
1376         return ckrealloc(NULL, nbytes);
1377 }
1378
1379 static void *
1380 ckzalloc(size_t nbytes)
1381 {
1382         return memset(ckmalloc(nbytes), 0, nbytes);
1383 }
1384
1385 static char *
1386 ckstrdup(const char *s)
1387 {
1388         char *p = strdup(s);
1389         if (!p)
1390                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1391         return p;
1392 }
1393 #else
1394 /* Using bbox equivalents. They exit if out of memory */
1395 # define ckrealloc xrealloc
1396 # define ckmalloc  xmalloc
1397 # define ckzalloc  xzalloc
1398 # define ckstrdup  xstrdup
1399 #endif
1400
1401 /*
1402  * It appears that grabstackstr() will barf with such alignments
1403  * because stalloc() will return a string allocated in a new stackblock.
1404  */
1405 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1406 enum {
1407         /* Most machines require the value returned from malloc to be aligned
1408          * in some way.  The following macro will get this right
1409          * on many machines.  */
1410         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1411         /* Minimum size of a block */
1412         MINSIZE = SHELL_ALIGN(504),
1413 };
1414
1415 struct stack_block {
1416         struct stack_block *prev;
1417         char space[MINSIZE];
1418 };
1419
1420 struct stackmark {
1421         struct stack_block *stackp;
1422         char *stacknxt;
1423         size_t stacknleft;
1424 };
1425
1426
1427 struct globals_memstack {
1428         struct stack_block *g_stackp; // = &stackbase;
1429         char *g_stacknxt; // = stackbase.space;
1430         char *sstrend; // = stackbase.space + MINSIZE;
1431         size_t g_stacknleft; // = MINSIZE;
1432         struct stack_block stackbase;
1433 };
1434 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1435 #define G_memstack (*ash_ptr_to_globals_memstack)
1436 #define g_stackp     (G_memstack.g_stackp    )
1437 #define g_stacknxt   (G_memstack.g_stacknxt  )
1438 #define sstrend      (G_memstack.sstrend     )
1439 #define g_stacknleft (G_memstack.g_stacknleft)
1440 #define stackbase    (G_memstack.stackbase   )
1441 #define INIT_G_memstack() do { \
1442         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1443         barrier(); \
1444         g_stackp = &stackbase; \
1445         g_stacknxt = stackbase.space; \
1446         g_stacknleft = MINSIZE; \
1447         sstrend = stackbase.space + MINSIZE; \
1448 } while (0)
1449
1450
1451 #define stackblock()     ((void *)g_stacknxt)
1452 #define stackblocksize() g_stacknleft
1453
1454 /*
1455  * Parse trees for commands are allocated in lifo order, so we use a stack
1456  * to make this more efficient, and also to avoid all sorts of exception
1457  * handling code to handle interrupts in the middle of a parse.
1458  *
1459  * The size 504 was chosen because the Ultrix malloc handles that size
1460  * well.
1461  */
1462 static void *
1463 stalloc(size_t nbytes)
1464 {
1465         char *p;
1466         size_t aligned;
1467
1468         aligned = SHELL_ALIGN(nbytes);
1469         if (aligned > g_stacknleft) {
1470                 size_t len;
1471                 size_t blocksize;
1472                 struct stack_block *sp;
1473
1474                 blocksize = aligned;
1475                 if (blocksize < MINSIZE)
1476                         blocksize = MINSIZE;
1477                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1478                 if (len < blocksize)
1479                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1480                 INT_OFF;
1481                 sp = ckmalloc(len);
1482                 sp->prev = g_stackp;
1483                 g_stacknxt = sp->space;
1484                 g_stacknleft = blocksize;
1485                 sstrend = g_stacknxt + blocksize;
1486                 g_stackp = sp;
1487                 INT_ON;
1488         }
1489         p = g_stacknxt;
1490         g_stacknxt += aligned;
1491         g_stacknleft -= aligned;
1492         return p;
1493 }
1494
1495 static void *
1496 stzalloc(size_t nbytes)
1497 {
1498         return memset(stalloc(nbytes), 0, nbytes);
1499 }
1500
1501 static void
1502 stunalloc(void *p)
1503 {
1504 #if DEBUG
1505         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1506                 write(STDERR_FILENO, "stunalloc\n", 10);
1507                 abort();
1508         }
1509 #endif
1510         g_stacknleft += g_stacknxt - (char *)p;
1511         g_stacknxt = p;
1512 }
1513
1514 /*
1515  * Like strdup but works with the ash stack.
1516  */
1517 static char *
1518 sstrdup(const char *p)
1519 {
1520         size_t len = strlen(p) + 1;
1521         return memcpy(stalloc(len), p, len);
1522 }
1523
1524 static inline void
1525 grabstackblock(size_t len)
1526 {
1527         stalloc(len);
1528 }
1529
1530 static void
1531 pushstackmark(struct stackmark *mark, size_t len)
1532 {
1533         mark->stackp = g_stackp;
1534         mark->stacknxt = g_stacknxt;
1535         mark->stacknleft = g_stacknleft;
1536         grabstackblock(len);
1537 }
1538
1539 static void
1540 setstackmark(struct stackmark *mark)
1541 {
1542         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1543 }
1544
1545 static void
1546 popstackmark(struct stackmark *mark)
1547 {
1548         struct stack_block *sp;
1549
1550         if (!mark->stackp)
1551                 return;
1552
1553         INT_OFF;
1554         while (g_stackp != mark->stackp) {
1555                 sp = g_stackp;
1556                 g_stackp = sp->prev;
1557                 free(sp);
1558         }
1559         g_stacknxt = mark->stacknxt;
1560         g_stacknleft = mark->stacknleft;
1561         sstrend = mark->stacknxt + mark->stacknleft;
1562         INT_ON;
1563 }
1564
1565 /*
1566  * When the parser reads in a string, it wants to stick the string on the
1567  * stack and only adjust the stack pointer when it knows how big the
1568  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1569  * of space on top of the stack and stackblocklen returns the length of
1570  * this block.  Growstackblock will grow this space by at least one byte,
1571  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1572  * part of the block that has been used.
1573  */
1574 static void
1575 growstackblock(void)
1576 {
1577         size_t newlen;
1578
1579         newlen = g_stacknleft * 2;
1580         if (newlen < g_stacknleft)
1581                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1582         if (newlen < 128)
1583                 newlen += 128;
1584
1585         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1586                 struct stack_block *sp;
1587                 struct stack_block *prevstackp;
1588                 size_t grosslen;
1589
1590                 INT_OFF;
1591                 sp = g_stackp;
1592                 prevstackp = sp->prev;
1593                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1594                 sp = ckrealloc(sp, grosslen);
1595                 sp->prev = prevstackp;
1596                 g_stackp = sp;
1597                 g_stacknxt = sp->space;
1598                 g_stacknleft = newlen;
1599                 sstrend = sp->space + newlen;
1600                 INT_ON;
1601         } else {
1602                 char *oldspace = g_stacknxt;
1603                 size_t oldlen = g_stacknleft;
1604                 char *p = stalloc(newlen);
1605
1606                 /* free the space we just allocated */
1607                 g_stacknxt = memcpy(p, oldspace, oldlen);
1608                 g_stacknleft += newlen;
1609         }
1610 }
1611
1612 /*
1613  * The following routines are somewhat easier to use than the above.
1614  * The user declares a variable of type STACKSTR, which may be declared
1615  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1616  * the user uses the macro STPUTC to add characters to the string.  In
1617  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1618  * grown as necessary.  When the user is done, she can just leave the
1619  * string there and refer to it using stackblock().  Or she can allocate
1620  * the space for it using grabstackstr().  If it is necessary to allow
1621  * someone else to use the stack temporarily and then continue to grow
1622  * the string, the user should use grabstack to allocate the space, and
1623  * then call ungrabstr(p) to return to the previous mode of operation.
1624  *
1625  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1626  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1627  * is space for at least one character.
1628  */
1629 static void *
1630 growstackstr(void)
1631 {
1632         size_t len = stackblocksize();
1633         growstackblock();
1634         return (char *)stackblock() + len;
1635 }
1636
1637 /*
1638  * Called from CHECKSTRSPACE.
1639  */
1640 static char *
1641 makestrspace(size_t newlen, char *p)
1642 {
1643         size_t len = p - g_stacknxt;
1644         size_t size;
1645
1646         for (;;) {
1647                 size_t nleft;
1648
1649                 size = stackblocksize();
1650                 nleft = size - len;
1651                 if (nleft >= newlen)
1652                         break;
1653                 growstackblock();
1654         }
1655         return (char *)stackblock() + len;
1656 }
1657
1658 static char *
1659 stack_nputstr(const char *s, size_t n, char *p)
1660 {
1661         p = makestrspace(n, p);
1662         p = (char *)memcpy(p, s, n) + n;
1663         return p;
1664 }
1665
1666 static char *
1667 stack_putstr(const char *s, char *p)
1668 {
1669         return stack_nputstr(s, strlen(s), p);
1670 }
1671
1672 static char *
1673 _STPUTC(int c, char *p)
1674 {
1675         if (p == sstrend)
1676                 p = growstackstr();
1677         *p++ = c;
1678         return p;
1679 }
1680
1681 #define STARTSTACKSTR(p)        ((p) = stackblock())
1682 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1683 #define CHECKSTRSPACE(n, p) do { \
1684         char *q = (p); \
1685         size_t l = (n); \
1686         size_t m = sstrend - q; \
1687         if (l > m) \
1688                 (p) = makestrspace(l, q); \
1689 } while (0)
1690 #define USTPUTC(c, p)           (*(p)++ = (c))
1691 #define STACKSTRNUL(p) do { \
1692         if ((p) == sstrend) \
1693                 (p) = growstackstr(); \
1694         *(p) = '\0'; \
1695 } while (0)
1696 #define STUNPUTC(p)             (--(p))
1697 #define STTOPC(p)               ((p)[-1])
1698 #define STADJUST(amount, p)     ((p) += (amount))
1699
1700 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1701 #define ungrabstackstr(s, p)    stunalloc(s)
1702 #define stackstrend()           ((void *)sstrend)
1703
1704
1705 /* ============ String helpers */
1706
1707 /*
1708  * prefix -- see if pfx is a prefix of string.
1709  */
1710 static char *
1711 prefix(const char *string, const char *pfx)
1712 {
1713         while (*pfx) {
1714                 if (*pfx++ != *string++)
1715                         return NULL;
1716         }
1717         return (char *) string;
1718 }
1719
1720 /*
1721  * Check for a valid number.  This should be elsewhere.
1722  */
1723 static int
1724 is_number(const char *p)
1725 {
1726         do {
1727                 if (!isdigit(*p))
1728                         return 0;
1729         } while (*++p != '\0');
1730         return 1;
1731 }
1732
1733 /*
1734  * Convert a string of digits to an integer, printing an error message on
1735  * failure.
1736  */
1737 static int
1738 number(const char *s)
1739 {
1740         if (!is_number(s))
1741                 ash_msg_and_raise_error(msg_illnum, s);
1742         return atoi(s);
1743 }
1744
1745 /*
1746  * Produce a possibly single quoted string suitable as input to the shell.
1747  * The return string is allocated on the stack.
1748  */
1749 static char *
1750 single_quote(const char *s)
1751 {
1752         char *p;
1753
1754         STARTSTACKSTR(p);
1755
1756         do {
1757                 char *q;
1758                 size_t len;
1759
1760                 len = strchrnul(s, '\'') - s;
1761
1762                 q = p = makestrspace(len + 3, p);
1763
1764                 *q++ = '\'';
1765                 q = (char *)memcpy(q, s, len) + len;
1766                 *q++ = '\'';
1767                 s += len;
1768
1769                 STADJUST(q - p, p);
1770
1771                 if (*s != '\'')
1772                         break;
1773                 len = 0;
1774                 do len++; while (*++s == '\'');
1775
1776                 q = p = makestrspace(len + 3, p);
1777
1778                 *q++ = '"';
1779                 q = (char *)memcpy(q, s - len, len) + len;
1780                 *q++ = '"';
1781
1782                 STADJUST(q - p, p);
1783         } while (*s);
1784
1785         USTPUTC('\0', p);
1786
1787         return stackblock();
1788 }
1789
1790
1791 /* ============ nextopt */
1792
1793 static char **argptr;                  /* argument list for builtin commands */
1794 static char *optionarg;                /* set by nextopt (like getopt) */
1795 static char *optptr;                   /* used by nextopt */
1796
1797 /*
1798  * XXX - should get rid of. Have all builtins use getopt(3).
1799  * The library getopt must have the BSD extension static variable
1800  * "optreset", otherwise it can't be used within the shell safely.
1801  *
1802  * Standard option processing (a la getopt) for builtin routines.
1803  * The only argument that is passed to nextopt is the option string;
1804  * the other arguments are unnecessary. It returns the character,
1805  * or '\0' on end of input.
1806  */
1807 static int
1808 nextopt(const char *optstring)
1809 {
1810         char *p;
1811         const char *q;
1812         char c;
1813
1814         p = optptr;
1815         if (p == NULL || *p == '\0') {
1816                 /* We ate entire "-param", take next one */
1817                 p = *argptr;
1818                 if (p == NULL)
1819                         return '\0';
1820                 if (*p != '-')
1821                         return '\0';
1822                 if (*++p == '\0') /* just "-" ? */
1823                         return '\0';
1824                 argptr++;
1825                 if (LONE_DASH(p)) /* "--" ? */
1826                         return '\0';
1827                 /* p => next "-param" */
1828         }
1829         /* p => some option char in the middle of a "-param" */
1830         c = *p++;
1831         for (q = optstring; *q != c;) {
1832                 if (*q == '\0')
1833                         ash_msg_and_raise_error("illegal option -%c", c);
1834                 if (*++q == ':')
1835                         q++;
1836         }
1837         if (*++q == ':') {
1838                 if (*p == '\0') {
1839                         p = *argptr++;
1840                         if (p == NULL)
1841                                 ash_msg_and_raise_error("no arg for -%c option", c);
1842                 }
1843                 optionarg = p;
1844                 p = NULL;
1845         }
1846         optptr = p;
1847         return c;
1848 }
1849
1850
1851 /* ============ Shell variables */
1852
1853 /*
1854  * The parsefile structure pointed to by the global variable parsefile
1855  * contains information about the current file being read.
1856  */
1857 struct shparam {
1858         int nparam;             /* # of positional parameters (without $0) */
1859 #if ENABLE_ASH_GETOPTS
1860         int optind;             /* next parameter to be processed by getopts */
1861         int optoff;             /* used by getopts */
1862 #endif
1863         unsigned char malloced; /* if parameter list dynamically allocated */
1864         char **p;               /* parameter list */
1865 };
1866
1867 /*
1868  * Free the list of positional parameters.
1869  */
1870 static void
1871 freeparam(volatile struct shparam *param)
1872 {
1873         if (param->malloced) {
1874                 char **ap, **ap1;
1875                 ap = ap1 = param->p;
1876                 while (*ap)
1877                         free(*ap++);
1878                 free(ap1);
1879         }
1880 }
1881
1882 #if ENABLE_ASH_GETOPTS
1883 static void FAST_FUNC getoptsreset(const char *value);
1884 #endif
1885
1886 struct var {
1887         struct var *next;               /* next entry in hash list */
1888         int flags;                      /* flags are defined above */
1889         const char *var_text;           /* name=value */
1890         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1891                                         /* the variable gets set/unset */
1892 };
1893
1894 struct localvar {
1895         struct localvar *next;          /* next local variable in list */
1896         struct var *vp;                 /* the variable that was made local */
1897         int flags;                      /* saved flags */
1898         const char *text;               /* saved text */
1899 };
1900
1901 /* flags */
1902 #define VEXPORT         0x01    /* variable is exported */
1903 #define VREADONLY       0x02    /* variable cannot be modified */
1904 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1905 #define VTEXTFIXED      0x08    /* text is statically allocated */
1906 #define VSTACK          0x10    /* text is allocated on the stack */
1907 #define VUNSET          0x20    /* the variable is not set */
1908 #define VNOFUNC         0x40    /* don't call the callback function */
1909 #define VNOSET          0x80    /* do not set variable - just readonly test */
1910 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1911 #if ENABLE_ASH_RANDOM_SUPPORT
1912 # define VDYNAMIC       0x200   /* dynamic variable */
1913 #else
1914 # define VDYNAMIC       0
1915 #endif
1916
1917
1918 /* Need to be before varinit_data[] */
1919 #if ENABLE_LOCALE_SUPPORT
1920 static void FAST_FUNC
1921 change_lc_all(const char *value)
1922 {
1923         if (value && *value != '\0')
1924                 setlocale(LC_ALL, value);
1925 }
1926 static void FAST_FUNC
1927 change_lc_ctype(const char *value)
1928 {
1929         if (value && *value != '\0')
1930                 setlocale(LC_CTYPE, value);
1931 }
1932 #endif
1933 #if ENABLE_ASH_MAIL
1934 static void chkmail(void);
1935 static void changemail(const char *var_value) FAST_FUNC;
1936 #else
1937 # define chkmail()  ((void)0)
1938 #endif
1939 static void changepath(const char *) FAST_FUNC;
1940 #if ENABLE_ASH_RANDOM_SUPPORT
1941 static void change_random(const char *) FAST_FUNC;
1942 #endif
1943
1944 static const struct {
1945         int flags;
1946         const char *var_text;
1947         void (*var_func)(const char *) FAST_FUNC;
1948 } varinit_data[] = {
1949         /*
1950          * Note: VEXPORT would not work correctly here for NOFORK applets:
1951          * some environment strings may be constant.
1952          */
1953         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1954 #if ENABLE_ASH_MAIL
1955         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1956         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1957 #endif
1958         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1959         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1960         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1961         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1962 #if ENABLE_ASH_GETOPTS
1963         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
1964 #endif
1965 #if ENABLE_ASH_RANDOM_SUPPORT
1966         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1967 #endif
1968 #if ENABLE_LOCALE_SUPPORT
1969         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
1970         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
1971 #endif
1972 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1973         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
1974 #endif
1975 };
1976
1977 struct redirtab;
1978
1979 struct globals_var {
1980         struct shparam shellparam;      /* $@ current positional parameters */
1981         struct redirtab *redirlist;
1982         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1983         struct var *vartab[VTABSIZE];
1984         struct var varinit[ARRAY_SIZE(varinit_data)];
1985 };
1986 extern struct globals_var *const ash_ptr_to_globals_var;
1987 #define G_var (*ash_ptr_to_globals_var)
1988 #define shellparam    (G_var.shellparam   )
1989 //#define redirlist     (G_var.redirlist    )
1990 #define preverrout_fd (G_var.preverrout_fd)
1991 #define vartab        (G_var.vartab       )
1992 #define varinit       (G_var.varinit      )
1993 #define INIT_G_var() do { \
1994         unsigned i; \
1995         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1996         barrier(); \
1997         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1998                 varinit[i].flags    = varinit_data[i].flags; \
1999                 varinit[i].var_text = varinit_data[i].var_text; \
2000                 varinit[i].var_func = varinit_data[i].var_func; \
2001         } \
2002 } while (0)
2003
2004 #define vifs      varinit[0]
2005 #if ENABLE_ASH_MAIL
2006 # define vmail    (&vifs)[1]
2007 # define vmpath   (&vmail)[1]
2008 # define vpath    (&vmpath)[1]
2009 #else
2010 # define vpath    (&vifs)[1]
2011 #endif
2012 #define vps1      (&vpath)[1]
2013 #define vps2      (&vps1)[1]
2014 #define vps4      (&vps2)[1]
2015 #if ENABLE_ASH_GETOPTS
2016 # define voptind  (&vps4)[1]
2017 # if ENABLE_ASH_RANDOM_SUPPORT
2018 #  define vrandom (&voptind)[1]
2019 # endif
2020 #else
2021 # if ENABLE_ASH_RANDOM_SUPPORT
2022 #  define vrandom (&vps4)[1]
2023 # endif
2024 #endif
2025
2026 /*
2027  * The following macros access the values of the above variables.
2028  * They have to skip over the name.  They return the null string
2029  * for unset variables.
2030  */
2031 #define ifsval()        (vifs.var_text + 4)
2032 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2033 #if ENABLE_ASH_MAIL
2034 # define mailval()      (vmail.var_text + 5)
2035 # define mpathval()     (vmpath.var_text + 9)
2036 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2037 #endif
2038 #define pathval()       (vpath.var_text + 5)
2039 #define ps1val()        (vps1.var_text + 4)
2040 #define ps2val()        (vps2.var_text + 4)
2041 #define ps4val()        (vps4.var_text + 4)
2042 #if ENABLE_ASH_GETOPTS
2043 # define optindval()    (voptind.var_text + 7)
2044 #endif
2045
2046 #if ENABLE_ASH_GETOPTS
2047 static void FAST_FUNC
2048 getoptsreset(const char *value)
2049 {
2050         shellparam.optind = number(value) ?: 1;
2051         shellparam.optoff = -1;
2052 }
2053 #endif
2054
2055 /*
2056  * Compares two strings up to the first = or '\0'.  The first
2057  * string must be terminated by '='; the second may be terminated by
2058  * either '=' or '\0'.
2059  */
2060 static int
2061 varcmp(const char *p, const char *q)
2062 {
2063         int c, d;
2064
2065         while ((c = *p) == (d = *q)) {
2066                 if (c == '\0' || c == '=')
2067                         goto out;
2068                 p++;
2069                 q++;
2070         }
2071         if (c == '=')
2072                 c = '\0';
2073         if (d == '=')
2074                 d = '\0';
2075  out:
2076         return c - d;
2077 }
2078
2079 /*
2080  * Find the appropriate entry in the hash table from the name.
2081  */
2082 static struct var **
2083 hashvar(const char *p)
2084 {
2085         unsigned hashval;
2086
2087         hashval = ((unsigned char) *p) << 4;
2088         while (*p && *p != '=')
2089                 hashval += (unsigned char) *p++;
2090         return &vartab[hashval % VTABSIZE];
2091 }
2092
2093 static int
2094 vpcmp(const void *a, const void *b)
2095 {
2096         return varcmp(*(const char **)a, *(const char **)b);
2097 }
2098
2099 /*
2100  * This routine initializes the builtin variables.
2101  */
2102 static void
2103 initvar(void)
2104 {
2105         struct var *vp;
2106         struct var *end;
2107         struct var **vpp;
2108
2109         /*
2110          * PS1 depends on uid
2111          */
2112 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2113         vps1.var_text = "PS1=\\w \\$ ";
2114 #else
2115         if (!geteuid())
2116                 vps1.var_text = "PS1=# ";
2117 #endif
2118         vp = varinit;
2119         end = vp + ARRAY_SIZE(varinit);
2120         do {
2121                 vpp = hashvar(vp->var_text);
2122                 vp->next = *vpp;
2123                 *vpp = vp;
2124         } while (++vp < end);
2125 }
2126
2127 static struct var **
2128 findvar(struct var **vpp, const char *name)
2129 {
2130         for (; *vpp; vpp = &(*vpp)->next) {
2131                 if (varcmp((*vpp)->var_text, name) == 0) {
2132                         break;
2133                 }
2134         }
2135         return vpp;
2136 }
2137
2138 /*
2139  * Find the value of a variable.  Returns NULL if not set.
2140  */
2141 static const char* FAST_FUNC
2142 lookupvar(const char *name)
2143 {
2144         struct var *v;
2145
2146         v = *findvar(hashvar(name), name);
2147         if (v) {
2148 #if ENABLE_ASH_RANDOM_SUPPORT
2149         /*
2150          * Dynamic variables are implemented roughly the same way they are
2151          * in bash. Namely, they're "special" so long as they aren't unset.
2152          * As soon as they're unset, they're no longer dynamic, and dynamic
2153          * lookup will no longer happen at that point. -- PFM.
2154          */
2155                 if (v->flags & VDYNAMIC)
2156                         v->var_func(NULL);
2157 #endif
2158                 if (!(v->flags & VUNSET))
2159                         return var_end(v->var_text);
2160         }
2161         return NULL;
2162 }
2163
2164 #if ENABLE_UNICODE_SUPPORT
2165 static void
2166 reinit_unicode_for_ash(void)
2167 {
2168         /* Unicode support should be activated even if LANG is set
2169          * _during_ shell execution, not only if it was set when
2170          * shell was started. Therefore, re-check LANG every time:
2171          */
2172         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2173          || ENABLE_UNICODE_USING_LOCALE
2174         ) {
2175                 const char *s = lookupvar("LC_ALL");
2176                 if (!s) s = lookupvar("LC_CTYPE");
2177                 if (!s) s = lookupvar("LANG");
2178                 reinit_unicode(s);
2179         }
2180 }
2181 #else
2182 # define reinit_unicode_for_ash() ((void)0)
2183 #endif
2184
2185 /*
2186  * Search the environment of a builtin command.
2187  */
2188 static const char *
2189 bltinlookup(const char *name)
2190 {
2191         struct strlist *sp;
2192
2193         for (sp = cmdenviron; sp; sp = sp->next) {
2194                 if (varcmp(sp->text, name) == 0)
2195                         return var_end(sp->text);
2196         }
2197         return lookupvar(name);
2198 }
2199
2200 /*
2201  * Same as setvar except that the variable and value are passed in
2202  * the first argument as name=value.  Since the first argument will
2203  * be actually stored in the table, it should not be a string that
2204  * will go away.
2205  * Called with interrupts off.
2206  */
2207 static void
2208 setvareq(char *s, int flags)
2209 {
2210         struct var *vp, **vpp;
2211
2212         vpp = hashvar(s);
2213         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2214         vp = *findvar(vpp, s);
2215         if (vp) {
2216                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2217                         const char *n;
2218
2219                         if (flags & VNOSAVE)
2220                                 free(s);
2221                         n = vp->var_text;
2222                         exitstatus = 1;
2223                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2224                 }
2225
2226                 if (flags & VNOSET)
2227                         return;
2228
2229                 if (vp->var_func && !(flags & VNOFUNC))
2230                         vp->var_func(var_end(s));
2231
2232                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2233                         free((char*)vp->var_text);
2234
2235                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2236         } else {
2237                 /* variable s is not found */
2238                 if (flags & VNOSET)
2239                         return;
2240                 vp = ckzalloc(sizeof(*vp));
2241                 vp->next = *vpp;
2242                 /*vp->func = NULL; - ckzalloc did it */
2243                 *vpp = vp;
2244         }
2245         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2246                 s = ckstrdup(s);
2247         vp->var_text = s;
2248         vp->flags = flags;
2249 }
2250
2251 /*
2252  * Set the value of a variable.  The flags argument is ored with the
2253  * flags of the variable.  If val is NULL, the variable is unset.
2254  */
2255 static void
2256 setvar(const char *name, const char *val, int flags)
2257 {
2258         const char *q;
2259         char *p;
2260         char *nameeq;
2261         size_t namelen;
2262         size_t vallen;
2263
2264         q = endofname(name);
2265         p = strchrnul(q, '=');
2266         namelen = p - name;
2267         if (!namelen || p != q)
2268                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2269         vallen = 0;
2270         if (val == NULL) {
2271                 flags |= VUNSET;
2272         } else {
2273                 vallen = strlen(val);
2274         }
2275
2276         INT_OFF;
2277         nameeq = ckmalloc(namelen + vallen + 2);
2278         p = memcpy(nameeq, name, namelen) + namelen;
2279         if (val) {
2280                 *p++ = '=';
2281                 p = memcpy(p, val, vallen) + vallen;
2282         }
2283         *p = '\0';
2284         setvareq(nameeq, flags | VNOSAVE);
2285         INT_ON;
2286 }
2287
2288 static void FAST_FUNC
2289 setvar0(const char *name, const char *val)
2290 {
2291         setvar(name, val, 0);
2292 }
2293
2294 /*
2295  * Unset the specified variable.
2296  */
2297 static int
2298 unsetvar(const char *s)
2299 {
2300         struct var **vpp;
2301         struct var *vp;
2302         int retval;
2303
2304         vpp = findvar(hashvar(s), s);
2305         vp = *vpp;
2306         retval = 2;
2307         if (vp) {
2308                 int flags = vp->flags;
2309
2310                 retval = 1;
2311                 if (flags & VREADONLY)
2312                         goto out;
2313 #if ENABLE_ASH_RANDOM_SUPPORT
2314                 vp->flags &= ~VDYNAMIC;
2315 #endif
2316                 if (flags & VUNSET)
2317                         goto ok;
2318                 if ((flags & VSTRFIXED) == 0) {
2319                         INT_OFF;
2320                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2321                                 free((char*)vp->var_text);
2322                         *vpp = vp->next;
2323                         free(vp);
2324                         INT_ON;
2325                 } else {
2326                         setvar0(s, NULL);
2327                         vp->flags &= ~VEXPORT;
2328                 }
2329  ok:
2330                 retval = 0;
2331         }
2332  out:
2333         return retval;
2334 }
2335
2336 /*
2337  * Process a linked list of variable assignments.
2338  */
2339 static void
2340 listsetvar(struct strlist *list_set_var, int flags)
2341 {
2342         struct strlist *lp = list_set_var;
2343
2344         if (!lp)
2345                 return;
2346         INT_OFF;
2347         do {
2348                 setvareq(lp->text, flags);
2349                 lp = lp->next;
2350         } while (lp);
2351         INT_ON;
2352 }
2353
2354 /*
2355  * Generate a list of variables satisfying the given conditions.
2356  */
2357 static char **
2358 listvars(int on, int off, char ***end)
2359 {
2360         struct var **vpp;
2361         struct var *vp;
2362         char **ep;
2363         int mask;
2364
2365         STARTSTACKSTR(ep);
2366         vpp = vartab;
2367         mask = on | off;
2368         do {
2369                 for (vp = *vpp; vp; vp = vp->next) {
2370                         if ((vp->flags & mask) == on) {
2371                                 if (ep == stackstrend())
2372                                         ep = growstackstr();
2373                                 *ep++ = (char*)vp->var_text;
2374                         }
2375                 }
2376         } while (++vpp < vartab + VTABSIZE);
2377         if (ep == stackstrend())
2378                 ep = growstackstr();
2379         if (end)
2380                 *end = ep;
2381         *ep++ = NULL;
2382         return grabstackstr(ep);
2383 }
2384
2385
2386 /* ============ Path search helper
2387  *
2388  * The variable path (passed by reference) should be set to the start
2389  * of the path before the first call; path_advance will update
2390  * this value as it proceeds.  Successive calls to path_advance will return
2391  * the possible path expansions in sequence.  If an option (indicated by
2392  * a percent sign) appears in the path entry then the global variable
2393  * pathopt will be set to point to it; otherwise pathopt will be set to
2394  * NULL.
2395  */
2396 static const char *pathopt;     /* set by path_advance */
2397
2398 static char *
2399 path_advance(const char **path, const char *name)
2400 {
2401         const char *p;
2402         char *q;
2403         const char *start;
2404         size_t len;
2405
2406         if (*path == NULL)
2407                 return NULL;
2408         start = *path;
2409         for (p = start; *p && *p != ':' && *p != '%'; p++)
2410                 continue;
2411         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2412         while (stackblocksize() < len)
2413                 growstackblock();
2414         q = stackblock();
2415         if (p != start) {
2416                 memcpy(q, start, p - start);
2417                 q += p - start;
2418                 *q++ = '/';
2419         }
2420         strcpy(q, name);
2421         pathopt = NULL;
2422         if (*p == '%') {
2423                 pathopt = ++p;
2424                 while (*p && *p != ':')
2425                         p++;
2426         }
2427         if (*p == ':')
2428                 *path = p + 1;
2429         else
2430                 *path = NULL;
2431         return stalloc(len);
2432 }
2433
2434
2435 /* ============ Prompt */
2436
2437 static smallint doprompt;                   /* if set, prompt the user */
2438 static smallint needprompt;                 /* true if interactive and at start of line */
2439
2440 #if ENABLE_FEATURE_EDITING
2441 static line_input_t *line_input_state;
2442 static const char *cmdedit_prompt;
2443 static void
2444 putprompt(const char *s)
2445 {
2446         if (ENABLE_ASH_EXPAND_PRMT) {
2447                 free((char*)cmdedit_prompt);
2448                 cmdedit_prompt = ckstrdup(s);
2449                 return;
2450         }
2451         cmdedit_prompt = s;
2452 }
2453 #else
2454 static void
2455 putprompt(const char *s)
2456 {
2457         out2str(s);
2458 }
2459 #endif
2460
2461 /* expandstr() needs parsing machinery, so it is far away ahead... */
2462 static const char *expandstr(const char *ps);
2463
2464 static void
2465 setprompt_if(smallint do_set, int whichprompt)
2466 {
2467         const char *prompt;
2468         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2469
2470         if (!do_set)
2471                 return;
2472
2473         needprompt = 0;
2474
2475         switch (whichprompt) {
2476         case 1:
2477                 prompt = ps1val();
2478                 break;
2479         case 2:
2480                 prompt = ps2val();
2481                 break;
2482         default:                        /* 0 */
2483                 prompt = nullstr;
2484         }
2485 #if ENABLE_ASH_EXPAND_PRMT
2486         pushstackmark(&smark, stackblocksize());
2487         putprompt(expandstr(prompt));
2488         popstackmark(&smark);
2489 #else
2490         putprompt(prompt);
2491 #endif
2492 }
2493
2494
2495 /* ============ The cd and pwd commands */
2496
2497 #define CD_PHYSICAL 1
2498 #define CD_PRINT 2
2499
2500 static int
2501 cdopt(void)
2502 {
2503         int flags = 0;
2504         int i, j;
2505
2506         j = 'L';
2507         while ((i = nextopt("LP")) != '\0') {
2508                 if (i != j) {
2509                         flags ^= CD_PHYSICAL;
2510                         j = i;
2511                 }
2512         }
2513
2514         return flags;
2515 }
2516
2517 /*
2518  * Update curdir (the name of the current directory) in response to a
2519  * cd command.
2520  */
2521 static const char *
2522 updatepwd(const char *dir)
2523 {
2524         char *new;
2525         char *p;
2526         char *cdcomppath;
2527         const char *lim;
2528
2529         cdcomppath = sstrdup(dir);
2530         STARTSTACKSTR(new);
2531         if (*dir != '/') {
2532                 if (curdir == nullstr)
2533                         return 0;
2534                 new = stack_putstr(curdir, new);
2535         }
2536         new = makestrspace(strlen(dir) + 2, new);
2537         lim = (char *)stackblock() + 1;
2538         if (*dir != '/') {
2539                 if (new[-1] != '/')
2540                         USTPUTC('/', new);
2541                 if (new > lim && *lim == '/')
2542                         lim++;
2543         } else {
2544                 USTPUTC('/', new);
2545                 cdcomppath++;
2546                 if (dir[1] == '/' && dir[2] != '/') {
2547                         USTPUTC('/', new);
2548                         cdcomppath++;
2549                         lim++;
2550                 }
2551         }
2552         p = strtok(cdcomppath, "/");
2553         while (p) {
2554                 switch (*p) {
2555                 case '.':
2556                         if (p[1] == '.' && p[2] == '\0') {
2557                                 while (new > lim) {
2558                                         STUNPUTC(new);
2559                                         if (new[-1] == '/')
2560                                                 break;
2561                                 }
2562                                 break;
2563                         }
2564                         if (p[1] == '\0')
2565                                 break;
2566                         /* fall through */
2567                 default:
2568                         new = stack_putstr(p, new);
2569                         USTPUTC('/', new);
2570                 }
2571                 p = strtok(NULL, "/");
2572         }
2573         if (new > lim)
2574                 STUNPUTC(new);
2575         *new = 0;
2576         return stackblock();
2577 }
2578
2579 /*
2580  * Find out what the current directory is. If we already know the current
2581  * directory, this routine returns immediately.
2582  */
2583 static char *
2584 getpwd(void)
2585 {
2586         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2587         return dir ? dir : nullstr;
2588 }
2589
2590 static void
2591 setpwd(const char *val, int setold)
2592 {
2593         char *oldcur, *dir;
2594
2595         oldcur = dir = curdir;
2596
2597         if (setold) {
2598                 setvar("OLDPWD", oldcur, VEXPORT);
2599         }
2600         INT_OFF;
2601         if (physdir != nullstr) {
2602                 if (physdir != oldcur)
2603                         free(physdir);
2604                 physdir = nullstr;
2605         }
2606         if (oldcur == val || !val) {
2607                 char *s = getpwd();
2608                 physdir = s;
2609                 if (!val)
2610                         dir = s;
2611         } else
2612                 dir = ckstrdup(val);
2613         if (oldcur != dir && oldcur != nullstr) {
2614                 free(oldcur);
2615         }
2616         curdir = dir;
2617         INT_ON;
2618         setvar("PWD", dir, VEXPORT);
2619 }
2620
2621 static void hashcd(void);
2622
2623 /*
2624  * Actually do the chdir.  We also call hashcd to let other routines
2625  * know that the current directory has changed.
2626  */
2627 static int
2628 docd(const char *dest, int flags)
2629 {
2630         const char *dir = NULL;
2631         int err;
2632
2633         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2634
2635         INT_OFF;
2636         if (!(flags & CD_PHYSICAL)) {
2637                 dir = updatepwd(dest);
2638                 if (dir)
2639                         dest = dir;
2640         }
2641         err = chdir(dest);
2642         if (err)
2643                 goto out;
2644         setpwd(dir, 1);
2645         hashcd();
2646  out:
2647         INT_ON;
2648         return err;
2649 }
2650
2651 static int FAST_FUNC
2652 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2653 {
2654         const char *dest;
2655         const char *path;
2656         const char *p;
2657         char c;
2658         struct stat statb;
2659         int flags;
2660
2661         flags = cdopt();
2662         dest = *argptr;
2663         if (!dest)
2664                 dest = bltinlookup("HOME");
2665         else if (LONE_DASH(dest)) {
2666                 dest = bltinlookup("OLDPWD");
2667                 flags |= CD_PRINT;
2668         }
2669         if (!dest)
2670                 dest = nullstr;
2671         if (*dest == '/')
2672                 goto step6;
2673         if (*dest == '.') {
2674                 c = dest[1];
2675  dotdot:
2676                 switch (c) {
2677                 case '\0':
2678                 case '/':
2679                         goto step6;
2680                 case '.':
2681                         c = dest[2];
2682                         if (c != '.')
2683                                 goto dotdot;
2684                 }
2685         }
2686         if (!*dest)
2687                 dest = ".";
2688         path = bltinlookup("CDPATH");
2689         while (path) {
2690                 c = *path;
2691                 p = path_advance(&path, dest);
2692                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2693                         if (c && c != ':')
2694                                 flags |= CD_PRINT;
2695  docd:
2696                         if (!docd(p, flags))
2697                                 goto out;
2698                         goto err;
2699                 }
2700         }
2701
2702  step6:
2703         p = dest;
2704         goto docd;
2705
2706  err:
2707         ash_msg_and_raise_error("can't cd to %s", dest);
2708         /* NOTREACHED */
2709  out:
2710         if (flags & CD_PRINT)
2711                 out1fmt("%s\n", curdir);
2712         return 0;
2713 }
2714
2715 static int FAST_FUNC
2716 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2717 {
2718         int flags;
2719         const char *dir = curdir;
2720
2721         flags = cdopt();
2722         if (flags) {
2723                 if (physdir == nullstr)
2724                         setpwd(dir, 0);
2725                 dir = physdir;
2726         }
2727         out1fmt("%s\n", dir);
2728         return 0;
2729 }
2730
2731
2732 /* ============ ... */
2733
2734
2735 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2736
2737 /* Syntax classes */
2738 #define CWORD     0             /* character is nothing special */
2739 #define CNL       1             /* newline character */
2740 #define CBACK     2             /* a backslash character */
2741 #define CSQUOTE   3             /* single quote */
2742 #define CDQUOTE   4             /* double quote */
2743 #define CENDQUOTE 5             /* a terminating quote */
2744 #define CBQUOTE   6             /* backwards single quote */
2745 #define CVAR      7             /* a dollar sign */
2746 #define CENDVAR   8             /* a '}' character */
2747 #define CLP       9             /* a left paren in arithmetic */
2748 #define CRP      10             /* a right paren in arithmetic */
2749 #define CENDFILE 11             /* end of file */
2750 #define CCTL     12             /* like CWORD, except it must be escaped */
2751 #define CSPCL    13             /* these terminate a word */
2752 #define CIGN     14             /* character should be ignored */
2753
2754 #define PEOF     256
2755 #if ENABLE_ASH_ALIAS
2756 # define PEOA    257
2757 #endif
2758
2759 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2760
2761 #if ENABLE_FEATURE_SH_MATH
2762 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2763 #else
2764 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2765 #endif
2766 static const uint16_t S_I_T[] ALIGN2 = {
2767 #if ENABLE_ASH_ALIAS
2768         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2769 #endif
2770         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2771         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2772         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2773         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2774         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2775         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2776         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2777         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2778         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2779         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2780         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2781 #if !USE_SIT_FUNCTION
2782         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2783         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2784         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2785 #endif
2786 #undef SIT_ITEM
2787 };
2788 /* Constants below must match table above */
2789 enum {
2790 #if ENABLE_ASH_ALIAS
2791         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2792 #endif
2793         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2794         CNL_CNL_CNL_CNL                    , /*  2 */
2795         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2796         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2797         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2798         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2799         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2800         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2801         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2802         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2803         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2804         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2805         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2806         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2807 };
2808
2809 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2810  * caller must ensure proper cast on it if c is *char_ptr!
2811  */
2812 /* Values for syntax param */
2813 #define BASESYNTAX 0    /* not in quotes */
2814 #define DQSYNTAX   1    /* in double quotes */
2815 #define SQSYNTAX   2    /* in single quotes */
2816 #define ARISYNTAX  3    /* in arithmetic */
2817 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2818
2819 #if USE_SIT_FUNCTION
2820
2821 static int
2822 SIT(int c, int syntax)
2823 {
2824         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2825         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2826         /*
2827          * This causes '/' to be prepended with CTLESC in dquoted string,
2828          * making "./file"* treated incorrectly because we feed
2829          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2830          * The "homegrown" glob implementation is okay with that,
2831          * but glibc one isn't. With '/' always treated as CWORD,
2832          * both work fine.
2833          */
2834 # if ENABLE_ASH_ALIAS
2835         static const uint8_t syntax_index_table[] ALIGN1 = {
2836                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2837                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2838                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2839                 11, 3                           /* "}~" */
2840         };
2841 # else
2842         static const uint8_t syntax_index_table[] ALIGN1 = {
2843                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2844                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2845                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2846                 10, 2                           /* "}~" */
2847         };
2848 # endif
2849         const char *s;
2850         int indx;
2851
2852         if (c == PEOF)
2853                 return CENDFILE;
2854 # if ENABLE_ASH_ALIAS
2855         if (c == PEOA)
2856                 indx = 0;
2857         else
2858 # endif
2859         {
2860                 /* Cast is purely for paranoia here,
2861                  * just in case someone passed signed char to us */
2862                 if ((unsigned char)c >= CTL_FIRST
2863                  && (unsigned char)c <= CTL_LAST
2864                 ) {
2865                         return CCTL;
2866                 }
2867                 s = strchrnul(spec_symbls, c);
2868                 if (*s == '\0')
2869                         return CWORD;
2870                 indx = syntax_index_table[s - spec_symbls];
2871         }
2872         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2873 }
2874
2875 #else   /* !USE_SIT_FUNCTION */
2876
2877 static const uint8_t syntax_index_table[] ALIGN1 = {
2878         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2879         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2880         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2881         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2882         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2883         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2884         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2885         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2886         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2887         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2888         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2889         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2890         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2891         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2892         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2893         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2894         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2895         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2896         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2897         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2898         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2899         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2900         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2901         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2902         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2903         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2904         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2912         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2913         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2914         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2915         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2916         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2917         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2918         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2919         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2920         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2921         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2922         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2923         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2924         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2925         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2926 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2927         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2928         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2930         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2939         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2940         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2941         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2942         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2943         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2944         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2972         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2973         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2974         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2977         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2980         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2981         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2982         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2983         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2984         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2985         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2986         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2987         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2988         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2989         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3005         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3006         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3007         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3008         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3009         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3010         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3011         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3012         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3013         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3014         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3015         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3016         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3017         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3018         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3019         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3020         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3021         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3136         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3137 # if ENABLE_ASH_ALIAS
3138         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3139 # endif
3140 };
3141
3142 #if 1
3143 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3144 #else /* debug version, caught one signed char bug */
3145 # define SIT(c, syntax) \
3146         ({ \
3147                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3148                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3149                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3150                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3151                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3152         })
3153 #endif
3154
3155 #endif  /* !USE_SIT_FUNCTION */
3156
3157
3158 /* ============ Alias handling */
3159
3160 #if ENABLE_ASH_ALIAS
3161
3162 #define ALIASINUSE 1
3163 #define ALIASDEAD  2
3164
3165 struct alias {
3166         struct alias *next;
3167         char *name;
3168         char *val;
3169         int flag;
3170 };
3171
3172
3173 static struct alias **atab; // [ATABSIZE];
3174 #define INIT_G_alias() do { \
3175         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3176 } while (0)
3177
3178
3179 static struct alias **
3180 __lookupalias(const char *name)
3181 {
3182         unsigned int hashval;
3183         struct alias **app;
3184         const char *p;
3185         unsigned int ch;
3186
3187         p = name;
3188
3189         ch = (unsigned char)*p;
3190         hashval = ch << 4;
3191         while (ch) {
3192                 hashval += ch;
3193                 ch = (unsigned char)*++p;
3194         }
3195         app = &atab[hashval % ATABSIZE];
3196
3197         for (; *app; app = &(*app)->next) {
3198                 if (strcmp(name, (*app)->name) == 0) {
3199                         break;
3200                 }
3201         }
3202
3203         return app;
3204 }
3205
3206 static struct alias *
3207 lookupalias(const char *name, int check)
3208 {
3209         struct alias *ap = *__lookupalias(name);
3210
3211         if (check && ap && (ap->flag & ALIASINUSE))
3212                 return NULL;
3213         return ap;
3214 }
3215
3216 static struct alias *
3217 freealias(struct alias *ap)
3218 {
3219         struct alias *next;
3220
3221         if (ap->flag & ALIASINUSE) {
3222                 ap->flag |= ALIASDEAD;
3223                 return ap;
3224         }
3225
3226         next = ap->next;
3227         free(ap->name);
3228         free(ap->val);
3229         free(ap);
3230         return next;
3231 }
3232
3233 static void
3234 setalias(const char *name, const char *val)
3235 {
3236         struct alias *ap, **app;
3237
3238         app = __lookupalias(name);
3239         ap = *app;
3240         INT_OFF;
3241         if (ap) {
3242                 if (!(ap->flag & ALIASINUSE)) {
3243                         free(ap->val);
3244                 }
3245                 ap->val = ckstrdup(val);
3246                 ap->flag &= ~ALIASDEAD;
3247         } else {
3248                 /* not found */
3249                 ap = ckzalloc(sizeof(struct alias));
3250                 ap->name = ckstrdup(name);
3251                 ap->val = ckstrdup(val);
3252                 /*ap->flag = 0; - ckzalloc did it */
3253                 /*ap->next = NULL;*/
3254                 *app = ap;
3255         }
3256         INT_ON;
3257 }
3258
3259 static int
3260 unalias(const char *name)
3261 {
3262         struct alias **app;
3263
3264         app = __lookupalias(name);
3265
3266         if (*app) {
3267                 INT_OFF;
3268                 *app = freealias(*app);
3269                 INT_ON;
3270                 return 0;
3271         }
3272
3273         return 1;
3274 }
3275
3276 static void
3277 rmaliases(void)
3278 {
3279         struct alias *ap, **app;
3280         int i;
3281
3282         INT_OFF;
3283         for (i = 0; i < ATABSIZE; i++) {
3284                 app = &atab[i];
3285                 for (ap = *app; ap; ap = *app) {
3286                         *app = freealias(*app);
3287                         if (ap == *app) {
3288                                 app = &ap->next;
3289                         }
3290                 }
3291         }
3292         INT_ON;
3293 }
3294
3295 static void
3296 printalias(const struct alias *ap)
3297 {
3298         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3299 }
3300
3301 /*
3302  * TODO - sort output
3303  */
3304 static int FAST_FUNC
3305 aliascmd(int argc UNUSED_PARAM, char **argv)
3306 {
3307         char *n, *v;
3308         int ret = 0;
3309         struct alias *ap;
3310
3311         if (!argv[1]) {
3312                 int i;
3313
3314                 for (i = 0; i < ATABSIZE; i++) {
3315                         for (ap = atab[i]; ap; ap = ap->next) {
3316                                 printalias(ap);
3317                         }
3318                 }
3319                 return 0;
3320         }
3321         while ((n = *++argv) != NULL) {
3322                 v = strchr(n+1, '=');
3323                 if (v == NULL) { /* n+1: funny ksh stuff */
3324                         ap = *__lookupalias(n);
3325                         if (ap == NULL) {
3326                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3327                                 ret = 1;
3328                         } else
3329                                 printalias(ap);
3330                 } else {
3331                         *v++ = '\0';
3332                         setalias(n, v);
3333                 }
3334         }
3335
3336         return ret;
3337 }
3338
3339 static int FAST_FUNC
3340 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3341 {
3342         int i;
3343
3344         while (nextopt("a") != '\0') {
3345                 rmaliases();
3346                 return 0;
3347         }
3348         for (i = 0; *argptr; argptr++) {
3349                 if (unalias(*argptr)) {
3350                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3351                         i = 1;
3352                 }
3353         }
3354
3355         return i;
3356 }
3357
3358 #endif /* ASH_ALIAS */
3359
3360
3361 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3362 #define FORK_FG    0
3363 #define FORK_BG    1
3364 #define FORK_NOJOB 2
3365
3366 /* mode flags for showjob(s) */
3367 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3368 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3369 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3370 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3371
3372 /*
3373  * A job structure contains information about a job.  A job is either a
3374  * single process or a set of processes contained in a pipeline.  In the
3375  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3376  * array of pids.
3377  */
3378 struct procstat {
3379         pid_t   ps_pid;         /* process id */
3380         int     ps_status;      /* last process status from wait() */
3381         char    *ps_cmd;        /* text of command being run */
3382 };
3383
3384 struct job {
3385         struct procstat ps0;    /* status of process */
3386         struct procstat *ps;    /* status or processes when more than one */
3387 #if JOBS
3388         int stopstatus;         /* status of a stopped job */
3389 #endif
3390         unsigned nprocs;        /* number of processes */
3391
3392 #define JOBRUNNING      0       /* at least one proc running */
3393 #define JOBSTOPPED      1       /* all procs are stopped */
3394 #define JOBDONE         2       /* all procs are completed */
3395         unsigned
3396                 state: 8,
3397 #if JOBS
3398                 sigint: 1,      /* job was killed by SIGINT */
3399                 jobctl: 1,      /* job running under job control */
3400 #endif
3401                 waited: 1,      /* true if this entry has been waited for */
3402                 used: 1,        /* true if this entry is in used */
3403                 changed: 1;     /* true if status has changed */
3404         struct job *prev_job;   /* previous job */
3405 };
3406
3407 static struct job *makejob(/*union node *,*/ int);
3408 static int forkshell(struct job *, union node *, int);
3409 static int waitforjob(struct job *);
3410
3411 #if !JOBS
3412 enum { doing_jobctl = 0 };
3413 #define setjobctl(on) do {} while (0)
3414 #else
3415 static smallint doing_jobctl; //references:8
3416 static void setjobctl(int);
3417 #endif
3418
3419 /*
3420  * Ignore a signal.
3421  */
3422 static void
3423 ignoresig(int signo)
3424 {
3425         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3426         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3427                 /* No, need to do it */
3428                 signal(signo, SIG_IGN);
3429         }
3430         sigmode[signo - 1] = S_HARD_IGN;
3431 }
3432
3433 /*
3434  * Only one usage site - in setsignal()
3435  */
3436 static void
3437 signal_handler(int signo)
3438 {
3439         if (signo == SIGCHLD) {
3440                 got_sigchld = 1;
3441                 if (!trap[SIGCHLD])
3442                         return;
3443         }
3444
3445         gotsig[signo - 1] = 1;
3446         pending_sig = signo;
3447
3448         if (signo == SIGINT && !trap[SIGINT]) {
3449                 if (!suppress_int) {
3450                         pending_sig = 0;
3451                         raise_interrupt(); /* does not return */
3452                 }
3453                 pending_int = 1;
3454         }
3455 }
3456
3457 /*
3458  * Set the signal handler for the specified signal.  The routine figures
3459  * out what it should be set to.
3460  */
3461 static void
3462 setsignal(int signo)
3463 {
3464         char *t;
3465         char cur_act, new_act;
3466         struct sigaction act;
3467
3468         t = trap[signo];
3469         new_act = S_DFL;
3470         if (t != NULL) { /* trap for this sig is set */
3471                 new_act = S_CATCH;
3472                 if (t[0] == '\0') /* trap is "": ignore this sig */
3473                         new_act = S_IGN;
3474         }
3475
3476         if (rootshell && new_act == S_DFL) {
3477                 switch (signo) {
3478                 case SIGINT:
3479                         if (iflag || minusc || sflag == 0)
3480                                 new_act = S_CATCH;
3481                         break;
3482                 case SIGQUIT:
3483 #if DEBUG
3484                         if (debug)
3485                                 break;
3486 #endif
3487                         /* man bash:
3488                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3489                          * commands run by bash have signal handlers
3490                          * set to the values inherited by the shell
3491                          * from its parent". */
3492                         new_act = S_IGN;
3493                         break;
3494                 case SIGTERM:
3495                         if (iflag)
3496                                 new_act = S_IGN;
3497                         break;
3498 #if JOBS
3499                 case SIGTSTP:
3500                 case SIGTTOU:
3501                         if (mflag)
3502                                 new_act = S_IGN;
3503                         break;
3504 #endif
3505                 }
3506         }
3507 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3508 //whereas we have to restore it to what shell got on entry
3509 //from the parent. See comment above
3510
3511         if (signo == SIGCHLD)
3512                 new_act = S_CATCH;
3513
3514         t = &sigmode[signo - 1];
3515         cur_act = *t;
3516         if (cur_act == 0) {
3517                 /* current setting is not yet known */
3518                 if (sigaction(signo, NULL, &act)) {
3519                         /* pretend it worked; maybe we should give a warning,
3520                          * but other shells don't. We don't alter sigmode,
3521                          * so we retry every time.
3522                          * btw, in Linux it never fails. --vda */
3523                         return;
3524                 }
3525                 if (act.sa_handler == SIG_IGN) {
3526                         cur_act = S_HARD_IGN;
3527                         if (mflag
3528                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3529                         ) {
3530                                 cur_act = S_IGN;   /* don't hard ignore these */
3531                         }
3532                 }
3533         }
3534         if (cur_act == S_HARD_IGN || cur_act == new_act)
3535                 return;
3536
3537         act.sa_handler = SIG_DFL;
3538         switch (new_act) {
3539         case S_CATCH:
3540                 act.sa_handler = signal_handler;
3541                 break;
3542         case S_IGN:
3543                 act.sa_handler = SIG_IGN;
3544                 break;
3545         }
3546
3547         /* flags and mask matter only if !DFL and !IGN, but we do it
3548          * for all cases for more deterministic behavior:
3549          */
3550         act.sa_flags = 0;
3551         sigfillset(&act.sa_mask);
3552
3553         sigaction_set(signo, &act);
3554
3555         *t = new_act;
3556 }
3557
3558 /* mode flags for set_curjob */
3559 #define CUR_DELETE 2
3560 #define CUR_RUNNING 1
3561 #define CUR_STOPPED 0
3562
3563 #if JOBS
3564 /* pgrp of shell on invocation */
3565 static int initialpgrp; //references:2
3566 static int ttyfd = -1; //5
3567 #endif
3568 /* array of jobs */
3569 static struct job *jobtab; //5
3570 /* size of array */
3571 static unsigned njobs; //4
3572 /* current job */
3573 static struct job *curjob; //lots
3574 /* number of presumed living untracked jobs */
3575 static int jobless; //4
3576
3577 #if 0
3578 /* Bash has a feature: it restores termios after a successful wait for
3579  * a foreground job which had at least one stopped or sigkilled member.
3580  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3581  * properly restoring tty state. Should we do this too?
3582  * A reproducer: ^Z an interactive python:
3583  *
3584  * # python
3585  * Python 2.7.12 (...)
3586  * >>> ^Z
3587  *      { python leaves tty in -icanon -echo state. We do survive that... }
3588  *  [1]+  Stopped                    python
3589  *      { ...however, next program (python #2) does not survive it well: }
3590  * # python
3591  * Python 2.7.12 (...)
3592  * >>> Traceback (most recent call last):
3593  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3594  *   File "<stdin>", line 1, in <module>
3595  * NameError: name 'qwerty' is not defined
3596  *
3597  * The implementation below is modeled on bash code and seems to work.
3598  * However, I'm not sure we should do this. For one: what if I'd fg
3599  * the stopped python instead? It'll be confused by "restored" tty state.
3600  */
3601 static struct termios shell_tty_info;
3602 static void
3603 get_tty_state(void)
3604 {
3605         if (rootshell && ttyfd >= 0)
3606                 tcgetattr(ttyfd, &shell_tty_info);
3607 }
3608 static void
3609 set_tty_state(void)
3610 {
3611         /* if (rootshell) - caller ensures this */
3612         if (ttyfd >= 0)
3613                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3614 }
3615 static int
3616 job_signal_status(struct job *jp)
3617 {
3618         int status;
3619         unsigned i;
3620         struct procstat *ps = jp->ps;
3621         for (i = 0; i < jp->nprocs; i++) {
3622                 status = ps[i].ps_status;
3623                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3624                         return status;
3625         }
3626         return 0;
3627 }
3628 static void
3629 restore_tty_if_stopped_or_signaled(struct job *jp)
3630 {
3631 //TODO: check what happens if we come from waitforjob() in expbackq()
3632         if (rootshell) {
3633                 int s = job_signal_status(jp);
3634                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3635                         set_tty_state();
3636         }
3637 }
3638 #else
3639 # define get_tty_state() ((void)0)
3640 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3641 #endif
3642
3643 static void
3644 set_curjob(struct job *jp, unsigned mode)
3645 {
3646         struct job *jp1;
3647         struct job **jpp, **curp;
3648
3649         /* first remove from list */
3650         jpp = curp = &curjob;
3651         while (1) {
3652                 jp1 = *jpp;
3653                 if (jp1 == jp)
3654                         break;
3655                 jpp = &jp1->prev_job;
3656         }
3657         *jpp = jp1->prev_job;
3658
3659         /* Then re-insert in correct position */
3660         jpp = curp;
3661         switch (mode) {
3662         default:
3663 #if DEBUG
3664                 abort();
3665 #endif
3666         case CUR_DELETE:
3667                 /* job being deleted */
3668                 break;
3669         case CUR_RUNNING:
3670                 /* newly created job or backgrounded job,
3671                  * put after all stopped jobs.
3672                  */
3673                 while (1) {
3674                         jp1 = *jpp;
3675 #if JOBS
3676                         if (!jp1 || jp1->state != JOBSTOPPED)
3677 #endif
3678                                 break;
3679                         jpp = &jp1->prev_job;
3680                 }
3681                 /* FALLTHROUGH */
3682 #if JOBS
3683         case CUR_STOPPED:
3684 #endif
3685                 /* newly stopped job - becomes curjob */
3686                 jp->prev_job = *jpp;
3687                 *jpp = jp;
3688                 break;
3689         }
3690 }
3691
3692 #if JOBS || DEBUG
3693 static int
3694 jobno(const struct job *jp)
3695 {
3696         return jp - jobtab + 1;
3697 }
3698 #endif
3699
3700 /*
3701  * Convert a job name to a job structure.
3702  */
3703 #if !JOBS
3704 #define getjob(name, getctl) getjob(name)
3705 #endif
3706 static struct job *
3707 getjob(const char *name, int getctl)
3708 {
3709         struct job *jp;
3710         struct job *found;
3711         const char *err_msg = "%s: no such job";
3712         unsigned num;
3713         int c;
3714         const char *p;
3715         char *(*match)(const char *, const char *);
3716
3717         jp = curjob;
3718         p = name;
3719         if (!p)
3720                 goto currentjob;
3721
3722         if (*p != '%')
3723                 goto err;
3724
3725         c = *++p;
3726         if (!c)
3727                 goto currentjob;
3728
3729         if (!p[1]) {
3730                 if (c == '+' || c == '%') {
3731  currentjob:
3732                         err_msg = "No current job";
3733                         goto check;
3734                 }
3735                 if (c == '-') {
3736                         if (jp)
3737                                 jp = jp->prev_job;
3738                         err_msg = "No previous job";
3739  check:
3740                         if (!jp)
3741                                 goto err;
3742                         goto gotit;
3743                 }
3744         }
3745
3746         if (is_number(p)) {
3747                 num = atoi(p);
3748                 if (num > 0 && num <= njobs) {
3749                         jp = jobtab + num - 1;
3750                         if (jp->used)
3751                                 goto gotit;
3752                         goto err;
3753                 }
3754         }
3755
3756         match = prefix;
3757         if (*p == '?') {
3758                 match = strstr;
3759                 p++;
3760         }
3761
3762         found = NULL;
3763         while (jp) {
3764                 if (match(jp->ps[0].ps_cmd, p)) {
3765                         if (found)
3766                                 goto err;
3767                         found = jp;
3768                         err_msg = "%s: ambiguous";
3769                 }
3770                 jp = jp->prev_job;
3771         }
3772         if (!found)
3773                 goto err;
3774         jp = found;
3775
3776  gotit:
3777 #if JOBS
3778         err_msg = "job %s not created under job control";
3779         if (getctl && jp->jobctl == 0)
3780                 goto err;
3781 #endif
3782         return jp;
3783  err:
3784         ash_msg_and_raise_error(err_msg, name);
3785 }
3786
3787 /*
3788  * Mark a job structure as unused.
3789  */
3790 static void
3791 freejob(struct job *jp)
3792 {
3793         struct procstat *ps;
3794         int i;
3795
3796         INT_OFF;
3797         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3798                 if (ps->ps_cmd != nullstr)
3799                         free(ps->ps_cmd);
3800         }
3801         if (jp->ps != &jp->ps0)
3802                 free(jp->ps);
3803         jp->used = 0;
3804         set_curjob(jp, CUR_DELETE);
3805         INT_ON;
3806 }
3807
3808 #if JOBS
3809 static void
3810 xtcsetpgrp(int fd, pid_t pgrp)
3811 {
3812         if (tcsetpgrp(fd, pgrp))
3813                 ash_msg_and_raise_error("can't set tty process group (%m)");
3814 }
3815
3816 /*
3817  * Turn job control on and off.
3818  *
3819  * Note:  This code assumes that the third arg to ioctl is a character
3820  * pointer, which is true on Berkeley systems but not System V.  Since
3821  * System V doesn't have job control yet, this isn't a problem now.
3822  *
3823  * Called with interrupts off.
3824  */
3825 static void
3826 setjobctl(int on)
3827 {
3828         int fd;
3829         int pgrp;
3830
3831         if (on == doing_jobctl || rootshell == 0)
3832                 return;
3833         if (on) {
3834                 int ofd;
3835                 ofd = fd = open(_PATH_TTY, O_RDWR);
3836                 if (fd < 0) {
3837         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3838          * That sometimes helps to acquire controlling tty.
3839          * Obviously, a workaround for bugs when someone
3840          * failed to provide a controlling tty to bash! :) */
3841                         fd = 2;
3842                         while (!isatty(fd))
3843                                 if (--fd < 0)
3844                                         goto out;
3845                 }
3846                 /* fd is a tty at this point */
3847                 fd = fcntl(fd, F_DUPFD, 10);
3848                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3849                         close(ofd);
3850                 if (fd < 0)
3851                         goto out; /* F_DUPFD failed */
3852                 close_on_exec_on(fd);
3853                 while (1) { /* while we are in the background */
3854                         pgrp = tcgetpgrp(fd);
3855                         if (pgrp < 0) {
3856  out:
3857                                 ash_msg("can't access tty; job control turned off");
3858                                 mflag = on = 0;
3859                                 goto close;
3860                         }
3861                         if (pgrp == getpgrp())
3862                                 break;
3863                         killpg(0, SIGTTIN);
3864                 }
3865                 initialpgrp = pgrp;
3866
3867                 setsignal(SIGTSTP);
3868                 setsignal(SIGTTOU);
3869                 setsignal(SIGTTIN);
3870                 pgrp = rootpid;
3871                 setpgid(0, pgrp);
3872                 xtcsetpgrp(fd, pgrp);
3873         } else {
3874                 /* turning job control off */
3875                 fd = ttyfd;
3876                 pgrp = initialpgrp;
3877                 /* was xtcsetpgrp, but this can make exiting ash
3878                  * loop forever if pty is already deleted */
3879                 tcsetpgrp(fd, pgrp);
3880                 setpgid(0, pgrp);
3881                 setsignal(SIGTSTP);
3882                 setsignal(SIGTTOU);
3883                 setsignal(SIGTTIN);
3884  close:
3885                 if (fd >= 0)
3886                         close(fd);
3887                 fd = -1;
3888         }
3889         ttyfd = fd;
3890         doing_jobctl = on;
3891 }
3892
3893 static int FAST_FUNC
3894 killcmd(int argc, char **argv)
3895 {
3896         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3897                 int i = 1;
3898                 do {
3899                         if (argv[i][0] == '%') {
3900                                 /*
3901                                  * "kill %N" - job kill
3902                                  * Converting to pgrp / pid kill
3903                                  */
3904                                 struct job *jp;
3905                                 char *dst;
3906                                 int j, n;
3907
3908                                 jp = getjob(argv[i], 0);
3909                                 /*
3910                                  * In jobs started under job control, we signal
3911                                  * entire process group by kill -PGRP_ID.
3912                                  * This happens, f.e., in interactive shell.
3913                                  *
3914                                  * Otherwise, we signal each child via
3915                                  * kill PID1 PID2 PID3.
3916                                  * Testcases:
3917                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3918                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3919                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3920                                  */
3921                                 n = jp->nprocs; /* can't be 0 (I hope) */
3922                                 if (jp->jobctl)
3923                                         n = 1;
3924                                 dst = alloca(n * sizeof(int)*4);
3925                                 argv[i] = dst;
3926                                 for (j = 0; j < n; j++) {
3927                                         struct procstat *ps = &jp->ps[j];
3928                                         /* Skip non-running and not-stopped members
3929                                          * (i.e. dead members) of the job
3930                                          */
3931                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3932                                                 continue;
3933                                         /*
3934                                          * kill_main has matching code to expect
3935                                          * leading space. Needed to not confuse
3936                                          * negative pids with "kill -SIGNAL_NO" syntax
3937                                          */
3938                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3939                                 }
3940                                 *dst = '\0';
3941                         }
3942                 } while (argv[++i]);
3943         }
3944         return kill_main(argc, argv);
3945 }
3946
3947 static void
3948 showpipe(struct job *jp /*, FILE *out*/)
3949 {
3950         struct procstat *ps;
3951         struct procstat *psend;
3952
3953         psend = jp->ps + jp->nprocs;
3954         for (ps = jp->ps + 1; ps < psend; ps++)
3955                 printf(" | %s", ps->ps_cmd);
3956         newline_and_flush(stdout);
3957         flush_stdout_stderr();
3958 }
3959
3960
3961 static int
3962 restartjob(struct job *jp, int mode)
3963 {
3964         struct procstat *ps;
3965         int i;
3966         int status;
3967         pid_t pgid;
3968
3969         INT_OFF;
3970         if (jp->state == JOBDONE)
3971                 goto out;
3972         jp->state = JOBRUNNING;
3973         pgid = jp->ps[0].ps_pid;
3974         if (mode == FORK_FG) {
3975                 get_tty_state();
3976                 xtcsetpgrp(ttyfd, pgid);
3977         }
3978         killpg(pgid, SIGCONT);
3979         ps = jp->ps;
3980         i = jp->nprocs;
3981         do {
3982                 if (WIFSTOPPED(ps->ps_status)) {
3983                         ps->ps_status = -1;
3984                 }
3985                 ps++;
3986         } while (--i);
3987  out:
3988         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3989         INT_ON;
3990         return status;
3991 }
3992
3993 static int FAST_FUNC
3994 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3995 {
3996         struct job *jp;
3997         int mode;
3998         int retval;
3999
4000         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4001         nextopt(nullstr);
4002         argv = argptr;
4003         do {
4004                 jp = getjob(*argv, 1);
4005                 if (mode == FORK_BG) {
4006                         set_curjob(jp, CUR_RUNNING);
4007                         printf("[%d] ", jobno(jp));
4008                 }
4009                 out1str(jp->ps[0].ps_cmd);
4010                 showpipe(jp /*, stdout*/);
4011                 retval = restartjob(jp, mode);
4012         } while (*argv && *++argv);
4013         return retval;
4014 }
4015 #endif
4016
4017 static int
4018 sprint_status48(char *s, int status, int sigonly)
4019 {
4020         int col;
4021         int st;
4022
4023         col = 0;
4024         if (!WIFEXITED(status)) {
4025                 if (JOBS && WIFSTOPPED(status))
4026                         st = WSTOPSIG(status);
4027                 else
4028                         st = WTERMSIG(status);
4029                 if (sigonly) {
4030                         if (st == SIGINT || st == SIGPIPE)
4031                                 goto out;
4032                         if (JOBS && WIFSTOPPED(status))
4033                                 goto out;
4034                 }
4035                 st &= 0x7f;
4036 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4037                 col = fmtstr(s, 32, strsignal(st));
4038                 if (WCOREDUMP(status)) {
4039                         strcpy(s + col, " (core dumped)");
4040                         col += sizeof(" (core dumped)")-1;
4041                 }
4042         } else if (!sigonly) {
4043                 st = WEXITSTATUS(status);
4044                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4045         }
4046  out:
4047         return col;
4048 }
4049
4050 static int
4051 wait_block_or_sig(int *status)
4052 {
4053         int pid;
4054
4055         do {
4056                 sigset_t mask;
4057
4058                 /* Poll all children for changes in their state */
4059                 got_sigchld = 0;
4060                 /* if job control is active, accept stopped processes too */
4061                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4062                 if (pid != 0)
4063                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4064
4065                 /* Children exist, but none are ready. Sleep until interesting signal */
4066 #if 1
4067                 sigfillset(&mask);
4068                 sigprocmask(SIG_SETMASK, &mask, &mask);
4069                 while (!got_sigchld && !pending_sig)
4070                         sigsuspend(&mask);
4071                 sigprocmask(SIG_SETMASK, &mask, NULL);
4072 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4073                 while (!got_sigchld && !pending_sig)
4074                         pause();
4075 #endif
4076
4077                 /* If it was SIGCHLD, poll children again */
4078         } while (got_sigchld);
4079
4080         return pid;
4081 }
4082
4083 #define DOWAIT_NONBLOCK 0
4084 #define DOWAIT_BLOCK    1
4085 #define DOWAIT_BLOCK_OR_SIG 2
4086
4087 static int
4088 dowait(int block, struct job *job)
4089 {
4090         int pid;
4091         int status;
4092         struct job *jp;
4093         struct job *thisjob = NULL;
4094
4095         TRACE(("dowait(0x%x) called\n", block));
4096
4097         /* It's wrong to call waitpid() outside of INT_OFF region:
4098          * signal can arrive just after syscall return and handler can
4099          * longjmp away, losing stop/exit notification processing.
4100          * Thus, for "jobs" builtin, and for waiting for a fg job,
4101          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4102          *
4103          * However, for "wait" builtin it is wrong to simply call waitpid()
4104          * in INT_OFF region: "wait" needs to wait for any running job
4105          * to change state, but should exit on any trap too.
4106          * In INT_OFF region, a signal just before syscall entry can set
4107          * pending_sig variables, but we can't check them, and we would
4108          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4109          *
4110          * Because of this, we run inside INT_OFF, but use a special routine
4111          * which combines waitpid() and sigsuspend().
4112          * This is the reason why we need to have a handler for SIGCHLD:
4113          * SIG_DFL handler does not wake sigsuspend().
4114          */
4115         INT_OFF;
4116         if (block == DOWAIT_BLOCK_OR_SIG) {
4117                 pid = wait_block_or_sig(&status);
4118         } else {
4119                 int wait_flags = 0;
4120                 if (block == DOWAIT_NONBLOCK)
4121                         wait_flags = WNOHANG;
4122                 /* if job control is active, accept stopped processes too */
4123                 if (doing_jobctl)
4124                         wait_flags |= WUNTRACED;
4125                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4126                 pid = waitpid(-1, &status, wait_flags);
4127         }
4128         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4129                                 pid, status, errno, strerror(errno)));
4130         if (pid <= 0)
4131                 goto out;
4132
4133         thisjob = NULL;
4134         for (jp = curjob; jp; jp = jp->prev_job) {
4135                 int jobstate;
4136                 struct procstat *ps;
4137                 struct procstat *psend;
4138                 if (jp->state == JOBDONE)
4139                         continue;
4140                 jobstate = JOBDONE;
4141                 ps = jp->ps;
4142                 psend = ps + jp->nprocs;
4143                 do {
4144                         if (ps->ps_pid == pid) {
4145                                 TRACE(("Job %d: changing status of proc %d "
4146                                         "from 0x%x to 0x%x\n",
4147                                         jobno(jp), pid, ps->ps_status, status));
4148                                 ps->ps_status = status;
4149                                 thisjob = jp;
4150                         }
4151                         if (ps->ps_status == -1)
4152                                 jobstate = JOBRUNNING;
4153 #if JOBS
4154                         if (jobstate == JOBRUNNING)
4155                                 continue;
4156                         if (WIFSTOPPED(ps->ps_status)) {
4157                                 jp->stopstatus = ps->ps_status;
4158                                 jobstate = JOBSTOPPED;
4159                         }
4160 #endif
4161                 } while (++ps < psend);
4162                 if (!thisjob)
4163                         continue;
4164
4165                 /* Found the job where one of its processes changed its state.
4166                  * Is there at least one live and running process in this job? */
4167                 if (jobstate != JOBRUNNING) {
4168                         /* No. All live processes in the job are stopped
4169                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4170                          */
4171                         thisjob->changed = 1;
4172                         if (thisjob->state != jobstate) {
4173                                 TRACE(("Job %d: changing state from %d to %d\n",
4174                                         jobno(thisjob), thisjob->state, jobstate));
4175                                 thisjob->state = jobstate;
4176 #if JOBS
4177                                 if (jobstate == JOBSTOPPED)
4178                                         set_curjob(thisjob, CUR_STOPPED);
4179 #endif
4180                         }
4181                 }
4182                 goto out;
4183         }
4184         /* The process wasn't found in job list */
4185         if (JOBS && !WIFSTOPPED(status))
4186                 jobless--;
4187  out:
4188         INT_ON;
4189
4190         if (thisjob && thisjob == job) {
4191                 char s[48 + 1];
4192                 int len;
4193
4194                 len = sprint_status48(s, status, 1);
4195                 if (len) {
4196                         s[len] = '\n';
4197                         s[len + 1] = '\0';
4198                         out2str(s);
4199                 }
4200         }
4201         return pid;
4202 }
4203
4204 #if JOBS
4205 static void
4206 showjob(struct job *jp, int mode)
4207 {
4208         struct procstat *ps;
4209         struct procstat *psend;
4210         int col;
4211         int indent_col;
4212         char s[16 + 16 + 48];
4213         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4214
4215         ps = jp->ps;
4216
4217         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4218                 /* just output process (group) id of pipeline */
4219                 fprintf(out, "%d\n", ps->ps_pid);
4220                 return;
4221         }
4222
4223         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4224         indent_col = col;
4225
4226         if (jp == curjob)
4227                 s[col - 3] = '+';
4228         else if (curjob && jp == curjob->prev_job)
4229                 s[col - 3] = '-';
4230
4231         if (mode & SHOW_PIDS)
4232                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4233
4234         psend = ps + jp->nprocs;
4235
4236         if (jp->state == JOBRUNNING) {
4237                 strcpy(s + col, "Running");
4238                 col += sizeof("Running") - 1;
4239         } else {
4240                 int status = psend[-1].ps_status;
4241                 if (jp->state == JOBSTOPPED)
4242                         status = jp->stopstatus;
4243                 col += sprint_status48(s + col, status, 0);
4244         }
4245         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4246
4247         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4248          * or prints several "PID             | <cmdN>" lines,
4249          * depending on SHOW_PIDS bit.
4250          * We do not print status of individual processes
4251          * between PID and <cmdN>. bash does it, but not very well:
4252          * first line shows overall job status, not process status,
4253          * making it impossible to know 1st process status.
4254          */
4255         goto start;
4256         do {
4257                 /* for each process */
4258                 s[0] = '\0';
4259                 col = 33;
4260                 if (mode & SHOW_PIDS)
4261                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4262  start:
4263                 fprintf(out, "%s%*c%s%s",
4264                                 s,
4265                                 33 - col >= 0 ? 33 - col : 0, ' ',
4266                                 ps == jp->ps ? "" : "| ",
4267                                 ps->ps_cmd
4268                 );
4269         } while (++ps != psend);
4270         newline_and_flush(out);
4271
4272         jp->changed = 0;
4273
4274         if (jp->state == JOBDONE) {
4275                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4276                 freejob(jp);
4277         }
4278 }
4279
4280 /*
4281  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4282  * statuses have changed since the last call to showjobs.
4283  */
4284 static void
4285 showjobs(int mode)
4286 {
4287         struct job *jp;
4288
4289         TRACE(("showjobs(0x%x) called\n", mode));
4290
4291         /* Handle all finished jobs */
4292         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4293                 continue;
4294
4295         for (jp = curjob; jp; jp = jp->prev_job) {
4296                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4297                         showjob(jp, mode);
4298                 }
4299         }
4300 }
4301
4302 static int FAST_FUNC
4303 jobscmd(int argc UNUSED_PARAM, char **argv)
4304 {
4305         int mode, m;
4306
4307         mode = 0;
4308         while ((m = nextopt("lp")) != '\0') {
4309                 if (m == 'l')
4310                         mode |= SHOW_PIDS;
4311                 else
4312                         mode |= SHOW_ONLY_PGID;
4313         }
4314
4315         argv = argptr;
4316         if (*argv) {
4317                 do
4318                         showjob(getjob(*argv, 0), mode);
4319                 while (*++argv);
4320         } else {
4321                 showjobs(mode);
4322         }
4323
4324         return 0;
4325 }
4326 #endif /* JOBS */
4327
4328 /* Called only on finished or stopped jobs (no members are running) */
4329 static int
4330 getstatus(struct job *job)
4331 {
4332         int status;
4333         int retval;
4334         struct procstat *ps;
4335
4336         /* Fetch last member's status */
4337         ps = job->ps + job->nprocs - 1;
4338         status = ps->ps_status;
4339         if (pipefail) {
4340                 /* "set -o pipefail" mode: use last _nonzero_ status */
4341                 while (status == 0 && --ps >= job->ps)
4342                         status = ps->ps_status;
4343         }
4344
4345         retval = WEXITSTATUS(status);
4346         if (!WIFEXITED(status)) {
4347 #if JOBS
4348                 retval = WSTOPSIG(status);
4349                 if (!WIFSTOPPED(status))
4350 #endif
4351                 {
4352                         /* XXX: limits number of signals */
4353                         retval = WTERMSIG(status);
4354 #if JOBS
4355                         if (retval == SIGINT)
4356                                 job->sigint = 1;
4357 #endif
4358                 }
4359                 retval += 128;
4360         }
4361         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4362                 jobno(job), job->nprocs, status, retval));
4363         return retval;
4364 }
4365
4366 static int FAST_FUNC
4367 waitcmd(int argc UNUSED_PARAM, char **argv)
4368 {
4369         struct job *job;
4370         int retval;
4371         struct job *jp;
4372
4373         nextopt(nullstr);
4374         retval = 0;
4375
4376         argv = argptr;
4377         if (!*argv) {
4378                 /* wait for all jobs */
4379                 for (;;) {
4380                         jp = curjob;
4381                         while (1) {
4382                                 if (!jp) /* no running procs */
4383                                         goto ret;
4384                                 if (jp->state == JOBRUNNING)
4385                                         break;
4386                                 jp->waited = 1;
4387                                 jp = jp->prev_job;
4388                         }
4389         /* man bash:
4390          * "When bash is waiting for an asynchronous command via
4391          * the wait builtin, the reception of a signal for which a trap
4392          * has been set will cause the wait builtin to return immediately
4393          * with an exit status greater than 128, immediately after which
4394          * the trap is executed."
4395          */
4396                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4397         /* if child sends us a signal *and immediately exits*,
4398          * dowait() returns pid > 0. Check this case,
4399          * not "if (dowait() < 0)"!
4400          */
4401                         if (pending_sig)
4402                                 goto sigout;
4403                 }
4404         }
4405
4406         retval = 127;
4407         do {
4408                 if (**argv != '%') {
4409                         pid_t pid = number(*argv);
4410                         job = curjob;
4411                         while (1) {
4412                                 if (!job)
4413                                         goto repeat;
4414                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4415                                         break;
4416                                 job = job->prev_job;
4417                         }
4418                 } else {
4419                         job = getjob(*argv, 0);
4420                 }
4421                 /* loop until process terminated or stopped */
4422                 while (job->state == JOBRUNNING) {
4423                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4424                         if (pending_sig)
4425                                 goto sigout;
4426                 }
4427                 job->waited = 1;
4428                 retval = getstatus(job);
4429  repeat: ;
4430         } while (*++argv);
4431
4432  ret:
4433         return retval;
4434  sigout:
4435         retval = 128 + pending_sig;
4436         return retval;
4437 }
4438
4439 static struct job *
4440 growjobtab(void)
4441 {
4442         size_t len;
4443         ptrdiff_t offset;
4444         struct job *jp, *jq;
4445
4446         len = njobs * sizeof(*jp);
4447         jq = jobtab;
4448         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4449
4450         offset = (char *)jp - (char *)jq;
4451         if (offset) {
4452                 /* Relocate pointers */
4453                 size_t l = len;
4454
4455                 jq = (struct job *)((char *)jq + l);
4456                 while (l) {
4457                         l -= sizeof(*jp);
4458                         jq--;
4459 #define joff(p) ((struct job *)((char *)(p) + l))
4460 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4461                         if (joff(jp)->ps == &jq->ps0)
4462                                 jmove(joff(jp)->ps);
4463                         if (joff(jp)->prev_job)
4464                                 jmove(joff(jp)->prev_job);
4465                 }
4466                 if (curjob)
4467                         jmove(curjob);
4468 #undef joff
4469 #undef jmove
4470         }
4471
4472         njobs += 4;
4473         jobtab = jp;
4474         jp = (struct job *)((char *)jp + len);
4475         jq = jp + 3;
4476         do {
4477                 jq->used = 0;
4478         } while (--jq >= jp);
4479         return jp;
4480 }
4481
4482 /*
4483  * Return a new job structure.
4484  * Called with interrupts off.
4485  */
4486 static struct job *
4487 makejob(/*union node *node,*/ int nprocs)
4488 {
4489         int i;
4490         struct job *jp;
4491
4492         for (i = njobs, jp = jobtab; ; jp++) {
4493                 if (--i < 0) {
4494                         jp = growjobtab();
4495                         break;
4496                 }
4497                 if (jp->used == 0)
4498                         break;
4499                 if (jp->state != JOBDONE || !jp->waited)
4500                         continue;
4501 #if JOBS
4502                 if (doing_jobctl)
4503                         continue;
4504 #endif
4505                 freejob(jp);
4506                 break;
4507         }
4508         memset(jp, 0, sizeof(*jp));
4509 #if JOBS
4510         /* jp->jobctl is a bitfield.
4511          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4512         if (doing_jobctl)
4513                 jp->jobctl = 1;
4514 #endif
4515         jp->prev_job = curjob;
4516         curjob = jp;
4517         jp->used = 1;
4518         jp->ps = &jp->ps0;
4519         if (nprocs > 1) {
4520                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4521         }
4522         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4523                                 jobno(jp)));
4524         return jp;
4525 }
4526
4527 #if JOBS
4528 /*
4529  * Return a string identifying a command (to be printed by the
4530  * jobs command).
4531  */
4532 static char *cmdnextc;
4533
4534 static void
4535 cmdputs(const char *s)
4536 {
4537         static const char vstype[VSTYPE + 1][3] = {
4538                 "", "}", "-", "+", "?", "=",
4539                 "%", "%%", "#", "##"
4540                 IF_BASH_SUBSTR(, ":")
4541                 IF_BASH_PATTERN_SUBST(, "/", "//")
4542         };
4543
4544         const char *p, *str;
4545         char cc[2];
4546         char *nextc;
4547         unsigned char c;
4548         unsigned char subtype = 0;
4549         int quoted = 0;
4550
4551         cc[1] = '\0';
4552         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4553         p = s;
4554         while ((c = *p++) != '\0') {
4555                 str = NULL;
4556                 switch (c) {
4557                 case CTLESC:
4558                         c = *p++;
4559                         break;
4560                 case CTLVAR:
4561                         subtype = *p++;
4562                         if ((subtype & VSTYPE) == VSLENGTH)
4563                                 str = "${#";
4564                         else
4565                                 str = "${";
4566                         goto dostr;
4567                 case CTLENDVAR:
4568                         str = "\"}" + !(quoted & 1);
4569                         quoted >>= 1;
4570                         subtype = 0;
4571                         goto dostr;
4572                 case CTLBACKQ:
4573                         str = "$(...)";
4574                         goto dostr;
4575 #if ENABLE_FEATURE_SH_MATH
4576                 case CTLARI:
4577                         str = "$((";
4578                         goto dostr;
4579                 case CTLENDARI:
4580                         str = "))";
4581                         goto dostr;
4582 #endif
4583                 case CTLQUOTEMARK:
4584                         quoted ^= 1;
4585                         c = '"';
4586                         break;
4587                 case '=':
4588                         if (subtype == 0)
4589                                 break;
4590                         if ((subtype & VSTYPE) != VSNORMAL)
4591                                 quoted <<= 1;
4592                         str = vstype[subtype & VSTYPE];
4593                         if (subtype & VSNUL)
4594                                 c = ':';
4595                         else
4596                                 goto checkstr;
4597                         break;
4598                 case '\'':
4599                 case '\\':
4600                 case '"':
4601                 case '$':
4602                         /* These can only happen inside quotes */
4603                         cc[0] = c;
4604                         str = cc;
4605                         c = '\\';
4606                         break;
4607                 default:
4608                         break;
4609                 }
4610                 USTPUTC(c, nextc);
4611  checkstr:
4612                 if (!str)
4613                         continue;
4614  dostr:
4615                 while ((c = *str++) != '\0') {
4616                         USTPUTC(c, nextc);
4617                 }
4618         } /* while *p++ not NUL */
4619
4620         if (quoted & 1) {
4621                 USTPUTC('"', nextc);
4622         }
4623         *nextc = 0;
4624         cmdnextc = nextc;
4625 }
4626
4627 /* cmdtxt() and cmdlist() call each other */
4628 static void cmdtxt(union node *n);
4629
4630 static void
4631 cmdlist(union node *np, int sep)
4632 {
4633         for (; np; np = np->narg.next) {
4634                 if (!sep)
4635                         cmdputs(" ");
4636                 cmdtxt(np);
4637                 if (sep && np->narg.next)
4638                         cmdputs(" ");
4639         }
4640 }
4641
4642 static void
4643 cmdtxt(union node *n)
4644 {
4645         union node *np;
4646         struct nodelist *lp;
4647         const char *p;
4648
4649         if (!n)
4650                 return;
4651         switch (n->type) {
4652         default:
4653 #if DEBUG
4654                 abort();
4655 #endif
4656         case NPIPE:
4657                 lp = n->npipe.cmdlist;
4658                 for (;;) {
4659                         cmdtxt(lp->n);
4660                         lp = lp->next;
4661                         if (!lp)
4662                                 break;
4663                         cmdputs(" | ");
4664                 }
4665                 break;
4666         case NSEMI:
4667                 p = "; ";
4668                 goto binop;
4669         case NAND:
4670                 p = " && ";
4671                 goto binop;
4672         case NOR:
4673                 p = " || ";
4674  binop:
4675                 cmdtxt(n->nbinary.ch1);
4676                 cmdputs(p);
4677                 n = n->nbinary.ch2;
4678                 goto donode;
4679         case NREDIR:
4680         case NBACKGND:
4681                 n = n->nredir.n;
4682                 goto donode;
4683         case NNOT:
4684                 cmdputs("!");
4685                 n = n->nnot.com;
4686  donode:
4687                 cmdtxt(n);
4688                 break;
4689         case NIF:
4690                 cmdputs("if ");
4691                 cmdtxt(n->nif.test);
4692                 cmdputs("; then ");
4693                 if (n->nif.elsepart) {
4694                         cmdtxt(n->nif.ifpart);
4695                         cmdputs("; else ");
4696                         n = n->nif.elsepart;
4697                 } else {
4698                         n = n->nif.ifpart;
4699                 }
4700                 p = "; fi";
4701                 goto dotail;
4702         case NSUBSHELL:
4703                 cmdputs("(");
4704                 n = n->nredir.n;
4705                 p = ")";
4706                 goto dotail;
4707         case NWHILE:
4708                 p = "while ";
4709                 goto until;
4710         case NUNTIL:
4711                 p = "until ";
4712  until:
4713                 cmdputs(p);
4714                 cmdtxt(n->nbinary.ch1);
4715                 n = n->nbinary.ch2;
4716                 p = "; done";
4717  dodo:
4718                 cmdputs("; do ");
4719  dotail:
4720                 cmdtxt(n);
4721                 goto dotail2;
4722         case NFOR:
4723                 cmdputs("for ");
4724                 cmdputs(n->nfor.var);
4725                 cmdputs(" in ");
4726                 cmdlist(n->nfor.args, 1);
4727                 n = n->nfor.body;
4728                 p = "; done";
4729                 goto dodo;
4730         case NDEFUN:
4731                 cmdputs(n->narg.text);
4732                 p = "() { ... }";
4733                 goto dotail2;
4734         case NCMD:
4735                 cmdlist(n->ncmd.args, 1);
4736                 cmdlist(n->ncmd.redirect, 0);
4737                 break;
4738         case NARG:
4739                 p = n->narg.text;
4740  dotail2:
4741                 cmdputs(p);
4742                 break;
4743         case NHERE:
4744         case NXHERE:
4745                 p = "<<...";
4746                 goto dotail2;
4747         case NCASE:
4748                 cmdputs("case ");
4749                 cmdputs(n->ncase.expr->narg.text);
4750                 cmdputs(" in ");
4751                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4752                         cmdtxt(np->nclist.pattern);
4753                         cmdputs(") ");
4754                         cmdtxt(np->nclist.body);
4755                         cmdputs(";; ");
4756                 }
4757                 p = "esac";
4758                 goto dotail2;
4759         case NTO:
4760                 p = ">";
4761                 goto redir;
4762         case NCLOBBER:
4763                 p = ">|";
4764                 goto redir;
4765         case NAPPEND:
4766                 p = ">>";
4767                 goto redir;
4768 #if BASH_REDIR_OUTPUT
4769         case NTO2:
4770 #endif
4771         case NTOFD:
4772                 p = ">&";
4773                 goto redir;
4774         case NFROM:
4775                 p = "<";
4776                 goto redir;
4777         case NFROMFD:
4778                 p = "<&";
4779                 goto redir;
4780         case NFROMTO:
4781                 p = "<>";
4782  redir:
4783                 cmdputs(utoa(n->nfile.fd));
4784                 cmdputs(p);
4785                 if (n->type == NTOFD || n->type == NFROMFD) {
4786                         cmdputs(utoa(n->ndup.dupfd));
4787                         break;
4788                 }
4789                 n = n->nfile.fname;
4790                 goto donode;
4791         }
4792 }
4793
4794 static char *
4795 commandtext(union node *n)
4796 {
4797         char *name;
4798
4799         STARTSTACKSTR(cmdnextc);
4800         cmdtxt(n);
4801         name = stackblock();
4802         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4803         return ckstrdup(name);
4804 }
4805 #endif /* JOBS */
4806
4807 /*
4808  * Fork off a subshell.  If we are doing job control, give the subshell its
4809  * own process group.  Jp is a job structure that the job is to be added to.
4810  * N is the command that will be evaluated by the child.  Both jp and n may
4811  * be NULL.  The mode parameter can be one of the following:
4812  *      FORK_FG - Fork off a foreground process.
4813  *      FORK_BG - Fork off a background process.
4814  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4815  *                   process group even if job control is on.
4816  *
4817  * When job control is turned off, background processes have their standard
4818  * input redirected to /dev/null (except for the second and later processes
4819  * in a pipeline).
4820  *
4821  * Called with interrupts off.
4822  */
4823 /*
4824  * Clear traps on a fork.
4825  */
4826 static void
4827 clear_traps(void)
4828 {
4829         char **tp;
4830
4831         INT_OFF;
4832         for (tp = trap; tp < &trap[NSIG]; tp++) {
4833                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4834                         if (trap_ptr == trap)
4835                                 free(*tp);
4836                         /* else: it "belongs" to trap_ptr vector, don't free */
4837                         *tp = NULL;
4838                         if ((tp - trap) != 0)
4839                                 setsignal(tp - trap);
4840                 }
4841         }
4842         may_have_traps = 0;
4843         INT_ON;
4844 }
4845
4846 /* Lives far away from here, needed for forkchild */
4847 static void closescript(void);
4848
4849 /* Called after fork(), in child */
4850 /* jp and n are NULL when called by openhere() for heredoc support */
4851 static NOINLINE void
4852 forkchild(struct job *jp, union node *n, int mode)
4853 {
4854         int oldlvl;
4855
4856         TRACE(("Child shell %d\n", getpid()));
4857         oldlvl = shlvl;
4858         shlvl++;
4859
4860         /* man bash: "Non-builtin commands run by bash have signal handlers
4861          * set to the values inherited by the shell from its parent".
4862          * Do we do it correctly? */
4863
4864         closescript();
4865
4866         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4867          && n && n->type == NCMD        /* is it single cmd? */
4868         /* && n->ncmd.args->type == NARG - always true? */
4869          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4870          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4871         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4872         ) {
4873                 TRACE(("Trap hack\n"));
4874                 /* Awful hack for `trap` or $(trap).
4875                  *
4876                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4877                  * contains an example where "trap" is executed in a subshell:
4878                  *
4879                  * save_traps=$(trap)
4880                  * ...
4881                  * eval "$save_traps"
4882                  *
4883                  * Standard does not say that "trap" in subshell shall print
4884                  * parent shell's traps. It only says that its output
4885                  * must have suitable form, but then, in the above example
4886                  * (which is not supposed to be normative), it implies that.
4887                  *
4888                  * bash (and probably other shell) does implement it
4889                  * (traps are reset to defaults, but "trap" still shows them),
4890                  * but as a result, "trap" logic is hopelessly messed up:
4891                  *
4892                  * # trap
4893                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4894                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4895                  * # true | trap   <--- trap is in subshell - no output (ditto)
4896                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4897                  * trap -- 'echo Ho' SIGWINCH
4898                  * # echo `(trap)`         <--- in subshell in subshell - output
4899                  * trap -- 'echo Ho' SIGWINCH
4900                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4901                  * trap -- 'echo Ho' SIGWINCH
4902                  *
4903                  * The rules when to forget and when to not forget traps
4904                  * get really complex and nonsensical.
4905                  *
4906                  * Our solution: ONLY bare $(trap) or `trap` is special.
4907                  */
4908                 /* Save trap handler strings for trap builtin to print */
4909                 trap_ptr = xmemdup(trap, sizeof(trap));
4910                 /* Fall through into clearing traps */
4911         }
4912         clear_traps();
4913 #if JOBS
4914         /* do job control only in root shell */
4915         doing_jobctl = 0;
4916         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4917                 pid_t pgrp;
4918
4919                 if (jp->nprocs == 0)
4920                         pgrp = getpid();
4921                 else
4922                         pgrp = jp->ps[0].ps_pid;
4923                 /* this can fail because we are doing it in the parent also */
4924                 setpgid(0, pgrp);
4925                 if (mode == FORK_FG)
4926                         xtcsetpgrp(ttyfd, pgrp);
4927                 setsignal(SIGTSTP);
4928                 setsignal(SIGTTOU);
4929         } else
4930 #endif
4931         if (mode == FORK_BG) {
4932                 /* man bash: "When job control is not in effect,
4933                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4934                 ignoresig(SIGINT);
4935                 ignoresig(SIGQUIT);
4936                 if (jp->nprocs == 0) {
4937                         close(0);
4938                         if (open(bb_dev_null, O_RDONLY) != 0)
4939                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4940                 }
4941         }
4942         if (oldlvl == 0) {
4943                 if (iflag) { /* why if iflag only? */
4944                         setsignal(SIGINT);
4945                         setsignal(SIGTERM);
4946                 }
4947                 /* man bash:
4948                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4949                  * commands run by bash have signal handlers
4950                  * set to the values inherited by the shell
4951                  * from its parent".
4952                  * Take care of the second rule: */
4953                 setsignal(SIGQUIT);
4954         }
4955 #if JOBS
4956         if (n && n->type == NCMD
4957          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4958         ) {
4959                 TRACE(("Job hack\n"));
4960                 /* "jobs": we do not want to clear job list for it,
4961                  * instead we remove only _its_ own_ job from job list.
4962                  * This makes "jobs .... | cat" more useful.
4963                  */
4964                 freejob(curjob);
4965                 return;
4966         }
4967 #endif
4968         for (jp = curjob; jp; jp = jp->prev_job)
4969                 freejob(jp);
4970         jobless = 0;
4971 }
4972
4973 /* Called after fork(), in parent */
4974 #if !JOBS
4975 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4976 #endif
4977 static void
4978 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4979 {
4980         TRACE(("In parent shell: child = %d\n", pid));
4981         if (!jp) {
4982                 /* jp is NULL when called by openhere() for heredoc support */
4983                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4984                         continue;
4985                 jobless++;
4986                 return;
4987         }
4988 #if JOBS
4989         if (mode != FORK_NOJOB && jp->jobctl) {
4990                 int pgrp;
4991
4992                 if (jp->nprocs == 0)
4993                         pgrp = pid;
4994                 else
4995                         pgrp = jp->ps[0].ps_pid;
4996                 /* This can fail because we are doing it in the child also */
4997                 setpgid(pid, pgrp);
4998         }
4999 #endif
5000         if (mode == FORK_BG) {
5001                 backgndpid = pid;               /* set $! */
5002                 set_curjob(jp, CUR_RUNNING);
5003         }
5004         if (jp) {
5005                 struct procstat *ps = &jp->ps[jp->nprocs++];
5006                 ps->ps_pid = pid;
5007                 ps->ps_status = -1;
5008                 ps->ps_cmd = nullstr;
5009 #if JOBS
5010                 if (doing_jobctl && n)
5011                         ps->ps_cmd = commandtext(n);
5012 #endif
5013         }
5014 }
5015
5016 /* jp and n are NULL when called by openhere() for heredoc support */
5017 static int
5018 forkshell(struct job *jp, union node *n, int mode)
5019 {
5020         int pid;
5021
5022         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5023         pid = fork();
5024         if (pid < 0) {
5025                 TRACE(("Fork failed, errno=%d", errno));
5026                 if (jp)
5027                         freejob(jp);
5028                 ash_msg_and_raise_error("can't fork");
5029         }
5030         if (pid == 0) {
5031                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5032                 forkchild(jp, n, mode);
5033         } else {
5034                 forkparent(jp, n, mode, pid);
5035         }
5036         return pid;
5037 }
5038
5039 /*
5040  * Wait for job to finish.
5041  *
5042  * Under job control we have the problem that while a child process
5043  * is running interrupts generated by the user are sent to the child
5044  * but not to the shell.  This means that an infinite loop started by
5045  * an interactive user may be hard to kill.  With job control turned off,
5046  * an interactive user may place an interactive program inside a loop.
5047  * If the interactive program catches interrupts, the user doesn't want
5048  * these interrupts to also abort the loop.  The approach we take here
5049  * is to have the shell ignore interrupt signals while waiting for a
5050  * foreground process to terminate, and then send itself an interrupt
5051  * signal if the child process was terminated by an interrupt signal.
5052  * Unfortunately, some programs want to do a bit of cleanup and then
5053  * exit on interrupt; unless these processes terminate themselves by
5054  * sending a signal to themselves (instead of calling exit) they will
5055  * confuse this approach.
5056  *
5057  * Called with interrupts off.
5058  */
5059 static int
5060 waitforjob(struct job *jp)
5061 {
5062         int st;
5063
5064         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5065
5066         INT_OFF;
5067         while (jp->state == JOBRUNNING) {
5068                 /* In non-interactive shells, we _can_ get
5069                  * a keyboard signal here and be EINTRed,
5070                  * but we just loop back, waiting for command to complete.
5071                  *
5072                  * man bash:
5073                  * "If bash is waiting for a command to complete and receives
5074                  * a signal for which a trap has been set, the trap
5075                  * will not be executed until the command completes."
5076                  *
5077                  * Reality is that even if trap is not set, bash
5078                  * will not act on the signal until command completes.
5079                  * Try this. sleep5intoff.c:
5080                  * #include <signal.h>
5081                  * #include <unistd.h>
5082                  * int main() {
5083                  *         sigset_t set;
5084                  *         sigemptyset(&set);
5085                  *         sigaddset(&set, SIGINT);
5086                  *         sigaddset(&set, SIGQUIT);
5087                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5088                  *         sleep(5);
5089                  *         return 0;
5090                  * }
5091                  * $ bash -c './sleep5intoff; echo hi'
5092                  * ^C^C^C^C <--- pressing ^C once a second
5093                  * $ _
5094                  * $ bash -c './sleep5intoff; echo hi'
5095                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5096                  * $ _
5097                  */
5098                 dowait(DOWAIT_BLOCK, jp);
5099         }
5100         INT_ON;
5101
5102         st = getstatus(jp);
5103 #if JOBS
5104         if (jp->jobctl) {
5105                 xtcsetpgrp(ttyfd, rootpid);
5106                 restore_tty_if_stopped_or_signaled(jp);
5107
5108                 /*
5109                  * This is truly gross.
5110                  * If we're doing job control, then we did a TIOCSPGRP which
5111                  * caused us (the shell) to no longer be in the controlling
5112                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5113                  * intuit from the subprocess exit status whether a SIGINT
5114                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5115                  */
5116                 if (jp->sigint) /* TODO: do the same with all signals */
5117                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5118         }
5119         if (jp->state == JOBDONE)
5120 #endif
5121                 freejob(jp);
5122         return st;
5123 }
5124
5125 /*
5126  * return 1 if there are stopped jobs, otherwise 0
5127  */
5128 static int
5129 stoppedjobs(void)
5130 {
5131         struct job *jp;
5132         int retval;
5133
5134         retval = 0;
5135         if (job_warning)
5136                 goto out;
5137         jp = curjob;
5138         if (jp && jp->state == JOBSTOPPED) {
5139                 out2str("You have stopped jobs.\n");
5140                 job_warning = 2;
5141                 retval++;
5142         }
5143  out:
5144         return retval;
5145 }
5146
5147
5148 /*
5149  * Code for dealing with input/output redirection.
5150  */
5151
5152 #undef EMPTY
5153 #undef CLOSED
5154 #define EMPTY -2                /* marks an unused slot in redirtab */
5155 #define CLOSED -3               /* marks a slot of previously-closed fd */
5156
5157 /*
5158  * Open a file in noclobber mode.
5159  * The code was copied from bash.
5160  */
5161 static int
5162 noclobberopen(const char *fname)
5163 {
5164         int r, fd;
5165         struct stat finfo, finfo2;
5166
5167         /*
5168          * If the file exists and is a regular file, return an error
5169          * immediately.
5170          */
5171         r = stat(fname, &finfo);
5172         if (r == 0 && S_ISREG(finfo.st_mode)) {
5173                 errno = EEXIST;
5174                 return -1;
5175         }
5176
5177         /*
5178          * If the file was not present (r != 0), make sure we open it
5179          * exclusively so that if it is created before we open it, our open
5180          * will fail.  Make sure that we do not truncate an existing file.
5181          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5182          * file was not a regular file, we leave O_EXCL off.
5183          */
5184         if (r != 0)
5185                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5186         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5187
5188         /* If the open failed, return the file descriptor right away. */
5189         if (fd < 0)
5190                 return fd;
5191
5192         /*
5193          * OK, the open succeeded, but the file may have been changed from a
5194          * non-regular file to a regular file between the stat and the open.
5195          * We are assuming that the O_EXCL open handles the case where FILENAME
5196          * did not exist and is symlinked to an existing file between the stat
5197          * and open.
5198          */
5199
5200         /*
5201          * If we can open it and fstat the file descriptor, and neither check
5202          * revealed that it was a regular file, and the file has not been
5203          * replaced, return the file descriptor.
5204          */
5205         if (fstat(fd, &finfo2) == 0
5206          && !S_ISREG(finfo2.st_mode)
5207          && finfo.st_dev == finfo2.st_dev
5208          && finfo.st_ino == finfo2.st_ino
5209         ) {
5210                 return fd;
5211         }
5212
5213         /* The file has been replaced.  badness. */
5214         close(fd);
5215         errno = EEXIST;
5216         return -1;
5217 }
5218
5219 /*
5220  * Handle here documents.  Normally we fork off a process to write the
5221  * data to a pipe.  If the document is short, we can stuff the data in
5222  * the pipe without forking.
5223  */
5224 /* openhere needs this forward reference */
5225 static void expandhere(union node *arg, int fd);
5226 static int
5227 openhere(union node *redir)
5228 {
5229         int pip[2];
5230         size_t len = 0;
5231
5232         if (pipe(pip) < 0)
5233                 ash_msg_and_raise_error("pipe call failed");
5234         if (redir->type == NHERE) {
5235                 len = strlen(redir->nhere.doc->narg.text);
5236                 if (len <= PIPE_BUF) {
5237                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5238                         goto out;
5239                 }
5240         }
5241         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5242                 /* child */
5243                 close(pip[0]);
5244                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5245                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5246                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5247                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5248                 signal(SIGPIPE, SIG_DFL);
5249                 if (redir->type == NHERE)
5250                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5251                 else /* NXHERE */
5252                         expandhere(redir->nhere.doc, pip[1]);
5253                 _exit(EXIT_SUCCESS);
5254         }
5255  out:
5256         close(pip[1]);
5257         return pip[0];
5258 }
5259
5260 static int
5261 openredirect(union node *redir)
5262 {
5263         char *fname;
5264         int f;
5265
5266         switch (redir->nfile.type) {
5267 /* Can't happen, our single caller does this itself */
5268 //      case NTOFD:
5269 //      case NFROMFD:
5270 //              return -1;
5271         case NHERE:
5272         case NXHERE:
5273                 return openhere(redir);
5274         }
5275
5276         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5277          * allocated space. Do it only when we know it is safe.
5278          */
5279         fname = redir->nfile.expfname;
5280
5281         switch (redir->nfile.type) {
5282         default:
5283 #if DEBUG
5284                 abort();
5285 #endif
5286         case NFROM:
5287                 f = open(fname, O_RDONLY);
5288                 if (f < 0)
5289                         goto eopen;
5290                 break;
5291         case NFROMTO:
5292                 f = open(fname, O_RDWR|O_CREAT, 0666);
5293                 if (f < 0)
5294                         goto ecreate;
5295                 break;
5296         case NTO:
5297 #if BASH_REDIR_OUTPUT
5298         case NTO2:
5299 #endif
5300                 /* Take care of noclobber mode. */
5301                 if (Cflag) {
5302                         f = noclobberopen(fname);
5303                         if (f < 0)
5304                                 goto ecreate;
5305                         break;
5306                 }
5307                 /* FALLTHROUGH */
5308         case NCLOBBER:
5309                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5310                 if (f < 0)
5311                         goto ecreate;
5312                 break;
5313         case NAPPEND:
5314                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5315                 if (f < 0)
5316                         goto ecreate;
5317                 break;
5318         }
5319
5320         return f;
5321  ecreate:
5322         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5323  eopen:
5324         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5325 }
5326
5327 /*
5328  * Copy a file descriptor to be >= 10. Throws exception on error.
5329  */
5330 static int
5331 savefd(int from)
5332 {
5333         int newfd;
5334         int err;
5335
5336         newfd = fcntl(from, F_DUPFD, 10);
5337         err = newfd < 0 ? errno : 0;
5338         if (err != EBADF) {
5339                 if (err)
5340                         ash_msg_and_raise_error("%d: %m", from);
5341                 close(from);
5342                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5343         }
5344
5345         return newfd;
5346 }
5347 static int
5348 dup2_or_raise(int from, int to)
5349 {
5350         int newfd;
5351
5352         newfd = (from != to) ? dup2(from, to) : to;
5353         if (newfd < 0) {
5354                 /* Happens when source fd is not open: try "echo >&99" */
5355                 ash_msg_and_raise_error("%d: %m", from);
5356         }
5357         return newfd;
5358 }
5359
5360 /* Struct def and variable are moved down to the first usage site */
5361 struct two_fd_t {
5362         int orig, copy;
5363 };
5364 struct redirtab {
5365         struct redirtab *next;
5366         int pair_count;
5367         struct two_fd_t two_fd[];
5368 };
5369 #define redirlist (G_var.redirlist)
5370 enum {
5371         COPYFD_RESTORE = (int)~(INT_MAX),
5372 };
5373
5374 static int
5375 need_to_remember(struct redirtab *rp, int fd)
5376 {
5377         int i;
5378
5379         if (!rp) /* remembering was not requested */
5380                 return 0;
5381
5382         for (i = 0; i < rp->pair_count; i++) {
5383                 if (rp->two_fd[i].orig == fd) {
5384                         /* already remembered */
5385                         return 0;
5386                 }
5387         }
5388         return 1;
5389 }
5390
5391 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5392 static int
5393 is_hidden_fd(struct redirtab *rp, int fd)
5394 {
5395         int i;
5396         struct parsefile *pf;
5397
5398         if (fd == -1)
5399                 return 0;
5400         /* Check open scripts' fds */
5401         pf = g_parsefile;
5402         while (pf) {
5403                 /* We skip pf_fd == 0 case because of the following case:
5404                  * $ ash  # running ash interactively
5405                  * $ . ./script.sh
5406                  * and in script.sh: "exec 9>&0".
5407                  * Even though top-level pf_fd _is_ 0,
5408                  * it's still ok to use it: "read" builtin uses it,
5409                  * why should we cripple "exec" builtin?
5410                  */
5411                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5412                         return 1;
5413                 }
5414                 pf = pf->prev;
5415         }
5416
5417         if (!rp)
5418                 return 0;
5419         /* Check saved fds of redirects */
5420         fd |= COPYFD_RESTORE;
5421         for (i = 0; i < rp->pair_count; i++) {
5422                 if (rp->two_fd[i].copy == fd) {
5423                         return 1;
5424                 }
5425         }
5426         return 0;
5427 }
5428
5429 /*
5430  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5431  * old file descriptors are stashed away so that the redirection can be
5432  * undone by calling popredir.
5433  */
5434 /* flags passed to redirect */
5435 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5436 #define REDIR_SAVEFD2 03        /* set preverrout */
5437 static void
5438 redirect(union node *redir, int flags)
5439 {
5440         struct redirtab *sv;
5441         int sv_pos;
5442         int i;
5443         int fd;
5444         int newfd;
5445         int copied_fd2 = -1;
5446
5447         if (!redir) {
5448                 return;
5449         }
5450
5451         sv = NULL;
5452         sv_pos = 0;
5453         INT_OFF;
5454         if (flags & REDIR_PUSH) {
5455                 union node *tmp = redir;
5456                 do {
5457                         sv_pos++;
5458 #if BASH_REDIR_OUTPUT
5459                         if (tmp->nfile.type == NTO2)
5460                                 sv_pos++;
5461 #endif
5462                         tmp = tmp->nfile.next;
5463                 } while (tmp);
5464                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5465                 sv->next = redirlist;
5466                 sv->pair_count = sv_pos;
5467                 redirlist = sv;
5468                 while (sv_pos > 0) {
5469                         sv_pos--;
5470                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5471                 }
5472         }
5473
5474         do {
5475                 int right_fd = -1;
5476                 fd = redir->nfile.fd;
5477                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5478                         right_fd = redir->ndup.dupfd;
5479                         //bb_error_msg("doing %d > %d", fd, right_fd);
5480                         /* redirect from/to same file descriptor? */
5481                         if (right_fd == fd)
5482                                 continue;
5483                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5484                         if (is_hidden_fd(sv, right_fd)) {
5485                                 errno = EBADF; /* as if it is closed */
5486                                 ash_msg_and_raise_error("%d: %m", right_fd);
5487                         }
5488                         newfd = -1;
5489                 } else {
5490                         newfd = openredirect(redir); /* always >= 0 */
5491                         if (fd == newfd) {
5492                                 /* Descriptor wasn't open before redirect.
5493                                  * Mark it for close in the future */
5494                                 if (need_to_remember(sv, fd)) {
5495                                         goto remember_to_close;
5496                                 }
5497                                 continue;
5498                         }
5499                 }
5500 #if BASH_REDIR_OUTPUT
5501  redirect_more:
5502 #endif
5503                 if (need_to_remember(sv, fd)) {
5504                         /* Copy old descriptor */
5505                         /* Careful to not accidentally "save"
5506                          * to the same fd as right side fd in N>&M */
5507                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5508 #if defined(F_DUPFD_CLOEXEC)
5509                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5510 #else
5511                         i = fcntl(fd, F_DUPFD, minfd);
5512 #endif
5513                         if (i == -1) {
5514                                 i = errno;
5515                                 if (i != EBADF) {
5516                                         /* Strange error (e.g. "too many files" EMFILE?) */
5517                                         if (newfd >= 0)
5518                                                 close(newfd);
5519                                         errno = i;
5520                                         ash_msg_and_raise_error("%d: %m", fd);
5521                                         /* NOTREACHED */
5522                                 }
5523                                 /* EBADF: it is not open - good, remember to close it */
5524  remember_to_close:
5525                                 i = CLOSED;
5526                         } else { /* fd is open, save its copy */
5527 #if !defined(F_DUPFD_CLOEXEC)
5528                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5529 #endif
5530                                 /* "exec fd>&-" should not close fds
5531                                  * which point to script file(s).
5532                                  * Force them to be restored afterwards */
5533                                 if (is_hidden_fd(sv, fd))
5534                                         i |= COPYFD_RESTORE;
5535                         }
5536                         if (fd == 2)
5537                                 copied_fd2 = i;
5538                         sv->two_fd[sv_pos].orig = fd;
5539                         sv->two_fd[sv_pos].copy = i;
5540                         sv_pos++;
5541                 }
5542                 if (newfd < 0) {
5543                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5544                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5545                                 /* Don't want to trigger debugging */
5546                                 if (fd != -1)
5547                                         close(fd);
5548                         } else {
5549                                 dup2_or_raise(redir->ndup.dupfd, fd);
5550                         }
5551                 } else if (fd != newfd) { /* move newfd to fd */
5552                         dup2_or_raise(newfd, fd);
5553 #if BASH_REDIR_OUTPUT
5554                         if (!(redir->nfile.type == NTO2 && fd == 2))
5555 #endif
5556                                 close(newfd);
5557                 }
5558 #if BASH_REDIR_OUTPUT
5559                 if (redir->nfile.type == NTO2 && fd == 1) {
5560                         /* We already redirected it to fd 1, now copy it to 2 */
5561                         newfd = 1;
5562                         fd = 2;
5563                         goto redirect_more;
5564                 }
5565 #endif
5566         } while ((redir = redir->nfile.next) != NULL);
5567
5568         INT_ON;
5569         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5570                 preverrout_fd = copied_fd2;
5571 }
5572
5573 /*
5574  * Undo the effects of the last redirection.
5575  */
5576 static void
5577 popredir(int drop, int restore)
5578 {
5579         struct redirtab *rp;
5580         int i;
5581
5582         if (redirlist == NULL)
5583                 return;
5584         INT_OFF;
5585         rp = redirlist;
5586         for (i = 0; i < rp->pair_count; i++) {
5587                 int fd = rp->two_fd[i].orig;
5588                 int copy = rp->two_fd[i].copy;
5589                 if (copy == CLOSED) {
5590                         if (!drop)
5591                                 close(fd);
5592                         continue;
5593                 }
5594                 if (copy != EMPTY) {
5595                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5596                                 copy &= ~COPYFD_RESTORE;
5597                                 /*close(fd);*/
5598                                 dup2_or_raise(copy, fd);
5599                         }
5600                         close(copy & ~COPYFD_RESTORE);
5601                 }
5602         }
5603         redirlist = rp->next;
5604         free(rp);
5605         INT_ON;
5606 }
5607
5608 /*
5609  * Undo all redirections.  Called on error or interrupt.
5610  */
5611
5612 static int
5613 redirectsafe(union node *redir, int flags)
5614 {
5615         int err;
5616         volatile int saveint;
5617         struct jmploc *volatile savehandler = exception_handler;
5618         struct jmploc jmploc;
5619
5620         SAVE_INT(saveint);
5621         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5622         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5623         if (!err) {
5624                 exception_handler = &jmploc;
5625                 redirect(redir, flags);
5626         }
5627         exception_handler = savehandler;
5628         if (err && exception_type != EXERROR)
5629                 longjmp(exception_handler->loc, 1);
5630         RESTORE_INT(saveint);
5631         return err;
5632 }
5633
5634
5635 /* ============ Routines to expand arguments to commands
5636  *
5637  * We have to deal with backquotes, shell variables, and file metacharacters.
5638  */
5639
5640 #if ENABLE_FEATURE_SH_MATH
5641 static arith_t
5642 ash_arith(const char *s)
5643 {
5644         arith_state_t math_state;
5645         arith_t result;
5646
5647         math_state.lookupvar = lookupvar;
5648         math_state.setvar    = setvar0;
5649         //math_state.endofname = endofname;
5650
5651         INT_OFF;
5652         result = arith(&math_state, s);
5653         if (math_state.errmsg)
5654                 ash_msg_and_raise_error(math_state.errmsg);
5655         INT_ON;
5656
5657         return result;
5658 }
5659 #endif
5660
5661 /*
5662  * expandarg flags
5663  */
5664 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5665 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5666 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5667 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5668 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5669  * POSIX says for this case:
5670  *  Pathname expansion shall not be performed on the word by a
5671  *  non-interactive shell; an interactive shell may perform it, but shall
5672  *  do so only when the expansion would result in one word.
5673  * Currently, our code complies to the above rule by never globbing
5674  * redirection filenames.
5675  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5676  * (this means that on a typical Linux distro, bash almost always
5677  * performs globbing, and thus diverges from what we do).
5678  */
5679 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5680 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5681 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5682 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5683 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5684 /*
5685  * rmescape() flags
5686  */
5687 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5688 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5689 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5690 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5691 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5692
5693 /* Add CTLESC when necessary. */
5694 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5695 /* Do not skip NUL characters. */
5696 #define QUOTES_KEEPNUL EXP_TILDE
5697
5698 /*
5699  * Structure specifying which parts of the string should be searched
5700  * for IFS characters.
5701  */
5702 struct ifsregion {
5703         struct ifsregion *next; /* next region in list */
5704         int begoff;             /* offset of start of region */
5705         int endoff;             /* offset of end of region */
5706         int nulonly;            /* search for nul bytes only */
5707 };
5708
5709 struct arglist {
5710         struct strlist *list;
5711         struct strlist **lastp;
5712 };
5713
5714 /* output of current string */
5715 static char *expdest;
5716 /* list of back quote expressions */
5717 static struct nodelist *argbackq;
5718 /* first struct in list of ifs regions */
5719 static struct ifsregion ifsfirst;
5720 /* last struct in list */
5721 static struct ifsregion *ifslastp;
5722 /* holds expanded arg list */
5723 static struct arglist exparg;
5724
5725 /*
5726  * Our own itoa().
5727  */
5728 #if !ENABLE_FEATURE_SH_MATH
5729 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5730 typedef long arith_t;
5731 # define ARITH_FMT "%ld"
5732 #endif
5733 static int
5734 cvtnum(arith_t num)
5735 {
5736         int len;
5737
5738         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5739         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5740         STADJUST(len, expdest);
5741         return len;
5742 }
5743
5744 /*
5745  * Break the argument string into pieces based upon IFS and add the
5746  * strings to the argument list.  The regions of the string to be
5747  * searched for IFS characters have been stored by recordregion.
5748  */
5749 static void
5750 ifsbreakup(char *string, struct arglist *arglist)
5751 {
5752         struct ifsregion *ifsp;
5753         struct strlist *sp;
5754         char *start;
5755         char *p;
5756         char *q;
5757         const char *ifs, *realifs;
5758         int ifsspc;
5759         int nulonly;
5760
5761         start = string;
5762         if (ifslastp != NULL) {
5763                 ifsspc = 0;
5764                 nulonly = 0;
5765                 realifs = ifsset() ? ifsval() : defifs;
5766                 ifsp = &ifsfirst;
5767                 do {
5768                         p = string + ifsp->begoff;
5769                         nulonly = ifsp->nulonly;
5770                         ifs = nulonly ? nullstr : realifs;
5771                         ifsspc = 0;
5772                         while (p < string + ifsp->endoff) {
5773                                 q = p;
5774                                 if ((unsigned char)*p == CTLESC)
5775                                         p++;
5776                                 if (!strchr(ifs, *p)) {
5777                                         p++;
5778                                         continue;
5779                                 }
5780                                 if (!nulonly)
5781                                         ifsspc = (strchr(defifs, *p) != NULL);
5782                                 /* Ignore IFS whitespace at start */
5783                                 if (q == start && ifsspc) {
5784                                         p++;
5785                                         start = p;
5786                                         continue;
5787                                 }
5788                                 *q = '\0';
5789                                 sp = stzalloc(sizeof(*sp));
5790                                 sp->text = start;
5791                                 *arglist->lastp = sp;
5792                                 arglist->lastp = &sp->next;
5793                                 p++;
5794                                 if (!nulonly) {
5795                                         for (;;) {
5796                                                 if (p >= string + ifsp->endoff) {
5797                                                         break;
5798                                                 }
5799                                                 q = p;
5800                                                 if ((unsigned char)*p == CTLESC)
5801                                                         p++;
5802                                                 if (strchr(ifs, *p) == NULL) {
5803                                                         p = q;
5804                                                         break;
5805                                                 }
5806                                                 if (strchr(defifs, *p) == NULL) {
5807                                                         if (ifsspc) {
5808                                                                 p++;
5809                                                                 ifsspc = 0;
5810                                                         } else {
5811                                                                 p = q;
5812                                                                 break;
5813                                                         }
5814                                                 } else
5815                                                         p++;
5816                                         }
5817                                 }
5818                                 start = p;
5819                         } /* while */
5820                         ifsp = ifsp->next;
5821                 } while (ifsp != NULL);
5822                 if (nulonly)
5823                         goto add;
5824         }
5825
5826         if (!*start)
5827                 return;
5828
5829  add:
5830         sp = stzalloc(sizeof(*sp));
5831         sp->text = start;
5832         *arglist->lastp = sp;
5833         arglist->lastp = &sp->next;
5834 }
5835
5836 static void
5837 ifsfree(void)
5838 {
5839         struct ifsregion *p = ifsfirst.next;
5840
5841         if (!p)
5842                 goto out;
5843
5844         INT_OFF;
5845         do {
5846                 struct ifsregion *ifsp;
5847                 ifsp = p->next;
5848                 free(p);
5849                 p = ifsp;
5850         } while (p);
5851         ifsfirst.next = NULL;
5852         INT_ON;
5853  out:
5854         ifslastp = NULL;
5855 }
5856
5857 static size_t
5858 esclen(const char *start, const char *p)
5859 {
5860         size_t esc = 0;
5861
5862         while (p > start && (unsigned char)*--p == CTLESC) {
5863                 esc++;
5864         }
5865         return esc;
5866 }
5867
5868 /*
5869  * Remove any CTLESC characters from a string.
5870  */
5871 static char *
5872 rmescapes(char *str, int flag)
5873 {
5874         static const char qchars[] ALIGN1 = {
5875                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5876
5877         char *p, *q, *r;
5878         unsigned inquotes;
5879         unsigned protect_against_glob;
5880         unsigned globbing;
5881         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5882
5883         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5884         if (!p)
5885                 return str;
5886
5887         q = p;
5888         r = str;
5889         if (flag & RMESCAPE_ALLOC) {
5890                 size_t len = p - str;
5891                 size_t fulllen = len + strlen(p) + 1;
5892
5893                 if (flag & RMESCAPE_GROW) {
5894                         int strloc = str - (char *)stackblock();
5895                         r = makestrspace(fulllen, expdest);
5896                         /* p and str may be invalidated by makestrspace */
5897                         str = (char *)stackblock() + strloc;
5898                         p = str + len;
5899                 } else if (flag & RMESCAPE_HEAP) {
5900                         r = ckmalloc(fulllen);
5901                 } else {
5902                         r = stalloc(fulllen);
5903                 }
5904                 q = r;
5905                 if (len > 0) {
5906                         q = (char *)memcpy(q, str, len) + len;
5907                 }
5908         }
5909
5910         inquotes = 0;
5911         globbing = flag & RMESCAPE_GLOB;
5912         protect_against_glob = globbing;
5913         while (*p) {
5914                 if ((unsigned char)*p == CTLQUOTEMARK) {
5915 // Note: both inquotes and protect_against_glob only affect whether
5916 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5917                         inquotes = ~inquotes;
5918                         p++;
5919                         protect_against_glob = globbing;
5920                         continue;
5921                 }
5922                 if ((unsigned char)*p == CTLESC) {
5923                         p++;
5924 #if DEBUG
5925                         if (*p == '\0')
5926                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5927 #endif
5928                         if (protect_against_glob) {
5929                                 /*
5930                                  * We used to trust glob() and fnmatch() to eat
5931                                  * superfluous escapes (\z where z has no
5932                                  * special meaning anyway). But this causes
5933                                  * bugs such as string of one greek letter rho
5934                                  * (unicode-encoded as two bytes "cf,81")
5935                                  * getting encoded as "cf,CTLESC,81"
5936                                  * and here, converted to "cf,\,81" -
5937                                  * which does not go well with some flavors
5938                                  * of fnmatch() in unicode locales
5939                                  * (for example, glibc <= 2.22).
5940                                  *
5941                                  * Lets add "\" only on the chars which need it.
5942                                  * Testcases for less obvious chars are shown.
5943                                  */
5944                                 if (*p == '*'
5945                                  || *p == '?'
5946                                  || *p == '['
5947                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5948                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5949                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5950                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5951                                 /* Some libc support [^negate], that's why "^" also needs love */
5952                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5953                                 ) {
5954                                         *q++ = '\\';
5955                                 }
5956                         }
5957                 } else if (*p == '\\' && !inquotes) {
5958                         /* naked back slash */
5959                         protect_against_glob = 0;
5960                         goto copy;
5961                 }
5962 #if BASH_PATTERN_SUBST
5963                 else if (*p == '/' && slash) {
5964                         /* stop handling globbing and mark location of slash */
5965                         globbing = slash = 0;
5966                         *p = CTLESC;
5967                 }
5968 #endif
5969                 protect_against_glob = globbing;
5970  copy:
5971                 *q++ = *p++;
5972         }
5973         *q = '\0';
5974         if (flag & RMESCAPE_GROW) {
5975                 expdest = r;
5976                 STADJUST(q - r + 1, expdest);
5977         }
5978         return r;
5979 }
5980 #define pmatch(a, b) !fnmatch((a), (b), 0)
5981
5982 /*
5983  * Prepare a pattern for a expmeta (internal glob(3)) call.
5984  *
5985  * Returns an stalloced string.
5986  */
5987 static char *
5988 preglob(const char *pattern, int flag)
5989 {
5990         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5991 }
5992
5993 /*
5994  * Put a string on the stack.
5995  */
5996 static void
5997 memtodest(const char *p, size_t len, int syntax, int quotes)
5998 {
5999         char *q;
6000
6001         if (!len)
6002                 return;
6003
6004         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6005
6006         do {
6007                 unsigned char c = *p++;
6008                 if (c) {
6009                         if (quotes & QUOTES_ESC) {
6010                                 int n = SIT(c, syntax);
6011                                 if (n == CCTL
6012                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6013                                      && n == CBACK
6014                                     )
6015                                 ) {
6016                                         USTPUTC(CTLESC, q);
6017                                 }
6018                         }
6019                 } else if (!(quotes & QUOTES_KEEPNUL))
6020                         continue;
6021                 USTPUTC(c, q);
6022         } while (--len);
6023
6024         expdest = q;
6025 }
6026
6027 static size_t
6028 strtodest(const char *p, int syntax, int quotes)
6029 {
6030         size_t len = strlen(p);
6031         memtodest(p, len, syntax, quotes);
6032         return len;
6033 }
6034
6035 /*
6036  * Record the fact that we have to scan this region of the
6037  * string for IFS characters.
6038  */
6039 static void
6040 recordregion(int start, int end, int nulonly)
6041 {
6042         struct ifsregion *ifsp;
6043
6044         if (ifslastp == NULL) {
6045                 ifsp = &ifsfirst;
6046         } else {
6047                 INT_OFF;
6048                 ifsp = ckzalloc(sizeof(*ifsp));
6049                 /*ifsp->next = NULL; - ckzalloc did it */
6050                 ifslastp->next = ifsp;
6051                 INT_ON;
6052         }
6053         ifslastp = ifsp;
6054         ifslastp->begoff = start;
6055         ifslastp->endoff = end;
6056         ifslastp->nulonly = nulonly;
6057 }
6058
6059 static void
6060 removerecordregions(int endoff)
6061 {
6062         if (ifslastp == NULL)
6063                 return;
6064
6065         if (ifsfirst.endoff > endoff) {
6066                 while (ifsfirst.next) {
6067                         struct ifsregion *ifsp;
6068                         INT_OFF;
6069                         ifsp = ifsfirst.next->next;
6070                         free(ifsfirst.next);
6071                         ifsfirst.next = ifsp;
6072                         INT_ON;
6073                 }
6074                 if (ifsfirst.begoff > endoff) {
6075                         ifslastp = NULL;
6076                 } else {
6077                         ifslastp = &ifsfirst;
6078                         ifsfirst.endoff = endoff;
6079                 }
6080                 return;
6081         }
6082
6083         ifslastp = &ifsfirst;
6084         while (ifslastp->next && ifslastp->next->begoff < endoff)
6085                 ifslastp = ifslastp->next;
6086         while (ifslastp->next) {
6087                 struct ifsregion *ifsp;
6088                 INT_OFF;
6089                 ifsp = ifslastp->next->next;
6090                 free(ifslastp->next);
6091                 ifslastp->next = ifsp;
6092                 INT_ON;
6093         }
6094         if (ifslastp->endoff > endoff)
6095                 ifslastp->endoff = endoff;
6096 }
6097
6098 static char *
6099 exptilde(char *startp, char *p, int flags)
6100 {
6101         unsigned char c;
6102         char *name;
6103         struct passwd *pw;
6104         const char *home;
6105         int quotes = flags & QUOTES_ESC;
6106
6107         name = p + 1;
6108
6109         while ((c = *++p) != '\0') {
6110                 switch (c) {
6111                 case CTLESC:
6112                         return startp;
6113                 case CTLQUOTEMARK:
6114                         return startp;
6115                 case ':':
6116                         if (flags & EXP_VARTILDE)
6117                                 goto done;
6118                         break;
6119                 case '/':
6120                 case CTLENDVAR:
6121                         goto done;
6122                 }
6123         }
6124  done:
6125         *p = '\0';
6126         if (*name == '\0') {
6127                 home = lookupvar("HOME");
6128         } else {
6129                 pw = getpwnam(name);
6130                 if (pw == NULL)
6131                         goto lose;
6132                 home = pw->pw_dir;
6133         }
6134         if (!home || !*home)
6135                 goto lose;
6136         *p = c;
6137         strtodest(home, SQSYNTAX, quotes);
6138         return p;
6139  lose:
6140         *p = c;
6141         return startp;
6142 }
6143
6144 /*
6145  * Execute a command inside back quotes.  If it's a builtin command, we
6146  * want to save its output in a block obtained from malloc.  Otherwise
6147  * we fork off a subprocess and get the output of the command via a pipe.
6148  * Should be called with interrupts off.
6149  */
6150 struct backcmd {                /* result of evalbackcmd */
6151         int fd;                 /* file descriptor to read from */
6152         int nleft;              /* number of chars in buffer */
6153         char *buf;              /* buffer */
6154         struct job *jp;         /* job structure for command */
6155 };
6156
6157 /* These forward decls are needed to use "eval" code for backticks handling: */
6158 #define EV_EXIT 01              /* exit after evaluating tree */
6159 static int evaltree(union node *, int);
6160
6161 static void FAST_FUNC
6162 evalbackcmd(union node *n, struct backcmd *result)
6163 {
6164         int pip[2];
6165         struct job *jp;
6166
6167         result->fd = -1;
6168         result->buf = NULL;
6169         result->nleft = 0;
6170         result->jp = NULL;
6171         if (n == NULL) {
6172                 goto out;
6173         }
6174
6175         if (pipe(pip) < 0)
6176                 ash_msg_and_raise_error("pipe call failed");
6177         jp = makejob(/*n,*/ 1);
6178         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6179                 /* child */
6180                 FORCE_INT_ON;
6181                 close(pip[0]);
6182                 if (pip[1] != 1) {
6183                         /*close(1);*/
6184                         dup2_or_raise(pip[1], 1);
6185                         close(pip[1]);
6186                 }
6187 /* TODO: eflag clearing makes the following not abort:
6188  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6189  * which is what bash does (unless it is in POSIX mode).
6190  * dash deleted "eflag = 0" line in the commit
6191  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6192  *  [EVAL] Don't clear eflag in evalbackcmd
6193  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6194  */
6195                 eflag = 0;
6196                 ifsfree();
6197                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6198                 /* NOTREACHED */
6199         }
6200         /* parent */
6201         close(pip[1]);
6202         result->fd = pip[0];
6203         result->jp = jp;
6204
6205  out:
6206         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6207                 result->fd, result->buf, result->nleft, result->jp));
6208 }
6209
6210 /*
6211  * Expand stuff in backwards quotes.
6212  */
6213 static void
6214 expbackq(union node *cmd, int flag)
6215 {
6216         struct backcmd in;
6217         int i;
6218         char buf[128];
6219         char *p;
6220         char *dest;
6221         int startloc;
6222         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6223         struct stackmark smark;
6224
6225         INT_OFF;
6226         startloc = expdest - (char *)stackblock();
6227         pushstackmark(&smark, startloc);
6228         evalbackcmd(cmd, &in);
6229         popstackmark(&smark);
6230
6231         p = in.buf;
6232         i = in.nleft;
6233         if (i == 0)
6234                 goto read;
6235         for (;;) {
6236                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6237  read:
6238                 if (in.fd < 0)
6239                         break;
6240                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6241                 TRACE(("expbackq: read returns %d\n", i));
6242                 if (i <= 0)
6243                         break;
6244                 p = buf;
6245         }
6246
6247         free(in.buf);
6248         if (in.fd >= 0) {
6249                 close(in.fd);
6250                 back_exitstatus = waitforjob(in.jp);
6251         }
6252         INT_ON;
6253
6254         /* Eat all trailing newlines */
6255         dest = expdest;
6256         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6257                 STUNPUTC(dest);
6258         expdest = dest;
6259
6260         if (!(flag & EXP_QUOTED))
6261                 recordregion(startloc, dest - (char *)stackblock(), 0);
6262         TRACE(("evalbackq: size:%d:'%.*s'\n",
6263                 (int)((dest - (char *)stackblock()) - startloc),
6264                 (int)((dest - (char *)stackblock()) - startloc),
6265                 stackblock() + startloc));
6266 }
6267
6268 #if ENABLE_FEATURE_SH_MATH
6269 /*
6270  * Expand arithmetic expression.  Backup to start of expression,
6271  * evaluate, place result in (backed up) result, adjust string position.
6272  */
6273 static void
6274 expari(int flag)
6275 {
6276         char *p, *start;
6277         int begoff;
6278         int len;
6279
6280         /* ifsfree(); */
6281
6282         /*
6283          * This routine is slightly over-complicated for
6284          * efficiency.  Next we scan backwards looking for the
6285          * start of arithmetic.
6286          */
6287         start = stackblock();
6288         p = expdest - 1;
6289         *p = '\0';
6290         p--;
6291         while (1) {
6292                 int esc;
6293
6294                 while ((unsigned char)*p != CTLARI) {
6295                         p--;
6296 #if DEBUG
6297                         if (p < start) {
6298                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6299                         }
6300 #endif
6301                 }
6302
6303                 esc = esclen(start, p);
6304                 if (!(esc % 2)) {
6305                         break;
6306                 }
6307
6308                 p -= esc + 1;
6309         }
6310
6311         begoff = p - start;
6312
6313         removerecordregions(begoff);
6314
6315         expdest = p;
6316
6317         if (flag & QUOTES_ESC)
6318                 rmescapes(p + 1, 0);
6319
6320         len = cvtnum(ash_arith(p + 1));
6321
6322         if (!(flag & EXP_QUOTED))
6323                 recordregion(begoff, begoff + len, 0);
6324 }
6325 #endif
6326
6327 /* argstr needs it */
6328 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6329
6330 /*
6331  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6332  * characters to allow for further processing.  Otherwise treat
6333  * $@ like $* since no splitting will be performed.
6334  *
6335  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6336  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6337  * for correct expansion of "B=$A" word.
6338  */
6339 static void
6340 argstr(char *p, int flags, struct strlist *var_str_list)
6341 {
6342         static const char spclchars[] ALIGN1 = {
6343                 '=',
6344                 ':',
6345                 CTLQUOTEMARK,
6346                 CTLENDVAR,
6347                 CTLESC,
6348                 CTLVAR,
6349                 CTLBACKQ,
6350 #if ENABLE_FEATURE_SH_MATH
6351                 CTLENDARI,
6352 #endif
6353                 '\0'
6354         };
6355         const char *reject = spclchars;
6356         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6357         int inquotes;
6358         size_t length;
6359         int startloc;
6360
6361         if (!(flags & EXP_VARTILDE)) {
6362                 reject += 2;
6363         } else if (flags & EXP_VARTILDE2) {
6364                 reject++;
6365         }
6366         inquotes = 0;
6367         length = 0;
6368         if (flags & EXP_TILDE) {
6369                 char *q;
6370
6371                 flags &= ~EXP_TILDE;
6372  tilde:
6373                 q = p;
6374                 if (*q == '~')
6375                         p = exptilde(p, q, flags);
6376         }
6377  start:
6378         startloc = expdest - (char *)stackblock();
6379         for (;;) {
6380                 unsigned char c;
6381
6382                 length += strcspn(p + length, reject);
6383                 c = p[length];
6384                 if (c) {
6385                         if (!(c & 0x80)
6386                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6387                         ) {
6388                                 /* c == '=' || c == ':' || c == CTLENDARI */
6389                                 length++;
6390                         }
6391                 }
6392                 if (length > 0) {
6393                         int newloc;
6394                         expdest = stack_nputstr(p, length, expdest);
6395                         newloc = expdest - (char *)stackblock();
6396                         if (breakall && !inquotes && newloc > startloc) {
6397                                 recordregion(startloc, newloc, 0);
6398                         }
6399                         startloc = newloc;
6400                 }
6401                 p += length + 1;
6402                 length = 0;
6403
6404                 switch (c) {
6405                 case '\0':
6406                         goto breakloop;
6407                 case '=':
6408                         if (flags & EXP_VARTILDE2) {
6409                                 p--;
6410                                 continue;
6411                         }
6412                         flags |= EXP_VARTILDE2;
6413                         reject++;
6414                         /* fall through */
6415                 case ':':
6416                         /*
6417                          * sort of a hack - expand tildes in variable
6418                          * assignments (after the first '=' and after ':'s).
6419                          */
6420                         if (*--p == '~') {
6421                                 goto tilde;
6422                         }
6423                         continue;
6424                 }
6425
6426                 switch (c) {
6427                 case CTLENDVAR: /* ??? */
6428                         goto breakloop;
6429                 case CTLQUOTEMARK:
6430                         inquotes ^= EXP_QUOTED;
6431                         /* "$@" syntax adherence hack */
6432                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6433                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6434                                 goto start;
6435                         }
6436  addquote:
6437                         if (flags & QUOTES_ESC) {
6438                                 p--;
6439                                 length++;
6440                                 startloc++;
6441                         }
6442                         break;
6443                 case CTLESC:
6444                         startloc++;
6445                         length++;
6446
6447                         /*
6448                          * Quoted parameter expansion pattern: remove quote
6449                          * unless inside inner quotes or we have a literal
6450                          * backslash.
6451                          */
6452                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6453                             EXP_QPAT && *p != '\\')
6454                                 break;
6455
6456                         goto addquote;
6457                 case CTLVAR:
6458                         TRACE(("argstr: evalvar('%s')\n", p));
6459                         p = evalvar(p, flags | inquotes, var_str_list);
6460                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6461                         goto start;
6462                 case CTLBACKQ:
6463                         expbackq(argbackq->n, flags | inquotes);
6464                         argbackq = argbackq->next;
6465                         goto start;
6466 #if ENABLE_FEATURE_SH_MATH
6467                 case CTLENDARI:
6468                         p--;
6469                         expari(flags | inquotes);
6470                         goto start;
6471 #endif
6472                 }
6473         }
6474  breakloop: ;
6475 }
6476
6477 static char *
6478 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6479                 char *pattern, int quotes, int zero)
6480 {
6481         char *loc, *loc2;
6482         char c;
6483
6484         loc = startp;
6485         loc2 = rmesc;
6486         do {
6487                 int match;
6488                 const char *s = loc2;
6489
6490                 c = *loc2;
6491                 if (zero) {
6492                         *loc2 = '\0';
6493                         s = rmesc;
6494                 }
6495                 match = pmatch(pattern, s);
6496
6497                 *loc2 = c;
6498                 if (match)
6499                         return loc;
6500                 if (quotes && (unsigned char)*loc == CTLESC)
6501                         loc++;
6502                 loc++;
6503                 loc2++;
6504         } while (c);
6505         return NULL;
6506 }
6507
6508 static char *
6509 scanright(char *startp, char *rmesc, char *rmescend,
6510                 char *pattern, int quotes, int match_at_start)
6511 {
6512 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6513         int try2optimize = match_at_start;
6514 #endif
6515         int esc = 0;
6516         char *loc;
6517         char *loc2;
6518
6519         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6520          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6521          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6522          * Logic:
6523          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6524          * and on each iteration they go back two/one char until they reach the beginning.
6525          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6526          */
6527         /* TODO: document in what other circumstances we are called. */
6528
6529         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6530                 int match;
6531                 char c = *loc2;
6532                 const char *s = loc2;
6533                 if (match_at_start) {
6534                         *loc2 = '\0';
6535                         s = rmesc;
6536                 }
6537                 match = pmatch(pattern, s);
6538                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6539                 *loc2 = c;
6540                 if (match)
6541                         return loc;
6542 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6543                 if (try2optimize) {
6544                         /* Maybe we can optimize this:
6545                          * if pattern ends with unescaped *, we can avoid checking
6546                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6547                          * it won't match truncated "raw_value_of_" strings too.
6548                          */
6549                         unsigned plen = strlen(pattern);
6550                         /* Does it end with "*"? */
6551                         if (plen != 0 && pattern[--plen] == '*') {
6552                                 /* "xxxx*" is not escaped */
6553                                 /* "xxx\*" is escaped */
6554                                 /* "xx\\*" is not escaped */
6555                                 /* "x\\\*" is escaped */
6556                                 int slashes = 0;
6557                                 while (plen != 0 && pattern[--plen] == '\\')
6558                                         slashes++;
6559                                 if (!(slashes & 1))
6560                                         break; /* ends with unescaped "*" */
6561                         }
6562                         try2optimize = 0;
6563                 }
6564 #endif
6565                 loc--;
6566                 if (quotes) {
6567                         if (--esc < 0) {
6568                                 esc = esclen(startp, loc);
6569                         }
6570                         if (esc % 2) {
6571                                 esc--;
6572                                 loc--;
6573                         }
6574                 }
6575         }
6576         return NULL;
6577 }
6578
6579 static void varunset(const char *, const char *, const char *, int) NORETURN;
6580 static void
6581 varunset(const char *end, const char *var, const char *umsg, int varflags)
6582 {
6583         const char *msg;
6584         const char *tail;
6585
6586         tail = nullstr;
6587         msg = "parameter not set";
6588         if (umsg) {
6589                 if ((unsigned char)*end == CTLENDVAR) {
6590                         if (varflags & VSNUL)
6591                                 tail = " or null";
6592                 } else {
6593                         msg = umsg;
6594                 }
6595         }
6596         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6597 }
6598
6599 static const char *
6600 subevalvar(char *p, char *varname, int strloc, int subtype,
6601                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6602 {
6603         struct nodelist *saveargbackq = argbackq;
6604         int quotes = flag & QUOTES_ESC;
6605         char *startp;
6606         char *loc;
6607         char *rmesc, *rmescend;
6608         char *str;
6609         IF_BASH_SUBSTR(int pos, len, orig_len;)
6610         int amount, resetloc;
6611         IF_BASH_PATTERN_SUBST(int workloc;)
6612         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6613         int zero;
6614         char *(*scan)(char*, char*, char*, char*, int, int);
6615
6616         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6617         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6618
6619         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6620                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6621                         var_str_list);
6622         STPUTC('\0', expdest);
6623         argbackq = saveargbackq;
6624         startp = (char *)stackblock() + startloc;
6625
6626         switch (subtype) {
6627         case VSASSIGN:
6628                 setvar0(varname, startp);
6629                 amount = startp - expdest;
6630                 STADJUST(amount, expdest);
6631                 return startp;
6632
6633         case VSQUESTION:
6634                 varunset(p, varname, startp, varflags);
6635                 /* NOTREACHED */
6636
6637 #if BASH_SUBSTR
6638         case VSSUBSTR:
6639 //TODO: support more general format ${v:EXPR:EXPR},
6640 // where EXPR follows $(()) rules
6641                 loc = str = stackblock() + strloc;
6642                 /* Read POS in ${var:POS:LEN} */
6643                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6644                 len = str - startp - 1;
6645
6646                 /* *loc != '\0', guaranteed by parser */
6647                 if (quotes) {
6648                         char *ptr;
6649
6650                         /* Adjust the length by the number of escapes */
6651                         for (ptr = startp; ptr < (str - 1); ptr++) {
6652                                 if ((unsigned char)*ptr == CTLESC) {
6653                                         len--;
6654                                         ptr++;
6655                                 }
6656                         }
6657                 }
6658                 orig_len = len;
6659
6660                 if (*loc++ == ':') {
6661                         /* ${var::LEN} */
6662                         len = number(loc);
6663                 } else {
6664                         /* Skip POS in ${var:POS:LEN} */
6665                         len = orig_len;
6666                         while (*loc && *loc != ':') {
6667                                 /* TODO?
6668                                  * bash complains on: var=qwe; echo ${var:1a:123}
6669                                 if (!isdigit(*loc))
6670                                         ash_msg_and_raise_error(msg_illnum, str);
6671                                  */
6672                                 loc++;
6673                         }
6674                         if (*loc++ == ':') {
6675                                 len = number(loc);
6676                         }
6677                 }
6678                 if (pos < 0) {
6679                         /* ${VAR:$((-n)):l} starts n chars from the end */
6680                         pos = orig_len + pos;
6681                 }
6682                 if ((unsigned)pos >= orig_len) {
6683                         /* apart from obvious ${VAR:999999:l},
6684                          * covers ${VAR:$((-9999999)):l} - result is ""
6685                          * (bash-compat)
6686                          */
6687                         pos = 0;
6688                         len = 0;
6689                 }
6690                 if (len > (orig_len - pos))
6691                         len = orig_len - pos;
6692
6693                 for (str = startp; pos; str++, pos--) {
6694                         if (quotes && (unsigned char)*str == CTLESC)
6695                                 str++;
6696                 }
6697                 for (loc = startp; len; len--) {
6698                         if (quotes && (unsigned char)*str == CTLESC)
6699                                 *loc++ = *str++;
6700                         *loc++ = *str++;
6701                 }
6702                 *loc = '\0';
6703                 amount = loc - expdest;
6704                 STADJUST(amount, expdest);
6705                 return loc;
6706 #endif /* BASH_SUBSTR */
6707         }
6708
6709         resetloc = expdest - (char *)stackblock();
6710
6711 #if BASH_PATTERN_SUBST
6712         /* We'll comeback here if we grow the stack while handling
6713          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6714          * stack will need rebasing, and we'll need to remove our work
6715          * areas each time
6716          */
6717  restart:
6718 #endif
6719
6720         amount = expdest - ((char *)stackblock() + resetloc);
6721         STADJUST(-amount, expdest);
6722         startp = (char *)stackblock() + startloc;
6723
6724         rmesc = startp;
6725         rmescend = (char *)stackblock() + strloc;
6726         if (quotes) {
6727                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6728                 if (rmesc != startp) {
6729                         rmescend = expdest;
6730                         startp = (char *)stackblock() + startloc;
6731                 }
6732         }
6733         rmescend--;
6734         str = (char *)stackblock() + strloc;
6735         /*
6736          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6737          * The result is a_\_z_c (not a\_\_z_c)!
6738          *
6739          * The search pattern and replace string treat backslashes differently!
6740          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6741          * and string.  It's only used on the first call.
6742          */
6743         preglob(str, IF_BASH_PATTERN_SUBST(
6744                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6745                         RMESCAPE_SLASH : ) 0);
6746
6747 #if BASH_PATTERN_SUBST
6748         workloc = expdest - (char *)stackblock();
6749         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6750                 char *idx, *end;
6751
6752                 if (!repl) {
6753                         repl = strchr(str, CTLESC);
6754                         if (repl)
6755                                 *repl++ = '\0';
6756                         else
6757                                 repl = nullstr;
6758                 }
6759                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6760
6761                 /* If there's no pattern to match, return the expansion unmolested */
6762                 if (str[0] == '\0')
6763                         return NULL;
6764
6765                 len = 0;
6766                 idx = startp;
6767                 end = str - 1;
6768                 while (idx < end) {
6769  try_to_match:
6770                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6771                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6772                         if (!loc) {
6773                                 /* No match, advance */
6774                                 char *restart_detect = stackblock();
6775  skip_matching:
6776                                 STPUTC(*idx, expdest);
6777                                 if (quotes && (unsigned char)*idx == CTLESC) {
6778                                         idx++;
6779                                         len++;
6780                                         STPUTC(*idx, expdest);
6781                                 }
6782                                 if (stackblock() != restart_detect)
6783                                         goto restart;
6784                                 idx++;
6785                                 len++;
6786                                 rmesc++;
6787                                 /* continue; - prone to quadratic behavior, smarter code: */
6788                                 if (idx >= end)
6789                                         break;
6790                                 if (str[0] == '*') {
6791                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6792                                          * it would never match "ong_string" etc, no point in trying.
6793                                          */
6794                                         goto skip_matching;
6795                                 }
6796                                 goto try_to_match;
6797                         }
6798
6799                         if (subtype == VSREPLACEALL) {
6800                                 while (idx < loc) {
6801                                         if (quotes && (unsigned char)*idx == CTLESC)
6802                                                 idx++;
6803                                         idx++;
6804                                         rmesc++;
6805                                 }
6806                         } else {
6807                                 idx = loc;
6808                         }
6809
6810                         //bb_error_msg("repl:'%s'", repl);
6811                         for (loc = (char*)repl; *loc; loc++) {
6812                                 char *restart_detect = stackblock();
6813                                 if (quotes && *loc == '\\') {
6814                                         STPUTC(CTLESC, expdest);
6815                                         len++;
6816                                 }
6817                                 STPUTC(*loc, expdest);
6818                                 if (stackblock() != restart_detect)
6819                                         goto restart;
6820                                 len++;
6821                         }
6822
6823                         if (subtype == VSREPLACE) {
6824                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6825                                 while (*idx) {
6826                                         char *restart_detect = stackblock();
6827                                         STPUTC(*idx, expdest);
6828                                         if (stackblock() != restart_detect)
6829                                                 goto restart;
6830                                         len++;
6831                                         idx++;
6832                                 }
6833                                 break;
6834                         }
6835                 }
6836
6837                 /* We've put the replaced text into a buffer at workloc, now
6838                  * move it to the right place and adjust the stack.
6839                  */
6840                 STPUTC('\0', expdest);
6841                 startp = (char *)stackblock() + startloc;
6842                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6843                 //bb_error_msg("startp:'%s'", startp);
6844                 amount = expdest - (startp + len);
6845                 STADJUST(-amount, expdest);
6846                 return startp;
6847         }
6848 #endif /* BASH_PATTERN_SUBST */
6849
6850         subtype -= VSTRIMRIGHT;
6851 #if DEBUG
6852         if (subtype < 0 || subtype > 7)
6853                 abort();
6854 #endif
6855         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6856         zero = subtype >> 1;
6857         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6858         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6859
6860         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6861         if (loc) {
6862                 if (zero) {
6863                         memmove(startp, loc, str - loc);
6864                         loc = startp + (str - loc) - 1;
6865                 }
6866                 *loc = '\0';
6867                 amount = loc - expdest;
6868                 STADJUST(amount, expdest);
6869         }
6870         return loc;
6871 }
6872
6873 /*
6874  * Add the value of a specialized variable to the stack string.
6875  * name parameter (examples):
6876  * ash -c 'echo $1'      name:'1='
6877  * ash -c 'echo $qwe'    name:'qwe='
6878  * ash -c 'echo $$'      name:'$='
6879  * ash -c 'echo ${$}'    name:'$='
6880  * ash -c 'echo ${$##q}' name:'$=q'
6881  * ash -c 'echo ${#$}'   name:'$='
6882  * note: examples with bad shell syntax:
6883  * ash -c 'echo ${#$1}'  name:'$=1'
6884  * ash -c 'echo ${#1#}'  name:'1=#'
6885  */
6886 static NOINLINE ssize_t
6887 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6888 {
6889         const char *p;
6890         int num;
6891         int i;
6892         ssize_t len = 0;
6893         int sep;
6894         int quoted = *quotedp;
6895         int subtype = varflags & VSTYPE;
6896         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6897         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6898         int syntax;
6899
6900         sep = (flags & EXP_FULL) << CHAR_BIT;
6901         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6902
6903         switch (*name) {
6904         case '$':
6905                 num = rootpid;
6906                 goto numvar;
6907         case '?':
6908                 num = exitstatus;
6909                 goto numvar;
6910         case '#':
6911                 num = shellparam.nparam;
6912                 goto numvar;
6913         case '!':
6914                 num = backgndpid;
6915                 if (num == 0)
6916                         return -1;
6917  numvar:
6918                 len = cvtnum(num);
6919                 goto check_1char_name;
6920         case '-':
6921                 expdest = makestrspace(NOPTS, expdest);
6922                 for (i = NOPTS - 1; i >= 0; i--) {
6923                         if (optlist[i]) {
6924                                 USTPUTC(optletters(i), expdest);
6925                                 len++;
6926                         }
6927                 }
6928  check_1char_name:
6929 #if 0
6930                 /* handles cases similar to ${#$1} */
6931                 if (name[2] != '\0')
6932                         raise_error_syntax("bad substitution");
6933 #endif
6934                 break;
6935         case '@':
6936                 if (quoted && sep)
6937                         goto param;
6938                 /* fall through */
6939         case '*': {
6940                 char **ap;
6941                 char sepc;
6942
6943                 if (quoted)
6944                         sep = 0;
6945                 sep |= ifsset() ? ifsval()[0] : ' ';
6946  param:
6947                 sepc = sep;
6948                 *quotedp = !sepc;
6949                 ap = shellparam.p;
6950                 if (!ap)
6951                         return -1;
6952                 while ((p = *ap++) != NULL) {
6953                         len += strtodest(p, syntax, quotes);
6954
6955                         if (*ap && sep) {
6956                                 len++;
6957                                 memtodest(&sepc, 1, syntax, quotes);
6958                         }
6959                 }
6960                 break;
6961         } /* case '*' */
6962         case '0':
6963         case '1':
6964         case '2':
6965         case '3':
6966         case '4':
6967         case '5':
6968         case '6':
6969         case '7':
6970         case '8':
6971         case '9':
6972                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6973                 if (num < 0 || num > shellparam.nparam)
6974                         return -1;
6975                 p = num ? shellparam.p[num - 1] : arg0;
6976                 goto value;
6977         default:
6978                 /* NB: name has form "VAR=..." */
6979
6980                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6981                  * which should be considered before we check variables. */
6982                 if (var_str_list) {
6983                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6984                         p = NULL;
6985                         do {
6986                                 char *str, *eq;
6987                                 str = var_str_list->text;
6988                                 eq = strchr(str, '=');
6989                                 if (!eq) /* stop at first non-assignment */
6990                                         break;
6991                                 eq++;
6992                                 if (name_len == (unsigned)(eq - str)
6993                                  && strncmp(str, name, name_len) == 0
6994                                 ) {
6995                                         p = eq;
6996                                         /* goto value; - WRONG! */
6997                                         /* think "A=1 A=2 B=$A" */
6998                                 }
6999                                 var_str_list = var_str_list->next;
7000                         } while (var_str_list);
7001                         if (p)
7002                                 goto value;
7003                 }
7004                 p = lookupvar(name);
7005  value:
7006                 if (!p)
7007                         return -1;
7008
7009                 len = strtodest(p, syntax, quotes);
7010 #if ENABLE_UNICODE_SUPPORT
7011                 if (subtype == VSLENGTH && len > 0) {
7012                         reinit_unicode_for_ash();
7013                         if (unicode_status == UNICODE_ON) {
7014                                 STADJUST(-len, expdest);
7015                                 discard = 0;
7016                                 len = unicode_strlen(p);
7017                         }
7018                 }
7019 #endif
7020                 break;
7021         }
7022
7023         if (discard)
7024                 STADJUST(-len, expdest);
7025         return len;
7026 }
7027
7028 /*
7029  * Expand a variable, and return a pointer to the next character in the
7030  * input string.
7031  */
7032 static char *
7033 evalvar(char *p, int flag, struct strlist *var_str_list)
7034 {
7035         char varflags;
7036         char subtype;
7037         int quoted;
7038         char easy;
7039         char *var;
7040         int patloc;
7041         int startloc;
7042         ssize_t varlen;
7043
7044         varflags = (unsigned char) *p++;
7045         subtype = varflags & VSTYPE;
7046
7047         if (!subtype)
7048                 raise_error_syntax("bad substitution");
7049
7050         quoted = flag & EXP_QUOTED;
7051         var = p;
7052         easy = (!quoted || (*var == '@' && shellparam.nparam));
7053         startloc = expdest - (char *)stackblock();
7054         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7055
7056  again:
7057         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7058         if (varflags & VSNUL)
7059                 varlen--;
7060
7061         if (subtype == VSPLUS) {
7062                 varlen = -1 - varlen;
7063                 goto vsplus;
7064         }
7065
7066         if (subtype == VSMINUS) {
7067  vsplus:
7068                 if (varlen < 0) {
7069                         argstr(
7070                                 p,
7071                                 flag | EXP_TILDE | EXP_WORD,
7072                                 var_str_list
7073                         );
7074                         goto end;
7075                 }
7076                 goto record;
7077         }
7078
7079         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7080                 if (varlen >= 0)
7081                         goto record;
7082
7083                 subevalvar(p, var, 0, subtype, startloc, varflags,
7084                            flag & ~QUOTES_ESC, var_str_list);
7085                 varflags &= ~VSNUL;
7086                 /*
7087                  * Remove any recorded regions beyond
7088                  * start of variable
7089                  */
7090                 removerecordregions(startloc);
7091                 goto again;
7092         }
7093
7094         if (varlen < 0 && uflag)
7095                 varunset(p, var, 0, 0);
7096
7097         if (subtype == VSLENGTH) {
7098                 cvtnum(varlen > 0 ? varlen : 0);
7099                 goto record;
7100         }
7101
7102         if (subtype == VSNORMAL) {
7103  record:
7104                 if (!easy)
7105                         goto end;
7106                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7107                 goto end;
7108         }
7109
7110 #if DEBUG
7111         switch (subtype) {
7112         case VSTRIMLEFT:
7113         case VSTRIMLEFTMAX:
7114         case VSTRIMRIGHT:
7115         case VSTRIMRIGHTMAX:
7116 #if BASH_SUBSTR
7117         case VSSUBSTR:
7118 #endif
7119 #if BASH_PATTERN_SUBST
7120         case VSREPLACE:
7121         case VSREPLACEALL:
7122 #endif
7123                 break;
7124         default:
7125                 abort();
7126         }
7127 #endif
7128
7129         if (varlen >= 0) {
7130                 /*
7131                  * Terminate the string and start recording the pattern
7132                  * right after it
7133                  */
7134                 STPUTC('\0', expdest);
7135                 patloc = expdest - (char *)stackblock();
7136                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7137                                 startloc, varflags, flag, var_str_list)) {
7138                         int amount = expdest - (
7139                                 (char *)stackblock() + patloc - 1
7140                         );
7141                         STADJUST(-amount, expdest);
7142                 }
7143                 /* Remove any recorded regions beyond start of variable */
7144                 removerecordregions(startloc);
7145                 goto record;
7146         }
7147
7148  end:
7149         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7150                 int nesting = 1;
7151                 for (;;) {
7152                         unsigned char c = *p++;
7153                         if (c == CTLESC)
7154                                 p++;
7155                         else if (c == CTLBACKQ) {
7156                                 if (varlen >= 0)
7157                                         argbackq = argbackq->next;
7158                         } else if (c == CTLVAR) {
7159                                 if ((*p++ & VSTYPE) != VSNORMAL)
7160                                         nesting++;
7161                         } else if (c == CTLENDVAR) {
7162                                 if (--nesting == 0)
7163                                         break;
7164                         }
7165                 }
7166         }
7167         return p;
7168 }
7169
7170 /*
7171  * Add a file name to the list.
7172  */
7173 static void
7174 addfname(const char *name)
7175 {
7176         struct strlist *sp;
7177
7178         sp = stzalloc(sizeof(*sp));
7179         sp->text = sstrdup(name);
7180         *exparg.lastp = sp;
7181         exparg.lastp = &sp->next;
7182 }
7183
7184 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7185 static int
7186 hasmeta(const char *p)
7187 {
7188         static const char chars[] ALIGN1 = {
7189                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7190         };
7191
7192         for (;;) {
7193                 p = strpbrk(p, chars);
7194                 if (!p)
7195                         break;
7196                 switch ((unsigned char) *p) {
7197                 case CTLQUOTEMARK:
7198                         for (;;) {
7199                                 p++;
7200                                 if (*p == CTLQUOTEMARK)
7201                                         break;
7202                                 if (*p == CTLESC)
7203                                         p++;
7204                                 if (*p == '\0') /* huh? */
7205                                         return 0;
7206                         }
7207                         break;
7208                 case '\\':
7209                 case CTLESC:
7210                         p++;
7211                         if (*p == '\0')
7212                                 return 0;
7213                         break;
7214                 case '[':
7215                         if (!strchr(p + 1, ']')) {
7216                                 /* It's not a properly closed [] pattern,
7217                                  * but other metas may follow. Continue checking.
7218                                  * my[file* _is_ globbed by bash
7219                                  * and matches filenames like "my[file1".
7220                                  */
7221                                 break;
7222                         }
7223                         /* fallthrough */
7224                 default:
7225                 /* case '*': */
7226                 /* case '?': */
7227                         return 1;
7228                 }
7229                 p++;
7230         }
7231
7232         return 0;
7233 }
7234
7235 /* If we want to use glob() from libc... */
7236 #if !ENABLE_ASH_INTERNAL_GLOB
7237
7238 /* Add the result of glob() to the list */
7239 static void
7240 addglob(const glob_t *pglob)
7241 {
7242         char **p = pglob->gl_pathv;
7243
7244         do {
7245                 addfname(*p);
7246         } while (*++p);
7247 }
7248 static void
7249 expandmeta(struct strlist *str /*, int flag*/)
7250 {
7251         /* TODO - EXP_REDIR */
7252
7253         while (str) {
7254                 char *p;
7255                 glob_t pglob;
7256                 int i;
7257
7258                 if (fflag)
7259                         goto nometa;
7260
7261                 if (!hasmeta(str->text))
7262                         goto nometa;
7263
7264                 INT_OFF;
7265                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7266 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7267 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7268 //
7269 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7270 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7271 // Which means you need to unescape the string, right? Not so fast:
7272 // if there _is_ a file named "file\?" (with backslash), it is returned
7273 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7274 // You DON'T KNOW by looking at the result whether you need to unescape it.
7275 //
7276 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7277 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7278 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7279 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7280 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7281 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7282                 i = glob(p, 0, NULL, &pglob);
7283                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7284                 if (p != str->text)
7285                         free(p);
7286                 switch (i) {
7287                 case 0:
7288 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7289                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7290                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7291                                 goto nometa2;
7292 #endif
7293                         addglob(&pglob);
7294                         globfree(&pglob);
7295                         INT_ON;
7296                         break;
7297                 case GLOB_NOMATCH:
7298  //nometa2:
7299                         globfree(&pglob);
7300                         INT_ON;
7301  nometa:
7302                         *exparg.lastp = str;
7303                         rmescapes(str->text, 0);
7304                         exparg.lastp = &str->next;
7305                         break;
7306                 default:        /* GLOB_NOSPACE */
7307                         globfree(&pglob);
7308                         INT_ON;
7309                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7310                 }
7311                 str = str->next;
7312         }
7313 }
7314
7315 #else
7316 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7317
7318 /*
7319  * Do metacharacter (i.e. *, ?, [...]) expansion.
7320  */
7321 static void
7322 expmeta(char *expdir, char *enddir, char *name)
7323 {
7324         char *p;
7325         const char *cp;
7326         char *start;
7327         char *endname;
7328         int metaflag;
7329         struct stat statb;
7330         DIR *dirp;
7331         struct dirent *dp;
7332         int atend;
7333         int matchdot;
7334         int esc;
7335
7336         metaflag = 0;
7337         start = name;
7338         for (p = name; esc = 0, *p; p += esc + 1) {
7339                 if (*p == '*' || *p == '?')
7340                         metaflag = 1;
7341                 else if (*p == '[') {
7342                         char *q = p + 1;
7343                         if (*q == '!')
7344                                 q++;
7345                         for (;;) {
7346                                 if (*q == '\\')
7347                                         q++;
7348                                 if (*q == '/' || *q == '\0')
7349                                         break;
7350                                 if (*++q == ']') {
7351                                         metaflag = 1;
7352                                         break;
7353                                 }
7354                         }
7355                 } else {
7356                         if (*p == '\\')
7357                                 esc++;
7358                         if (p[esc] == '/') {
7359                                 if (metaflag)
7360                                         break;
7361                                 start = p + esc + 1;
7362                         }
7363                 }
7364         }
7365         if (metaflag == 0) {    /* we've reached the end of the file name */
7366                 if (enddir != expdir)
7367                         metaflag++;
7368                 p = name;
7369                 do {
7370                         if (*p == '\\')
7371                                 p++;
7372                         *enddir++ = *p;
7373                 } while (*p++);
7374                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7375                         addfname(expdir);
7376                 return;
7377         }
7378         endname = p;
7379         if (name < start) {
7380                 p = name;
7381                 do {
7382                         if (*p == '\\')
7383                                 p++;
7384                         *enddir++ = *p++;
7385                 } while (p < start);
7386         }
7387         if (enddir == expdir) {
7388                 cp = ".";
7389         } else if (enddir == expdir + 1 && *expdir == '/') {
7390                 cp = "/";
7391         } else {
7392                 cp = expdir;
7393                 enddir[-1] = '\0';
7394         }
7395         dirp = opendir(cp);
7396         if (dirp == NULL)
7397                 return;
7398         if (enddir != expdir)
7399                 enddir[-1] = '/';
7400         if (*endname == 0) {
7401                 atend = 1;
7402         } else {
7403                 atend = 0;
7404                 *endname = '\0';
7405                 endname += esc + 1;
7406         }
7407         matchdot = 0;
7408         p = start;
7409         if (*p == '\\')
7410                 p++;
7411         if (*p == '.')
7412                 matchdot++;
7413         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7414                 if (dp->d_name[0] == '.' && !matchdot)
7415                         continue;
7416                 if (pmatch(start, dp->d_name)) {
7417                         if (atend) {
7418                                 strcpy(enddir, dp->d_name);
7419                                 addfname(expdir);
7420                         } else {
7421                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7422                                         continue;
7423                                 p[-1] = '/';
7424                                 expmeta(expdir, p, endname);
7425                         }
7426                 }
7427         }
7428         closedir(dirp);
7429         if (!atend)
7430                 endname[-esc - 1] = esc ? '\\' : '/';
7431 }
7432
7433 static struct strlist *
7434 msort(struct strlist *list, int len)
7435 {
7436         struct strlist *p, *q = NULL;
7437         struct strlist **lpp;
7438         int half;
7439         int n;
7440
7441         if (len <= 1)
7442                 return list;
7443         half = len >> 1;
7444         p = list;
7445         for (n = half; --n >= 0;) {
7446                 q = p;
7447                 p = p->next;
7448         }
7449         q->next = NULL;                 /* terminate first half of list */
7450         q = msort(list, half);          /* sort first half of list */
7451         p = msort(p, len - half);               /* sort second half */
7452         lpp = &list;
7453         for (;;) {
7454 #if ENABLE_LOCALE_SUPPORT
7455                 if (strcoll(p->text, q->text) < 0)
7456 #else
7457                 if (strcmp(p->text, q->text) < 0)
7458 #endif
7459                                                 {
7460                         *lpp = p;
7461                         lpp = &p->next;
7462                         p = *lpp;
7463                         if (p == NULL) {
7464                                 *lpp = q;
7465                                 break;
7466                         }
7467                 } else {
7468                         *lpp = q;
7469                         lpp = &q->next;
7470                         q = *lpp;
7471                         if (q == NULL) {
7472                                 *lpp = p;
7473                                 break;
7474                         }
7475                 }
7476         }
7477         return list;
7478 }
7479
7480 /*
7481  * Sort the results of file name expansion.  It calculates the number of
7482  * strings to sort and then calls msort (short for merge sort) to do the
7483  * work.
7484  */
7485 static struct strlist *
7486 expsort(struct strlist *str)
7487 {
7488         int len;
7489         struct strlist *sp;
7490
7491         len = 0;
7492         for (sp = str; sp; sp = sp->next)
7493                 len++;
7494         return msort(str, len);
7495 }
7496
7497 static void
7498 expandmeta(struct strlist *str /*, int flag*/)
7499 {
7500         /* TODO - EXP_REDIR */
7501
7502         while (str) {
7503                 char *expdir;
7504                 struct strlist **savelastp;
7505                 struct strlist *sp;
7506                 char *p;
7507
7508                 if (fflag)
7509                         goto nometa;
7510                 if (!hasmeta(str->text))
7511                         goto nometa;
7512                 savelastp = exparg.lastp;
7513
7514                 INT_OFF;
7515                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7516                 {
7517                         int i = strlen(str->text);
7518 //BUGGY estimation of how long expanded name can be
7519                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7520                 }
7521                 expmeta(expdir, expdir, p);
7522                 free(expdir);
7523                 if (p != str->text)
7524                         free(p);
7525                 INT_ON;
7526                 if (exparg.lastp == savelastp) {
7527                         /*
7528                          * no matches
7529                          */
7530  nometa:
7531                         *exparg.lastp = str;
7532                         rmescapes(str->text, 0);
7533                         exparg.lastp = &str->next;
7534                 } else {
7535                         *exparg.lastp = NULL;
7536                         *savelastp = sp = expsort(*savelastp);
7537                         while (sp->next != NULL)
7538                                 sp = sp->next;
7539                         exparg.lastp = &sp->next;
7540                 }
7541                 str = str->next;
7542         }
7543 }
7544 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7545
7546 /*
7547  * Perform variable substitution and command substitution on an argument,
7548  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7549  * perform splitting and file name expansion.  When arglist is NULL, perform
7550  * here document expansion.
7551  */
7552 static void
7553 expandarg(union node *arg, struct arglist *arglist, int flag)
7554 {
7555         struct strlist *sp;
7556         char *p;
7557
7558         argbackq = arg->narg.backquote;
7559         STARTSTACKSTR(expdest);
7560         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7561         argstr(arg->narg.text, flag,
7562                         /* var_str_list: */ arglist ? arglist->list : NULL);
7563         p = _STPUTC('\0', expdest);
7564         expdest = p - 1;
7565         if (arglist == NULL) {
7566                 /* here document expanded */
7567                 goto out;
7568         }
7569         p = grabstackstr(p);
7570         TRACE(("expandarg: p:'%s'\n", p));
7571         exparg.lastp = &exparg.list;
7572         /*
7573          * TODO - EXP_REDIR
7574          */
7575         if (flag & EXP_FULL) {
7576                 ifsbreakup(p, &exparg);
7577                 *exparg.lastp = NULL;
7578                 exparg.lastp = &exparg.list;
7579                 expandmeta(exparg.list /*, flag*/);
7580         } else {
7581                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7582                         rmescapes(p, 0);
7583                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7584                 }
7585                 sp = stzalloc(sizeof(*sp));
7586                 sp->text = p;
7587                 *exparg.lastp = sp;
7588                 exparg.lastp = &sp->next;
7589         }
7590         *exparg.lastp = NULL;
7591         if (exparg.list) {
7592                 *arglist->lastp = exparg.list;
7593                 arglist->lastp = exparg.lastp;
7594         }
7595
7596  out:
7597         ifsfree();
7598 }
7599
7600 /*
7601  * Expand shell variables and backquotes inside a here document.
7602  */
7603 static void
7604 expandhere(union node *arg, int fd)
7605 {
7606         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7607         full_write(fd, stackblock(), expdest - (char *)stackblock());
7608 }
7609
7610 /*
7611  * Returns true if the pattern matches the string.
7612  */
7613 static int
7614 patmatch(char *pattern, const char *string)
7615 {
7616         char *p = preglob(pattern, 0);
7617         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7618         return pmatch(p, string);
7619 }
7620
7621 /*
7622  * See if a pattern matches in a case statement.
7623  */
7624 static int
7625 casematch(union node *pattern, char *val)
7626 {
7627         struct stackmark smark;
7628         int result;
7629
7630         setstackmark(&smark);
7631         argbackq = pattern->narg.backquote;
7632         STARTSTACKSTR(expdest);
7633         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7634                         /* var_str_list: */ NULL);
7635         STACKSTRNUL(expdest);
7636         ifsfree();
7637         result = patmatch(stackblock(), val);
7638         popstackmark(&smark);
7639         return result;
7640 }
7641
7642
7643 /* ============ find_command */
7644
7645 struct builtincmd {
7646         const char *name;
7647         int (*builtin)(int, char **) FAST_FUNC;
7648         /* unsigned flags; */
7649 };
7650 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7651 /* "regular" builtins always take precedence over commands,
7652  * regardless of PATH=....%builtin... position */
7653 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7654 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7655
7656 struct cmdentry {
7657         smallint cmdtype;       /* CMDxxx */
7658         union param {
7659                 int index;
7660                 /* index >= 0 for commands without path (slashes) */
7661                 /* (TODO: what exactly does the value mean? PATH position?) */
7662                 /* index == -1 for commands with slashes */
7663                 /* index == (-2 - applet_no) for NOFORK applets */
7664                 const struct builtincmd *cmd;
7665                 struct funcnode *func;
7666         } u;
7667 };
7668 /* values of cmdtype */
7669 #define CMDUNKNOWN      -1      /* no entry in table for command */
7670 #define CMDNORMAL       0       /* command is an executable program */
7671 #define CMDFUNCTION     1       /* command is a shell function */
7672 #define CMDBUILTIN      2       /* command is a shell builtin */
7673
7674 /* action to find_command() */
7675 #define DO_ERR          0x01    /* prints errors */
7676 #define DO_ABS          0x02    /* checks absolute paths */
7677 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7678 #define DO_ALTPATH      0x08    /* using alternate path */
7679 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7680
7681 static void find_command(char *, struct cmdentry *, int, const char *);
7682
7683
7684 /* ============ Hashing commands */
7685
7686 /*
7687  * When commands are first encountered, they are entered in a hash table.
7688  * This ensures that a full path search will not have to be done for them
7689  * on each invocation.
7690  *
7691  * We should investigate converting to a linear search, even though that
7692  * would make the command name "hash" a misnomer.
7693  */
7694
7695 struct tblentry {
7696         struct tblentry *next;  /* next entry in hash chain */
7697         union param param;      /* definition of builtin function */
7698         smallint cmdtype;       /* CMDxxx */
7699         char rehash;            /* if set, cd done since entry created */
7700         char cmdname[1];        /* name of command */
7701 };
7702
7703 static struct tblentry **cmdtable;
7704 #define INIT_G_cmdtable() do { \
7705         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7706 } while (0)
7707
7708 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7709
7710
7711 static void
7712 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7713 {
7714 #if ENABLE_FEATURE_SH_STANDALONE
7715         if (applet_no >= 0) {
7716                 if (APPLET_IS_NOEXEC(applet_no)) {
7717                         clearenv();
7718                         while (*envp)
7719                                 putenv(*envp++);
7720                         run_applet_no_and_exit(applet_no, cmd, argv);
7721                 }
7722                 /* re-exec ourselves with the new arguments */
7723                 execve(bb_busybox_exec_path, argv, envp);
7724                 /* If they called chroot or otherwise made the binary no longer
7725                  * executable, fall through */
7726         }
7727 #endif
7728
7729  repeat:
7730 #ifdef SYSV
7731         do {
7732                 execve(cmd, argv, envp);
7733         } while (errno == EINTR);
7734 #else
7735         execve(cmd, argv, envp);
7736 #endif
7737         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7738                 /* Run "cmd" as a shell script:
7739                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7740                  * "If the execve() function fails with ENOEXEC, the shell
7741                  * shall execute a command equivalent to having a shell invoked
7742                  * with the command name as its first operand,
7743                  * with any remaining arguments passed to the new shell"
7744                  *
7745                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7746                  * just call ourselves.
7747                  *
7748                  * Note that bash reads ~80 chars of the file, and if it sees
7749                  * a zero byte before it sees newline, it doesn't try to
7750                  * interpret it, but fails with "cannot execute binary file"
7751                  * message and exit code 126. For one, this prevents attempts
7752                  * to interpret foreign ELF binaries as shell scripts.
7753                  */
7754                 argv[0] = cmd;
7755                 cmd = (char*) bb_busybox_exec_path;
7756                 /* NB: this is only possible because all callers of shellexec()
7757                  * ensure that the argv[-1] slot exists!
7758                  */
7759                 argv--;
7760                 argv[0] = (char*) "ash";
7761                 goto repeat;
7762         }
7763 }
7764
7765 /*
7766  * Exec a program.  Never returns.  If you change this routine, you may
7767  * have to change the find_command routine as well.
7768  * argv[-1] must exist and be writable! See tryexec() for why.
7769  */
7770 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7771 static void shellexec(char *prog, char **argv, const char *path, int idx)
7772 {
7773         char *cmdname;
7774         int e;
7775         char **envp;
7776         int exerrno;
7777         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7778
7779         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7780         if (strchr(prog, '/') != NULL
7781 #if ENABLE_FEATURE_SH_STANDALONE
7782          || (applet_no = find_applet_by_name(prog)) >= 0
7783 #endif
7784         ) {
7785                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7786                 if (applet_no >= 0) {
7787                         /* We tried execing ourself, but it didn't work.
7788                          * Maybe /proc/self/exe doesn't exist?
7789                          * Try $PATH search.
7790                          */
7791                         goto try_PATH;
7792                 }
7793                 e = errno;
7794         } else {
7795  try_PATH:
7796                 e = ENOENT;
7797                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7798                         if (--idx < 0 && pathopt == NULL) {
7799                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7800                                 if (errno != ENOENT && errno != ENOTDIR)
7801                                         e = errno;
7802                         }
7803                         stunalloc(cmdname);
7804                 }
7805         }
7806
7807         /* Map to POSIX errors */
7808         switch (e) {
7809         case EACCES:
7810                 exerrno = 126;
7811                 break;
7812         case ENOENT:
7813                 exerrno = 127;
7814                 break;
7815         default:
7816                 exerrno = 2;
7817                 break;
7818         }
7819         exitstatus = exerrno;
7820         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7821                 prog, e, suppress_int));
7822         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7823         /* NOTREACHED */
7824 }
7825
7826 static void
7827 printentry(struct tblentry *cmdp)
7828 {
7829         int idx;
7830         const char *path;
7831         char *name;
7832
7833         idx = cmdp->param.index;
7834         path = pathval();
7835         do {
7836                 name = path_advance(&path, cmdp->cmdname);
7837                 stunalloc(name);
7838         } while (--idx >= 0);
7839         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7840 }
7841
7842 /*
7843  * Clear out command entries.  The argument specifies the first entry in
7844  * PATH which has changed.
7845  */
7846 static void
7847 clearcmdentry(int firstchange)
7848 {
7849         struct tblentry **tblp;
7850         struct tblentry **pp;
7851         struct tblentry *cmdp;
7852
7853         INT_OFF;
7854         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7855                 pp = tblp;
7856                 while ((cmdp = *pp) != NULL) {
7857                         if ((cmdp->cmdtype == CMDNORMAL &&
7858                              cmdp->param.index >= firstchange)
7859                          || (cmdp->cmdtype == CMDBUILTIN &&
7860                              builtinloc >= firstchange)
7861                         ) {
7862                                 *pp = cmdp->next;
7863                                 free(cmdp);
7864                         } else {
7865                                 pp = &cmdp->next;
7866                         }
7867                 }
7868         }
7869         INT_ON;
7870 }
7871
7872 /*
7873  * Locate a command in the command hash table.  If "add" is nonzero,
7874  * add the command to the table if it is not already present.  The
7875  * variable "lastcmdentry" is set to point to the address of the link
7876  * pointing to the entry, so that delete_cmd_entry can delete the
7877  * entry.
7878  *
7879  * Interrupts must be off if called with add != 0.
7880  */
7881 static struct tblentry **lastcmdentry;
7882
7883 static struct tblentry *
7884 cmdlookup(const char *name, int add)
7885 {
7886         unsigned int hashval;
7887         const char *p;
7888         struct tblentry *cmdp;
7889         struct tblentry **pp;
7890
7891         p = name;
7892         hashval = (unsigned char)*p << 4;
7893         while (*p)
7894                 hashval += (unsigned char)*p++;
7895         hashval &= 0x7FFF;
7896         pp = &cmdtable[hashval % CMDTABLESIZE];
7897         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7898                 if (strcmp(cmdp->cmdname, name) == 0)
7899                         break;
7900                 pp = &cmdp->next;
7901         }
7902         if (add && cmdp == NULL) {
7903                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7904                                 + strlen(name)
7905                                 /* + 1 - already done because
7906                                  * tblentry::cmdname is char[1] */);
7907                 /*cmdp->next = NULL; - ckzalloc did it */
7908                 cmdp->cmdtype = CMDUNKNOWN;
7909                 strcpy(cmdp->cmdname, name);
7910         }
7911         lastcmdentry = pp;
7912         return cmdp;
7913 }
7914
7915 /*
7916  * Delete the command entry returned on the last lookup.
7917  */
7918 static void
7919 delete_cmd_entry(void)
7920 {
7921         struct tblentry *cmdp;
7922
7923         INT_OFF;
7924         cmdp = *lastcmdentry;
7925         *lastcmdentry = cmdp->next;
7926         if (cmdp->cmdtype == CMDFUNCTION)
7927                 freefunc(cmdp->param.func);
7928         free(cmdp);
7929         INT_ON;
7930 }
7931
7932 /*
7933  * Add a new command entry, replacing any existing command entry for
7934  * the same name - except special builtins.
7935  */
7936 static void
7937 addcmdentry(char *name, struct cmdentry *entry)
7938 {
7939         struct tblentry *cmdp;
7940
7941         cmdp = cmdlookup(name, 1);
7942         if (cmdp->cmdtype == CMDFUNCTION) {
7943                 freefunc(cmdp->param.func);
7944         }
7945         cmdp->cmdtype = entry->cmdtype;
7946         cmdp->param = entry->u;
7947         cmdp->rehash = 0;
7948 }
7949
7950 static int FAST_FUNC
7951 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7952 {
7953         struct tblentry **pp;
7954         struct tblentry *cmdp;
7955         int c;
7956         struct cmdentry entry;
7957         char *name;
7958
7959         if (nextopt("r") != '\0') {
7960                 clearcmdentry(0);
7961                 return 0;
7962         }
7963
7964         if (*argptr == NULL) {
7965                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7966                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7967                                 if (cmdp->cmdtype == CMDNORMAL)
7968                                         printentry(cmdp);
7969                         }
7970                 }
7971                 return 0;
7972         }
7973
7974         c = 0;
7975         while ((name = *argptr) != NULL) {
7976                 cmdp = cmdlookup(name, 0);
7977                 if (cmdp != NULL
7978                  && (cmdp->cmdtype == CMDNORMAL
7979                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7980                 ) {
7981                         delete_cmd_entry();
7982                 }
7983                 find_command(name, &entry, DO_ERR, pathval());
7984                 if (entry.cmdtype == CMDUNKNOWN)
7985                         c = 1;
7986                 argptr++;
7987         }
7988         return c;
7989 }
7990
7991 /*
7992  * Called when a cd is done.  Marks all commands so the next time they
7993  * are executed they will be rehashed.
7994  */
7995 static void
7996 hashcd(void)
7997 {
7998         struct tblentry **pp;
7999         struct tblentry *cmdp;
8000
8001         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8002                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8003                         if (cmdp->cmdtype == CMDNORMAL
8004                          || (cmdp->cmdtype == CMDBUILTIN
8005                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8006                              && builtinloc > 0)
8007                         ) {
8008                                 cmdp->rehash = 1;
8009                         }
8010                 }
8011         }
8012 }
8013
8014 /*
8015  * Fix command hash table when PATH changed.
8016  * Called before PATH is changed.  The argument is the new value of PATH;
8017  * pathval() still returns the old value at this point.
8018  * Called with interrupts off.
8019  */
8020 static void FAST_FUNC
8021 changepath(const char *new)
8022 {
8023         const char *old;
8024         int firstchange;
8025         int idx;
8026         int idx_bltin;
8027
8028         old = pathval();
8029         firstchange = 9999;     /* assume no change */
8030         idx = 0;
8031         idx_bltin = -1;
8032         for (;;) {
8033                 if (*old != *new) {
8034                         firstchange = idx;
8035                         if ((*old == '\0' && *new == ':')
8036                          || (*old == ':' && *new == '\0')
8037                         ) {
8038                                 firstchange++;
8039                         }
8040                         old = new;      /* ignore subsequent differences */
8041                 }
8042                 if (*new == '\0')
8043                         break;
8044                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8045                         idx_bltin = idx;
8046                 if (*new == ':')
8047                         idx++;
8048                 new++;
8049                 old++;
8050         }
8051         if (builtinloc < 0 && idx_bltin >= 0)
8052                 builtinloc = idx_bltin;             /* zap builtins */
8053         if (builtinloc >= 0 && idx_bltin < 0)
8054                 firstchange = 0;
8055         clearcmdentry(firstchange);
8056         builtinloc = idx_bltin;
8057 }
8058 enum {
8059         TEOF,
8060         TNL,
8061         TREDIR,
8062         TWORD,
8063         TSEMI,
8064         TBACKGND,
8065         TAND,
8066         TOR,
8067         TPIPE,
8068         TLP,
8069         TRP,
8070         TENDCASE,
8071         TENDBQUOTE,
8072         TNOT,
8073         TCASE,
8074         TDO,
8075         TDONE,
8076         TELIF,
8077         TELSE,
8078         TESAC,
8079         TFI,
8080         TFOR,
8081 #if BASH_FUNCTION
8082         TFUNCTION,
8083 #endif
8084         TIF,
8085         TIN,
8086         TTHEN,
8087         TUNTIL,
8088         TWHILE,
8089         TBEGIN,
8090         TEND
8091 };
8092 typedef smallint token_id_t;
8093
8094 /* Nth bit indicates if token marks the end of a list */
8095 enum {
8096         tokendlist = 0
8097         /*  0 */ | (1u << TEOF)
8098         /*  1 */ | (0u << TNL)
8099         /*  2 */ | (0u << TREDIR)
8100         /*  3 */ | (0u << TWORD)
8101         /*  4 */ | (0u << TSEMI)
8102         /*  5 */ | (0u << TBACKGND)
8103         /*  6 */ | (0u << TAND)
8104         /*  7 */ | (0u << TOR)
8105         /*  8 */ | (0u << TPIPE)
8106         /*  9 */ | (0u << TLP)
8107         /* 10 */ | (1u << TRP)
8108         /* 11 */ | (1u << TENDCASE)
8109         /* 12 */ | (1u << TENDBQUOTE)
8110         /* 13 */ | (0u << TNOT)
8111         /* 14 */ | (0u << TCASE)
8112         /* 15 */ | (1u << TDO)
8113         /* 16 */ | (1u << TDONE)
8114         /* 17 */ | (1u << TELIF)
8115         /* 18 */ | (1u << TELSE)
8116         /* 19 */ | (1u << TESAC)
8117         /* 20 */ | (1u << TFI)
8118         /* 21 */ | (0u << TFOR)
8119 #if BASH_FUNCTION
8120         /* 22 */ | (0u << TFUNCTION)
8121 #endif
8122         /* 23 */ | (0u << TIF)
8123         /* 24 */ | (0u << TIN)
8124         /* 25 */ | (1u << TTHEN)
8125         /* 26 */ | (0u << TUNTIL)
8126         /* 27 */ | (0u << TWHILE)
8127         /* 28 */ | (0u << TBEGIN)
8128         /* 29 */ | (1u << TEND)
8129         , /* thus far 29 bits used */
8130 };
8131
8132 static const char *const tokname_array[] = {
8133         "end of file",
8134         "newline",
8135         "redirection",
8136         "word",
8137         ";",
8138         "&",
8139         "&&",
8140         "||",
8141         "|",
8142         "(",
8143         ")",
8144         ";;",
8145         "`",
8146 #define KWDOFFSET 13
8147         /* the following are keywords */
8148         "!",
8149         "case",
8150         "do",
8151         "done",
8152         "elif",
8153         "else",
8154         "esac",
8155         "fi",
8156         "for",
8157 #if BASH_FUNCTION
8158         "function",
8159 #endif
8160         "if",
8161         "in",
8162         "then",
8163         "until",
8164         "while",
8165         "{",
8166         "}",
8167 };
8168
8169 /* Wrapper around strcmp for qsort/bsearch/... */
8170 static int
8171 pstrcmp(const void *a, const void *b)
8172 {
8173         return strcmp((char*)a, *(char**)b);
8174 }
8175
8176 static const char *const *
8177 findkwd(const char *s)
8178 {
8179         return bsearch(s, tokname_array + KWDOFFSET,
8180                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8181                         sizeof(tokname_array[0]), pstrcmp);
8182 }
8183
8184 /*
8185  * Locate and print what a word is...
8186  */
8187 static int
8188 describe_command(char *command, const char *path, int describe_command_verbose)
8189 {
8190         struct cmdentry entry;
8191 #if ENABLE_ASH_ALIAS
8192         const struct alias *ap;
8193 #endif
8194
8195         path = path ? path : pathval();
8196
8197         if (describe_command_verbose) {
8198                 out1str(command);
8199         }
8200
8201         /* First look at the keywords */
8202         if (findkwd(command)) {
8203                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8204                 goto out;
8205         }
8206
8207 #if ENABLE_ASH_ALIAS
8208         /* Then look at the aliases */
8209         ap = lookupalias(command, 0);
8210         if (ap != NULL) {
8211                 if (!describe_command_verbose) {
8212                         out1str("alias ");
8213                         printalias(ap);
8214                         return 0;
8215                 }
8216                 out1fmt(" is an alias for %s", ap->val);
8217                 goto out;
8218         }
8219 #endif
8220         /* Brute force */
8221         find_command(command, &entry, DO_ABS, path);
8222
8223         switch (entry.cmdtype) {
8224         case CMDNORMAL: {
8225                 int j = entry.u.index;
8226                 char *p;
8227                 if (j < 0) {
8228                         p = command;
8229                 } else {
8230                         do {
8231                                 p = path_advance(&path, command);
8232                                 stunalloc(p);
8233                         } while (--j >= 0);
8234                 }
8235                 if (describe_command_verbose) {
8236                         out1fmt(" is %s", p);
8237                 } else {
8238                         out1str(p);
8239                 }
8240                 break;
8241         }
8242
8243         case CMDFUNCTION:
8244                 if (describe_command_verbose) {
8245                         out1str(" is a shell function");
8246                 } else {
8247                         out1str(command);
8248                 }
8249                 break;
8250
8251         case CMDBUILTIN:
8252                 if (describe_command_verbose) {
8253                         out1fmt(" is a %sshell builtin",
8254                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8255                                         "special " : nullstr
8256                         );
8257                 } else {
8258                         out1str(command);
8259                 }
8260                 break;
8261
8262         default:
8263                 if (describe_command_verbose) {
8264                         out1str(": not found\n");
8265                 }
8266                 return 127;
8267         }
8268  out:
8269         out1str("\n");
8270         return 0;
8271 }
8272
8273 static int FAST_FUNC
8274 typecmd(int argc UNUSED_PARAM, char **argv)
8275 {
8276         int i = 1;
8277         int err = 0;
8278         int verbose = 1;
8279
8280         /* type -p ... ? (we don't bother checking for 'p') */
8281         if (argv[1] && argv[1][0] == '-') {
8282                 i++;
8283                 verbose = 0;
8284         }
8285         while (argv[i]) {
8286                 err |= describe_command(argv[i++], NULL, verbose);
8287         }
8288         return err;
8289 }
8290
8291 #if ENABLE_ASH_CMDCMD
8292 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8293 static char **
8294 parse_command_args(char **argv, const char **path)
8295 {
8296         char *cp, c;
8297
8298         for (;;) {
8299                 cp = *++argv;
8300                 if (!cp)
8301                         return NULL;
8302                 if (*cp++ != '-')
8303                         break;
8304                 c = *cp++;
8305                 if (!c)
8306                         break;
8307                 if (c == '-' && !*cp) {
8308                         if (!*++argv)
8309                                 return NULL;
8310                         break;
8311                 }
8312                 do {
8313                         switch (c) {
8314                         case 'p':
8315                                 *path = bb_default_path;
8316                                 break;
8317                         default:
8318                                 /* run 'typecmd' for other options */
8319                                 return NULL;
8320                         }
8321                         c = *cp++;
8322                 } while (c);
8323         }
8324         return argv;
8325 }
8326
8327 static int FAST_FUNC
8328 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8329 {
8330         char *cmd;
8331         int c;
8332         enum {
8333                 VERIFY_BRIEF = 1,
8334                 VERIFY_VERBOSE = 2,
8335         } verify = 0;
8336         const char *path = NULL;
8337
8338         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8339          * never reaches this function.
8340          */
8341
8342         while ((c = nextopt("pvV")) != '\0')
8343                 if (c == 'V')
8344                         verify |= VERIFY_VERBOSE;
8345                 else if (c == 'v')
8346                         /*verify |= VERIFY_BRIEF*/;
8347 #if DEBUG
8348                 else if (c != 'p')
8349                         abort();
8350 #endif
8351                 else
8352                         path = bb_default_path;
8353
8354         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8355         cmd = *argptr;
8356         if (/*verify && */ cmd)
8357                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8358
8359         return 0;
8360 }
8361 #endif
8362
8363
8364 /*static int funcblocksize;     // size of structures in function */
8365 /*static int funcstringsize;    // size of strings in node */
8366 static void *funcblock;         /* block to allocate function from */
8367 static char *funcstring_end;    /* end of block to allocate strings from */
8368
8369 /* flags in argument to evaltree */
8370 #define EV_EXIT    01           /* exit after evaluating tree */
8371 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8372
8373 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8374         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8375         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8376         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8377         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8378         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8379         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8380         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8381         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8382         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8383         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8384         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8385         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8386         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8387         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8388         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8389         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8390         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8391 #if BASH_REDIR_OUTPUT
8392         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8393 #endif
8394         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8395         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8396         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8397         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8398         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8399         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8400         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8401         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8402         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8403 };
8404
8405 static int calcsize(int funcblocksize, union node *n);
8406
8407 static int
8408 sizenodelist(int funcblocksize, struct nodelist *lp)
8409 {
8410         while (lp) {
8411                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8412                 funcblocksize = calcsize(funcblocksize, lp->n);
8413                 lp = lp->next;
8414         }
8415         return funcblocksize;
8416 }
8417
8418 static int
8419 calcsize(int funcblocksize, union node *n)
8420 {
8421         if (n == NULL)
8422                 return funcblocksize;
8423         funcblocksize += nodesize[n->type];
8424         switch (n->type) {
8425         case NCMD:
8426                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8427                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8428                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8429                 break;
8430         case NPIPE:
8431                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8432                 break;
8433         case NREDIR:
8434         case NBACKGND:
8435         case NSUBSHELL:
8436                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8437                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8438                 break;
8439         case NAND:
8440         case NOR:
8441         case NSEMI:
8442         case NWHILE:
8443         case NUNTIL:
8444                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8445                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8446                 break;
8447         case NIF:
8448                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8449                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8450                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8451                 break;
8452         case NFOR:
8453                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8454                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8455                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8456                 break;
8457         case NCASE:
8458                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8459                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8460                 break;
8461         case NCLIST:
8462                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8463                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8464                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8465                 break;
8466         case NDEFUN:
8467         case NARG:
8468                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8469                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8470                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8471                 break;
8472         case NTO:
8473 #if BASH_REDIR_OUTPUT
8474         case NTO2:
8475 #endif
8476         case NCLOBBER:
8477         case NFROM:
8478         case NFROMTO:
8479         case NAPPEND:
8480                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8481                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8482                 break;
8483         case NTOFD:
8484         case NFROMFD:
8485                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8486                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8487         break;
8488         case NHERE:
8489         case NXHERE:
8490                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8491                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8492                 break;
8493         case NNOT:
8494                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8495                 break;
8496         };
8497         return funcblocksize;
8498 }
8499
8500 static char *
8501 nodeckstrdup(char *s)
8502 {
8503         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8504         return strcpy(funcstring_end, s);
8505 }
8506
8507 static union node *copynode(union node *);
8508
8509 static struct nodelist *
8510 copynodelist(struct nodelist *lp)
8511 {
8512         struct nodelist *start;
8513         struct nodelist **lpp;
8514
8515         lpp = &start;
8516         while (lp) {
8517                 *lpp = funcblock;
8518                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8519                 (*lpp)->n = copynode(lp->n);
8520                 lp = lp->next;
8521                 lpp = &(*lpp)->next;
8522         }
8523         *lpp = NULL;
8524         return start;
8525 }
8526
8527 static union node *
8528 copynode(union node *n)
8529 {
8530         union node *new;
8531
8532         if (n == NULL)
8533                 return NULL;
8534         new = funcblock;
8535         funcblock = (char *) funcblock + nodesize[n->type];
8536
8537         switch (n->type) {
8538         case NCMD:
8539                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8540                 new->ncmd.args = copynode(n->ncmd.args);
8541                 new->ncmd.assign = copynode(n->ncmd.assign);
8542                 break;
8543         case NPIPE:
8544                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8545                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8546                 break;
8547         case NREDIR:
8548         case NBACKGND:
8549         case NSUBSHELL:
8550                 new->nredir.redirect = copynode(n->nredir.redirect);
8551                 new->nredir.n = copynode(n->nredir.n);
8552                 break;
8553         case NAND:
8554         case NOR:
8555         case NSEMI:
8556         case NWHILE:
8557         case NUNTIL:
8558                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8559                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8560                 break;
8561         case NIF:
8562                 new->nif.elsepart = copynode(n->nif.elsepart);
8563                 new->nif.ifpart = copynode(n->nif.ifpart);
8564                 new->nif.test = copynode(n->nif.test);
8565                 break;
8566         case NFOR:
8567                 new->nfor.var = nodeckstrdup(n->nfor.var);
8568                 new->nfor.body = copynode(n->nfor.body);
8569                 new->nfor.args = copynode(n->nfor.args);
8570                 break;
8571         case NCASE:
8572                 new->ncase.cases = copynode(n->ncase.cases);
8573                 new->ncase.expr = copynode(n->ncase.expr);
8574                 break;
8575         case NCLIST:
8576                 new->nclist.body = copynode(n->nclist.body);
8577                 new->nclist.pattern = copynode(n->nclist.pattern);
8578                 new->nclist.next = copynode(n->nclist.next);
8579                 break;
8580         case NDEFUN:
8581         case NARG:
8582                 new->narg.backquote = copynodelist(n->narg.backquote);
8583                 new->narg.text = nodeckstrdup(n->narg.text);
8584                 new->narg.next = copynode(n->narg.next);
8585                 break;
8586         case NTO:
8587 #if BASH_REDIR_OUTPUT
8588         case NTO2:
8589 #endif
8590         case NCLOBBER:
8591         case NFROM:
8592         case NFROMTO:
8593         case NAPPEND:
8594                 new->nfile.fname = copynode(n->nfile.fname);
8595                 new->nfile.fd = n->nfile.fd;
8596                 new->nfile.next = copynode(n->nfile.next);
8597                 break;
8598         case NTOFD:
8599         case NFROMFD:
8600                 new->ndup.vname = copynode(n->ndup.vname);
8601                 new->ndup.dupfd = n->ndup.dupfd;
8602                 new->ndup.fd = n->ndup.fd;
8603                 new->ndup.next = copynode(n->ndup.next);
8604                 break;
8605         case NHERE:
8606         case NXHERE:
8607                 new->nhere.doc = copynode(n->nhere.doc);
8608                 new->nhere.fd = n->nhere.fd;
8609                 new->nhere.next = copynode(n->nhere.next);
8610                 break;
8611         case NNOT:
8612                 new->nnot.com = copynode(n->nnot.com);
8613                 break;
8614         };
8615         new->type = n->type;
8616         return new;
8617 }
8618
8619 /*
8620  * Make a copy of a parse tree.
8621  */
8622 static struct funcnode *
8623 copyfunc(union node *n)
8624 {
8625         struct funcnode *f;
8626         size_t blocksize;
8627
8628         /*funcstringsize = 0;*/
8629         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8630         f = ckzalloc(blocksize /* + funcstringsize */);
8631         funcblock = (char *) f + offsetof(struct funcnode, n);
8632         funcstring_end = (char *) f + blocksize;
8633         copynode(n);
8634         /* f->count = 0; - ckzalloc did it */
8635         return f;
8636 }
8637
8638 /*
8639  * Define a shell function.
8640  */
8641 static void
8642 defun(union node *func)
8643 {
8644         struct cmdentry entry;
8645
8646         INT_OFF;
8647         entry.cmdtype = CMDFUNCTION;
8648         entry.u.func = copyfunc(func);
8649         addcmdentry(func->narg.text, &entry);
8650         INT_ON;
8651 }
8652
8653 /* Reasons for skipping commands (see comment on breakcmd routine) */
8654 #define SKIPBREAK      (1 << 0)
8655 #define SKIPCONT       (1 << 1)
8656 #define SKIPFUNC       (1 << 2)
8657 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8658 static int skipcount;           /* number of levels to skip */
8659 static int funcnest;            /* depth of function calls */
8660 static int loopnest;            /* current loop nesting level */
8661
8662 /* Forward decl way out to parsing code - dotrap needs it */
8663 static int evalstring(char *s, int flags);
8664
8665 /* Called to execute a trap.
8666  * Single callsite - at the end of evaltree().
8667  * If we return non-zero, evaltree raises EXEXIT exception.
8668  *
8669  * Perhaps we should avoid entering new trap handlers
8670  * while we are executing a trap handler. [is it a TODO?]
8671  */
8672 static void
8673 dotrap(void)
8674 {
8675         uint8_t *g;
8676         int sig;
8677         uint8_t last_status;
8678
8679         if (!pending_sig)
8680                 return;
8681
8682         last_status = exitstatus;
8683         pending_sig = 0;
8684         barrier();
8685
8686         TRACE(("dotrap entered\n"));
8687         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8688                 char *p;
8689
8690                 if (!*g)
8691                         continue;
8692
8693                 if (evalskip) {
8694                         pending_sig = sig;
8695                         break;
8696                 }
8697
8698                 p = trap[sig];
8699                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8700                  * don't upset it by resetting gotsig[SIGINT-1] */
8701                 if (sig == SIGINT && !p)
8702                         continue;
8703
8704                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8705                 *g = 0;
8706                 if (!p)
8707                         continue;
8708                 evalstring(p, 0);
8709         }
8710         exitstatus = last_status;
8711         TRACE(("dotrap returns\n"));
8712 }
8713
8714 /* forward declarations - evaluation is fairly recursive business... */
8715 static int evalloop(union node *, int);
8716 static int evalfor(union node *, int);
8717 static int evalcase(union node *, int);
8718 static int evalsubshell(union node *, int);
8719 static void expredir(union node *);
8720 static int evalpipe(union node *, int);
8721 static int evalcommand(union node *, int);
8722 static int evalbltin(const struct builtincmd *, int, char **, int);
8723 static void prehash(union node *);
8724
8725 /*
8726  * Evaluate a parse tree.  The value is left in the global variable
8727  * exitstatus.
8728  */
8729 static int
8730 evaltree(union node *n, int flags)
8731 {
8732         int checkexit = 0;
8733         int (*evalfn)(union node *, int);
8734         int status = 0;
8735
8736         if (n == NULL) {
8737                 TRACE(("evaltree(NULL) called\n"));
8738                 goto out;
8739         }
8740         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8741
8742         dotrap();
8743
8744         switch (n->type) {
8745         default:
8746 #if DEBUG
8747                 out1fmt("Node type = %d\n", n->type);
8748                 fflush_all();
8749                 break;
8750 #endif
8751         case NNOT:
8752                 status = !evaltree(n->nnot.com, EV_TESTED);
8753                 goto setstatus;
8754         case NREDIR:
8755                 expredir(n->nredir.redirect);
8756                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8757                 if (!status) {
8758                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8759                 }
8760                 if (n->nredir.redirect)
8761                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8762                 goto setstatus;
8763         case NCMD:
8764                 evalfn = evalcommand;
8765  checkexit:
8766                 if (eflag && !(flags & EV_TESTED))
8767                         checkexit = ~0;
8768                 goto calleval;
8769         case NFOR:
8770                 evalfn = evalfor;
8771                 goto calleval;
8772         case NWHILE:
8773         case NUNTIL:
8774                 evalfn = evalloop;
8775                 goto calleval;
8776         case NSUBSHELL:
8777         case NBACKGND:
8778                 evalfn = evalsubshell;
8779                 goto checkexit;
8780         case NPIPE:
8781                 evalfn = evalpipe;
8782                 goto checkexit;
8783         case NCASE:
8784                 evalfn = evalcase;
8785                 goto calleval;
8786         case NAND:
8787         case NOR:
8788         case NSEMI: {
8789
8790 #if NAND + 1 != NOR
8791 #error NAND + 1 != NOR
8792 #endif
8793 #if NOR + 1 != NSEMI
8794 #error NOR + 1 != NSEMI
8795 #endif
8796                 unsigned is_or = n->type - NAND;
8797                 status = evaltree(
8798                         n->nbinary.ch1,
8799                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8800                 );
8801                 if ((!status) == is_or || evalskip)
8802                         break;
8803                 n = n->nbinary.ch2;
8804  evaln:
8805                 evalfn = evaltree;
8806  calleval:
8807                 status = evalfn(n, flags);
8808                 goto setstatus;
8809         }
8810         case NIF:
8811                 status = evaltree(n->nif.test, EV_TESTED);
8812                 if (evalskip)
8813                         break;
8814                 if (!status) {
8815                         n = n->nif.ifpart;
8816                         goto evaln;
8817                 }
8818                 if (n->nif.elsepart) {
8819                         n = n->nif.elsepart;
8820                         goto evaln;
8821                 }
8822                 status = 0;
8823                 goto setstatus;
8824         case NDEFUN:
8825                 defun(n);
8826                 /* Not necessary. To test it:
8827                  * "false; f() { qwerty; }; echo $?" should print 0.
8828                  */
8829                 /* status = 0; */
8830  setstatus:
8831                 exitstatus = status;
8832                 break;
8833         }
8834  out:
8835         /* Order of checks below is important:
8836          * signal handlers trigger before exit caused by "set -e".
8837          */
8838         dotrap();
8839
8840         if (checkexit & status)
8841                 raise_exception(EXEXIT);
8842         if (flags & EV_EXIT)
8843                 raise_exception(EXEXIT);
8844
8845         TRACE(("leaving evaltree (no interrupts)\n"));
8846         return exitstatus;
8847 }
8848
8849 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8850 static
8851 #endif
8852 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8853
8854 static int
8855 skiploop(void)
8856 {
8857         int skip = evalskip;
8858
8859         switch (skip) {
8860         case 0:
8861                 break;
8862         case SKIPBREAK:
8863         case SKIPCONT:
8864                 if (--skipcount <= 0) {
8865                         evalskip = 0;
8866                         break;
8867                 }
8868                 skip = SKIPBREAK;
8869                 break;
8870         }
8871         return skip;
8872 }
8873
8874 static int
8875 evalloop(union node *n, int flags)
8876 {
8877         int skip;
8878         int status;
8879
8880         loopnest++;
8881         status = 0;
8882         flags &= EV_TESTED;
8883         do {
8884                 int i;
8885
8886                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8887                 skip = skiploop();
8888                 if (skip == SKIPFUNC)
8889                         status = i;
8890                 if (skip)
8891                         continue;
8892                 if (n->type != NWHILE)
8893                         i = !i;
8894                 if (i != 0)
8895                         break;
8896                 status = evaltree(n->nbinary.ch2, flags);
8897                 skip = skiploop();
8898         } while (!(skip & ~SKIPCONT));
8899         loopnest--;
8900
8901         return status;
8902 }
8903
8904 static int
8905 evalfor(union node *n, int flags)
8906 {
8907         struct arglist arglist;
8908         union node *argp;
8909         struct strlist *sp;
8910         struct stackmark smark;
8911         int status = 0;
8912
8913         setstackmark(&smark);
8914         arglist.list = NULL;
8915         arglist.lastp = &arglist.list;
8916         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8917                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8918         }
8919         *arglist.lastp = NULL;
8920
8921         loopnest++;
8922         flags &= EV_TESTED;
8923         for (sp = arglist.list; sp; sp = sp->next) {
8924                 setvar0(n->nfor.var, sp->text);
8925                 status = evaltree(n->nfor.body, flags);
8926                 if (skiploop() & ~SKIPCONT)
8927                         break;
8928         }
8929         loopnest--;
8930         popstackmark(&smark);
8931
8932         return status;
8933 }
8934
8935 static int
8936 evalcase(union node *n, int flags)
8937 {
8938         union node *cp;
8939         union node *patp;
8940         struct arglist arglist;
8941         struct stackmark smark;
8942         int status = 0;
8943
8944         setstackmark(&smark);
8945         arglist.list = NULL;
8946         arglist.lastp = &arglist.list;
8947         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8948         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8949                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8950                         if (casematch(patp, arglist.list->text)) {
8951                                 /* Ensure body is non-empty as otherwise
8952                                  * EV_EXIT may prevent us from setting the
8953                                  * exit status.
8954                                  */
8955                                 if (evalskip == 0 && cp->nclist.body) {
8956                                         status = evaltree(cp->nclist.body, flags);
8957                                 }
8958                                 goto out;
8959                         }
8960                 }
8961         }
8962  out:
8963         popstackmark(&smark);
8964
8965         return status;
8966 }
8967
8968 /*
8969  * Kick off a subshell to evaluate a tree.
8970  */
8971 static int
8972 evalsubshell(union node *n, int flags)
8973 {
8974         struct job *jp;
8975         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8976         int status;
8977
8978         expredir(n->nredir.redirect);
8979         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8980                 goto nofork;
8981         INT_OFF;
8982         if (backgnd == FORK_FG)
8983                 get_tty_state();
8984         jp = makejob(/*n,*/ 1);
8985         if (forkshell(jp, n, backgnd) == 0) {
8986                 /* child */
8987                 INT_ON;
8988                 flags |= EV_EXIT;
8989                 if (backgnd)
8990                         flags &= ~EV_TESTED;
8991  nofork:
8992                 redirect(n->nredir.redirect, 0);
8993                 evaltreenr(n->nredir.n, flags);
8994                 /* never returns */
8995         }
8996         /* parent */
8997         status = 0;
8998         if (backgnd == FORK_FG)
8999                 status = waitforjob(jp);
9000         INT_ON;
9001         return status;
9002 }
9003
9004 /*
9005  * Compute the names of the files in a redirection list.
9006  */
9007 static void fixredir(union node *, const char *, int);
9008 static void
9009 expredir(union node *n)
9010 {
9011         union node *redir;
9012
9013         for (redir = n; redir; redir = redir->nfile.next) {
9014                 struct arglist fn;
9015
9016                 fn.list = NULL;
9017                 fn.lastp = &fn.list;
9018                 switch (redir->type) {
9019                 case NFROMTO:
9020                 case NFROM:
9021                 case NTO:
9022 #if BASH_REDIR_OUTPUT
9023                 case NTO2:
9024 #endif
9025                 case NCLOBBER:
9026                 case NAPPEND:
9027                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9028                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9029 #if BASH_REDIR_OUTPUT
9030  store_expfname:
9031 #endif
9032 #if 0
9033 // By the design of stack allocator, the loop of this kind:
9034 //      while true; do while true; do break; done </dev/null; done
9035 // will look like a memory leak: ash plans to free expfname's
9036 // of "/dev/null" as soon as it finishes running the loop
9037 // (in this case, never).
9038 // This "fix" is wrong:
9039                         if (redir->nfile.expfname)
9040                                 stunalloc(redir->nfile.expfname);
9041 // It results in corrupted state of stacked allocations.
9042 #endif
9043                         redir->nfile.expfname = fn.list->text;
9044                         break;
9045                 case NFROMFD:
9046                 case NTOFD: /* >& */
9047                         if (redir->ndup.vname) {
9048                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9049                                 if (fn.list == NULL)
9050                                         ash_msg_and_raise_error("redir error");
9051 #if BASH_REDIR_OUTPUT
9052 //FIXME: we used expandarg with different args!
9053                                 if (!isdigit_str9(fn.list->text)) {
9054                                         /* >&file, not >&fd */
9055                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9056                                                 ash_msg_and_raise_error("redir error");
9057                                         redir->type = NTO2;
9058                                         goto store_expfname;
9059                                 }
9060 #endif
9061                                 fixredir(redir, fn.list->text, 1);
9062                         }
9063                         break;
9064                 }
9065         }
9066 }
9067
9068 /*
9069  * Evaluate a pipeline.  All the processes in the pipeline are children
9070  * of the process creating the pipeline.  (This differs from some versions
9071  * of the shell, which make the last process in a pipeline the parent
9072  * of all the rest.)
9073  */
9074 static int
9075 evalpipe(union node *n, int flags)
9076 {
9077         struct job *jp;
9078         struct nodelist *lp;
9079         int pipelen;
9080         int prevfd;
9081         int pip[2];
9082         int status = 0;
9083
9084         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9085         pipelen = 0;
9086         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9087                 pipelen++;
9088         flags |= EV_EXIT;
9089         INT_OFF;
9090         if (n->npipe.pipe_backgnd == 0)
9091                 get_tty_state();
9092         jp = makejob(/*n,*/ pipelen);
9093         prevfd = -1;
9094         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9095                 prehash(lp->n);
9096                 pip[1] = -1;
9097                 if (lp->next) {
9098                         if (pipe(pip) < 0) {
9099                                 close(prevfd);
9100                                 ash_msg_and_raise_error("pipe call failed");
9101                         }
9102                 }
9103                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9104                         /* child */
9105                         INT_ON;
9106                         if (pip[1] >= 0) {
9107                                 close(pip[0]);
9108                         }
9109                         if (prevfd > 0) {
9110                                 dup2(prevfd, 0);
9111                                 close(prevfd);
9112                         }
9113                         if (pip[1] > 1) {
9114                                 dup2(pip[1], 1);
9115                                 close(pip[1]);
9116                         }
9117                         evaltreenr(lp->n, flags);
9118                         /* never returns */
9119                 }
9120                 /* parent */
9121                 if (prevfd >= 0)
9122                         close(prevfd);
9123                 prevfd = pip[0];
9124                 /* Don't want to trigger debugging */
9125                 if (pip[1] != -1)
9126                         close(pip[1]);
9127         }
9128         if (n->npipe.pipe_backgnd == 0) {
9129                 status = waitforjob(jp);
9130                 TRACE(("evalpipe:  job done exit status %d\n", status));
9131         }
9132         INT_ON;
9133
9134         return status;
9135 }
9136
9137 /*
9138  * Controls whether the shell is interactive or not.
9139  */
9140 static void
9141 setinteractive(int on)
9142 {
9143         static smallint is_interactive;
9144
9145         if (++on == is_interactive)
9146                 return;
9147         is_interactive = on;
9148         setsignal(SIGINT);
9149         setsignal(SIGQUIT);
9150         setsignal(SIGTERM);
9151 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9152         if (is_interactive > 1) {
9153                 /* Looks like they want an interactive shell */
9154                 static smallint did_banner;
9155
9156                 if (!did_banner) {
9157                         /* note: ash and hush share this string */
9158                         out1fmt("\n\n%s %s\n"
9159                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9160                                 "\n",
9161                                 bb_banner,
9162                                 "built-in shell (ash)"
9163                         );
9164                         did_banner = 1;
9165                 }
9166         }
9167 #endif
9168 }
9169
9170 static void
9171 optschanged(void)
9172 {
9173 #if DEBUG
9174         opentrace();
9175 #endif
9176         setinteractive(iflag);
9177         setjobctl(mflag);
9178 #if ENABLE_FEATURE_EDITING_VI
9179         if (viflag)
9180                 line_input_state->flags |= VI_MODE;
9181         else
9182                 line_input_state->flags &= ~VI_MODE;
9183 #else
9184         viflag = 0; /* forcibly keep the option off */
9185 #endif
9186 }
9187
9188 static struct localvar *localvars;
9189
9190 /*
9191  * Called after a function returns.
9192  * Interrupts must be off.
9193  */
9194 static void
9195 poplocalvars(void)
9196 {
9197         struct localvar *lvp;
9198         struct var *vp;
9199
9200         while ((lvp = localvars) != NULL) {
9201                 localvars = lvp->next;
9202                 vp = lvp->vp;
9203                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9204                 if (vp == NULL) {       /* $- saved */
9205                         memcpy(optlist, lvp->text, sizeof(optlist));
9206                         free((char*)lvp->text);
9207                         optschanged();
9208                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9209                         unsetvar(vp->var_text);
9210                 } else {
9211                         if (vp->var_func)
9212                                 vp->var_func(var_end(lvp->text));
9213                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9214                                 free((char*)vp->var_text);
9215                         vp->flags = lvp->flags;
9216                         vp->var_text = lvp->text;
9217                 }
9218                 free(lvp);
9219         }
9220 }
9221
9222 static int
9223 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9224 {
9225         volatile struct shparam saveparam;
9226         struct localvar *volatile savelocalvars;
9227         struct jmploc *volatile savehandler;
9228         struct jmploc jmploc;
9229         int e;
9230
9231         saveparam = shellparam;
9232         savelocalvars = localvars;
9233         savehandler = exception_handler;
9234         e = setjmp(jmploc.loc);
9235         if (e) {
9236                 goto funcdone;
9237         }
9238         INT_OFF;
9239         exception_handler = &jmploc;
9240         localvars = NULL;
9241         shellparam.malloced = 0;
9242         func->count++;
9243         funcnest++;
9244         INT_ON;
9245         shellparam.nparam = argc - 1;
9246         shellparam.p = argv + 1;
9247 #if ENABLE_ASH_GETOPTS
9248         shellparam.optind = 1;
9249         shellparam.optoff = -1;
9250 #endif
9251         evaltree(func->n.narg.next, flags & EV_TESTED);
9252  funcdone:
9253         INT_OFF;
9254         funcnest--;
9255         freefunc(func);
9256         poplocalvars();
9257         localvars = savelocalvars;
9258         freeparam(&shellparam);
9259         shellparam = saveparam;
9260         exception_handler = savehandler;
9261         INT_ON;
9262         evalskip &= ~SKIPFUNC;
9263         return e;
9264 }
9265
9266 /*
9267  * Make a variable a local variable.  When a variable is made local, it's
9268  * value and flags are saved in a localvar structure.  The saved values
9269  * will be restored when the shell function returns.  We handle the name
9270  * "-" as a special case: it makes changes to "set +-options" local
9271  * (options will be restored on return from the function).
9272  */
9273 static void
9274 mklocal(char *name)
9275 {
9276         struct localvar *lvp;
9277         struct var **vpp;
9278         struct var *vp;
9279         char *eq = strchr(name, '=');
9280
9281         INT_OFF;
9282         /* Cater for duplicate "local". Examples:
9283          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9284          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9285          */
9286         lvp = localvars;
9287         while (lvp) {
9288                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9289                         if (eq)
9290                                 setvareq(name, 0);
9291                         /* else:
9292                          * it's a duplicate "local VAR" declaration, do nothing
9293                          */
9294                         goto ret;
9295                 }
9296                 lvp = lvp->next;
9297         }
9298
9299         lvp = ckzalloc(sizeof(*lvp));
9300         if (LONE_DASH(name)) {
9301                 char *p;
9302                 p = ckmalloc(sizeof(optlist));
9303                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9304                 vp = NULL;
9305         } else {
9306                 vpp = hashvar(name);
9307                 vp = *findvar(vpp, name);
9308                 if (vp == NULL) {
9309                         /* variable did not exist yet */
9310                         if (eq)
9311                                 setvareq(name, VSTRFIXED);
9312                         else
9313                                 setvar(name, NULL, VSTRFIXED);
9314                         vp = *vpp;      /* the new variable */
9315                         lvp->flags = VUNSET;
9316                 } else {
9317                         lvp->text = vp->var_text;
9318                         lvp->flags = vp->flags;
9319                         /* make sure neither "struct var" nor string gets freed
9320                          * during (un)setting:
9321                          */
9322                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9323                         if (eq)
9324                                 setvareq(name, 0);
9325                         else
9326                                 /* "local VAR" unsets VAR: */
9327                                 setvar0(name, NULL);
9328                 }
9329         }
9330         lvp->vp = vp;
9331         lvp->next = localvars;
9332         localvars = lvp;
9333  ret:
9334         INT_ON;
9335 }
9336
9337 /*
9338  * The "local" command.
9339  */
9340 static int FAST_FUNC
9341 localcmd(int argc UNUSED_PARAM, char **argv)
9342 {
9343         char *name;
9344
9345         if (!funcnest)
9346                 ash_msg_and_raise_error("not in a function");
9347
9348         argv = argptr;
9349         while ((name = *argv++) != NULL) {
9350                 mklocal(name);
9351         }
9352         return 0;
9353 }
9354
9355 static int FAST_FUNC
9356 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9357 {
9358         return 1;
9359 }
9360
9361 static int FAST_FUNC
9362 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9363 {
9364         return 0;
9365 }
9366
9367 static int FAST_FUNC
9368 execcmd(int argc UNUSED_PARAM, char **argv)
9369 {
9370         optionarg = NULL;
9371         while (nextopt("a:") != '\0')
9372                 /* nextopt() sets optionarg to "-a ARGV0" */;
9373
9374         argv = argptr;
9375         if (argv[0]) {
9376                 char *prog;
9377
9378                 iflag = 0;              /* exit on error */
9379                 mflag = 0;
9380                 optschanged();
9381                 /* We should set up signals for "exec CMD"
9382                  * the same way as for "CMD" without "exec".
9383                  * But optschanged->setinteractive->setsignal
9384                  * still thought we are a root shell. Therefore, for example,
9385                  * SIGQUIT is still set to IGN. Fix it:
9386                  */
9387                 shlvl++;
9388                 setsignal(SIGQUIT);
9389                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9390                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9391                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9392
9393                 prog = argv[0];
9394                 if (optionarg)
9395                         argv[0] = optionarg;
9396                 shellexec(prog, argv, pathval(), 0);
9397                 /* NOTREACHED */
9398         }
9399         return 0;
9400 }
9401
9402 /*
9403  * The return command.
9404  */
9405 static int FAST_FUNC
9406 returncmd(int argc UNUSED_PARAM, char **argv)
9407 {
9408         /*
9409          * If called outside a function, do what ksh does;
9410          * skip the rest of the file.
9411          */
9412         evalskip = SKIPFUNC;
9413         return argv[1] ? number(argv[1]) : exitstatus;
9414 }
9415
9416 /* Forward declarations for builtintab[] */
9417 static int breakcmd(int, char **) FAST_FUNC;
9418 static int dotcmd(int, char **) FAST_FUNC;
9419 static int evalcmd(int, char **, int) FAST_FUNC;
9420 static int exitcmd(int, char **) FAST_FUNC;
9421 static int exportcmd(int, char **) FAST_FUNC;
9422 #if ENABLE_ASH_GETOPTS
9423 static int getoptscmd(int, char **) FAST_FUNC;
9424 #endif
9425 #if ENABLE_ASH_HELP
9426 static int helpcmd(int, char **) FAST_FUNC;
9427 #endif
9428 #if MAX_HISTORY
9429 static int historycmd(int, char **) FAST_FUNC;
9430 #endif
9431 #if ENABLE_FEATURE_SH_MATH
9432 static int letcmd(int, char **) FAST_FUNC;
9433 #endif
9434 static int readcmd(int, char **) FAST_FUNC;
9435 static int setcmd(int, char **) FAST_FUNC;
9436 static int shiftcmd(int, char **) FAST_FUNC;
9437 static int timescmd(int, char **) FAST_FUNC;
9438 static int trapcmd(int, char **) FAST_FUNC;
9439 static int umaskcmd(int, char **) FAST_FUNC;
9440 static int unsetcmd(int, char **) FAST_FUNC;
9441 static int ulimitcmd(int, char **) FAST_FUNC;
9442
9443 #define BUILTIN_NOSPEC          "0"
9444 #define BUILTIN_SPECIAL         "1"
9445 #define BUILTIN_REGULAR         "2"
9446 #define BUILTIN_SPEC_REG        "3"
9447 #define BUILTIN_ASSIGN          "4"
9448 #define BUILTIN_SPEC_ASSG       "5"
9449 #define BUILTIN_REG_ASSG        "6"
9450 #define BUILTIN_SPEC_REG_ASSG   "7"
9451
9452 /* Stubs for calling non-FAST_FUNC's */
9453 #if ENABLE_ASH_ECHO
9454 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9455 #endif
9456 #if ENABLE_ASH_PRINTF
9457 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9458 #endif
9459 #if ENABLE_ASH_TEST || BASH_TEST2
9460 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9461 #endif
9462
9463 /* Keep these in proper order since it is searched via bsearch() */
9464 static const struct builtincmd builtintab[] = {
9465         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9466         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9467 #if ENABLE_ASH_TEST
9468         { BUILTIN_REGULAR       "["       , testcmd    },
9469 #endif
9470 #if BASH_TEST2
9471         { BUILTIN_REGULAR       "[["      , testcmd    },
9472 #endif
9473 #if ENABLE_ASH_ALIAS
9474         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9475 #endif
9476 #if JOBS
9477         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9478 #endif
9479         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9480         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9481         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9482 #if ENABLE_ASH_CMDCMD
9483         { BUILTIN_REGULAR       "command" , commandcmd },
9484 #endif
9485         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9486 #if ENABLE_ASH_ECHO
9487         { BUILTIN_REGULAR       "echo"    , echocmd    },
9488 #endif
9489         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9490         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9491         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9492         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9493         { BUILTIN_REGULAR       "false"   , falsecmd   },
9494 #if JOBS
9495         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9496 #endif
9497 #if ENABLE_ASH_GETOPTS
9498         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9499 #endif
9500         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9501 #if ENABLE_ASH_HELP
9502         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9503 #endif
9504 #if MAX_HISTORY
9505         { BUILTIN_NOSPEC        "history" , historycmd },
9506 #endif
9507 #if JOBS
9508         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9509         { BUILTIN_REGULAR       "kill"    , killcmd    },
9510 #endif
9511 #if ENABLE_FEATURE_SH_MATH
9512         { BUILTIN_NOSPEC        "let"     , letcmd     },
9513 #endif
9514         { BUILTIN_ASSIGN        "local"   , localcmd   },
9515 #if ENABLE_ASH_PRINTF
9516         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9517 #endif
9518         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9519         { BUILTIN_REGULAR       "read"    , readcmd    },
9520         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9521         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9522         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9523         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9524 #if BASH_SOURCE
9525         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9526 #endif
9527 #if ENABLE_ASH_TEST
9528         { BUILTIN_REGULAR       "test"    , testcmd    },
9529 #endif
9530         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9531         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9532         { BUILTIN_REGULAR       "true"    , truecmd    },
9533         { BUILTIN_NOSPEC        "type"    , typecmd    },
9534         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9535         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9536 #if ENABLE_ASH_ALIAS
9537         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9538 #endif
9539         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9540         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9541 };
9542
9543 /* Should match the above table! */
9544 #define COMMANDCMD (builtintab + \
9545         /* . : */       2 + \
9546         /* [ */         1 * ENABLE_ASH_TEST + \
9547         /* [[ */        1 * BASH_TEST2 + \
9548         /* alias */     1 * ENABLE_ASH_ALIAS + \
9549         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9550         /* break cd cddir  */   3)
9551 #define EVALCMD (COMMANDCMD + \
9552         /* command */   1 * ENABLE_ASH_CMDCMD + \
9553         /* continue */  1 + \
9554         /* echo */      1 * ENABLE_ASH_ECHO + \
9555         0)
9556 #define EXECCMD (EVALCMD + \
9557         /* eval */      1)
9558
9559 /*
9560  * Search the table of builtin commands.
9561  */
9562 static int
9563 pstrcmp1(const void *a, const void *b)
9564 {
9565         return strcmp((char*)a, *(char**)b + 1);
9566 }
9567 static struct builtincmd *
9568 find_builtin(const char *name)
9569 {
9570         struct builtincmd *bp;
9571
9572         bp = bsearch(
9573                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9574                 pstrcmp1
9575         );
9576         return bp;
9577 }
9578
9579 /*
9580  * Execute a simple command.
9581  */
9582 static int
9583 isassignment(const char *p)
9584 {
9585         const char *q = endofname(p);
9586         if (p == q)
9587                 return 0;
9588         return *q == '=';
9589 }
9590 static int FAST_FUNC
9591 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9592 {
9593         /* Preserve exitstatus of a previous possible redirection
9594          * as POSIX mandates */
9595         return back_exitstatus;
9596 }
9597 static int
9598 evalcommand(union node *cmd, int flags)
9599 {
9600         static const struct builtincmd null_bltin = {
9601                 "\0\0", bltincmd /* why three NULs? */
9602         };
9603         struct stackmark smark;
9604         union node *argp;
9605         struct arglist arglist;
9606         struct arglist varlist;
9607         char **argv;
9608         int argc;
9609         const struct strlist *sp;
9610         struct cmdentry cmdentry;
9611         struct job *jp;
9612         char *lastarg;
9613         const char *path;
9614         int spclbltin;
9615         int status;
9616         char **nargv;
9617         struct builtincmd *bcmd;
9618         smallint cmd_is_exec;
9619         smallint pseudovarflag = 0;
9620
9621         /* First expand the arguments. */
9622         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9623         setstackmark(&smark);
9624         back_exitstatus = 0;
9625
9626         cmdentry.cmdtype = CMDBUILTIN;
9627         cmdentry.u.cmd = &null_bltin;
9628         varlist.lastp = &varlist.list;
9629         *varlist.lastp = NULL;
9630         arglist.lastp = &arglist.list;
9631         *arglist.lastp = NULL;
9632
9633         argc = 0;
9634         if (cmd->ncmd.args) {
9635                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9636                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9637         }
9638
9639         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9640                 struct strlist **spp;
9641
9642                 spp = arglist.lastp;
9643                 if (pseudovarflag && isassignment(argp->narg.text))
9644                         expandarg(argp, &arglist, EXP_VARTILDE);
9645                 else
9646                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9647
9648                 for (sp = *spp; sp; sp = sp->next)
9649                         argc++;
9650         }
9651
9652         /* Reserve one extra spot at the front for shellexec. */
9653         nargv = stalloc(sizeof(char *) * (argc + 2));
9654         argv = ++nargv;
9655         for (sp = arglist.list; sp; sp = sp->next) {
9656                 TRACE(("evalcommand arg: %s\n", sp->text));
9657                 *nargv++ = sp->text;
9658         }
9659         *nargv = NULL;
9660
9661         lastarg = NULL;
9662         if (iflag && funcnest == 0 && argc > 0)
9663                 lastarg = nargv[-1];
9664
9665         preverrout_fd = 2;
9666         expredir(cmd->ncmd.redirect);
9667         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9668
9669         path = vpath.var_text;
9670         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9671                 struct strlist **spp;
9672                 char *p;
9673
9674                 spp = varlist.lastp;
9675                 expandarg(argp, &varlist, EXP_VARTILDE);
9676
9677                 /*
9678                  * Modify the command lookup path, if a PATH= assignment
9679                  * is present
9680                  */
9681                 p = (*spp)->text;
9682                 if (varcmp(p, path) == 0)
9683                         path = p;
9684         }
9685
9686         /* Print the command if xflag is set. */
9687         if (xflag) {
9688                 int n;
9689                 const char *p = " %s" + 1;
9690
9691                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9692                 sp = varlist.list;
9693                 for (n = 0; n < 2; n++) {
9694                         while (sp) {
9695                                 fdprintf(preverrout_fd, p, sp->text);
9696                                 sp = sp->next;
9697                                 p = " %s";
9698                         }
9699                         sp = arglist.list;
9700                 }
9701                 safe_write(preverrout_fd, "\n", 1);
9702         }
9703
9704         cmd_is_exec = 0;
9705         spclbltin = -1;
9706
9707         /* Now locate the command. */
9708         if (argc) {
9709                 int cmd_flag = DO_ERR;
9710 #if ENABLE_ASH_CMDCMD
9711                 const char *oldpath = path + 5;
9712 #endif
9713                 path += 5;
9714                 for (;;) {
9715                         find_command(argv[0], &cmdentry, cmd_flag, path);
9716                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9717                                 flush_stdout_stderr();
9718                                 status = 127;
9719                                 goto bail;
9720                         }
9721
9722                         /* implement bltin and command here */
9723                         if (cmdentry.cmdtype != CMDBUILTIN)
9724                                 break;
9725                         if (spclbltin < 0)
9726                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9727                         if (cmdentry.u.cmd == EXECCMD)
9728                                 cmd_is_exec = 1;
9729 #if ENABLE_ASH_CMDCMD
9730                         if (cmdentry.u.cmd == COMMANDCMD) {
9731                                 path = oldpath;
9732                                 nargv = parse_command_args(argv, &path);
9733                                 if (!nargv)
9734                                         break;
9735                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9736                                  * nargv => "PROG". path is updated if -p.
9737                                  */
9738                                 argc -= nargv - argv;
9739                                 argv = nargv;
9740                                 cmd_flag |= DO_NOFUNC;
9741                         } else
9742 #endif
9743                                 break;
9744                 }
9745         }
9746
9747         if (status) {
9748  bail:
9749                 exitstatus = status;
9750
9751                 /* We have a redirection error. */
9752                 if (spclbltin > 0)
9753                         raise_exception(EXERROR);
9754
9755                 goto out;
9756         }
9757
9758         /* Execute the command. */
9759         switch (cmdentry.cmdtype) {
9760         default: {
9761
9762 #if ENABLE_FEATURE_SH_NOFORK
9763 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9764  *     around run_nofork_applet() call.
9765  * (2) Should this check also be done in forkshell()?
9766  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9767  */
9768                 /* find_command() encodes applet_no as (-2 - applet_no) */
9769                 int applet_no = (- cmdentry.u.index - 2);
9770                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9771                         listsetvar(varlist.list, VEXPORT|VSTACK);
9772                         /* run <applet>_main() */
9773                         status = run_nofork_applet(applet_no, argv);
9774                         break;
9775                 }
9776 #endif
9777                 /* Can we avoid forking off? For example, very last command
9778                  * in a script or a subshell does not need forking,
9779                  * we can just exec it.
9780                  */
9781                 if (!(flags & EV_EXIT) || may_have_traps) {
9782                         /* No, forking off a child is necessary */
9783                         INT_OFF;
9784                         get_tty_state();
9785                         jp = makejob(/*cmd,*/ 1);
9786                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9787                                 /* parent */
9788                                 status = waitforjob(jp);
9789                                 INT_ON;
9790                                 TRACE(("forked child exited with %d\n", status));
9791                                 break;
9792                         }
9793                         /* child */
9794                         FORCE_INT_ON;
9795                         /* fall through to exec'ing external program */
9796                 }
9797                 listsetvar(varlist.list, VEXPORT|VSTACK);
9798                 shellexec(argv[0], argv, path, cmdentry.u.index);
9799                 /* NOTREACHED */
9800         } /* default */
9801         case CMDBUILTIN:
9802                 cmdenviron = varlist.list;
9803                 if (cmdenviron) {
9804                         struct strlist *list = cmdenviron;
9805                         int i = VNOSET;
9806                         if (spclbltin > 0 || argc == 0) {
9807                                 i = 0;
9808                                 if (cmd_is_exec && argc > 1)
9809                                         i = VEXPORT;
9810                         }
9811                         listsetvar(list, i);
9812                 }
9813                 /* Tight loop with builtins only:
9814                  * "while kill -0 $child; do true; done"
9815                  * will never exit even if $child died, unless we do this
9816                  * to reap the zombie and make kill detect that it's gone: */
9817                 dowait(DOWAIT_NONBLOCK, NULL);
9818
9819                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9820                         if (exception_type == EXERROR && spclbltin <= 0) {
9821                                 FORCE_INT_ON;
9822                                 goto readstatus;
9823                         }
9824  raise:
9825                         longjmp(exception_handler->loc, 1);
9826                 }
9827                 goto readstatus;
9828
9829         case CMDFUNCTION:
9830                 listsetvar(varlist.list, 0);
9831                 /* See above for the rationale */
9832                 dowait(DOWAIT_NONBLOCK, NULL);
9833                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9834                         goto raise;
9835  readstatus:
9836                 status = exitstatus;
9837                 break;
9838         } /* switch */
9839
9840  out:
9841         if (cmd->ncmd.redirect)
9842                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9843         if (lastarg) {
9844                 /* dsl: I think this is intended to be used to support
9845                  * '_' in 'vi' command mode during line editing...
9846                  * However I implemented that within libedit itself.
9847                  */
9848                 setvar0("_", lastarg);
9849         }
9850         popstackmark(&smark);
9851
9852         return status;
9853 }
9854
9855 static int
9856 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9857 {
9858         char *volatile savecmdname;
9859         struct jmploc *volatile savehandler;
9860         struct jmploc jmploc;
9861         int status;
9862         int i;
9863
9864         savecmdname = commandname;
9865         savehandler = exception_handler;
9866         i = setjmp(jmploc.loc);
9867         if (i)
9868                 goto cmddone;
9869         exception_handler = &jmploc;
9870         commandname = argv[0];
9871         argptr = argv + 1;
9872         optptr = NULL;                  /* initialize nextopt */
9873         if (cmd == EVALCMD)
9874                 status = evalcmd(argc, argv, flags);
9875         else
9876                 status = (*cmd->builtin)(argc, argv);
9877         flush_stdout_stderr();
9878         status |= ferror(stdout);
9879         exitstatus = status;
9880  cmddone:
9881         clearerr(stdout);
9882         commandname = savecmdname;
9883         exception_handler = savehandler;
9884
9885         return i;
9886 }
9887
9888 static int
9889 goodname(const char *p)
9890 {
9891         return endofname(p)[0] == '\0';
9892 }
9893
9894
9895 /*
9896  * Search for a command.  This is called before we fork so that the
9897  * location of the command will be available in the parent as well as
9898  * the child.  The check for "goodname" is an overly conservative
9899  * check that the name will not be subject to expansion.
9900  */
9901 static void
9902 prehash(union node *n)
9903 {
9904         struct cmdentry entry;
9905
9906         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9907                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9908 }
9909
9910
9911 /* ============ Builtin commands
9912  *
9913  * Builtin commands whose functions are closely tied to evaluation
9914  * are implemented here.
9915  */
9916
9917 /*
9918  * Handle break and continue commands.  Break, continue, and return are
9919  * all handled by setting the evalskip flag.  The evaluation routines
9920  * above all check this flag, and if it is set they start skipping
9921  * commands rather than executing them.  The variable skipcount is
9922  * the number of loops to break/continue, or the number of function
9923  * levels to return.  (The latter is always 1.)  It should probably
9924  * be an error to break out of more loops than exist, but it isn't
9925  * in the standard shell so we don't make it one here.
9926  */
9927 static int FAST_FUNC
9928 breakcmd(int argc UNUSED_PARAM, char **argv)
9929 {
9930         int n = argv[1] ? number(argv[1]) : 1;
9931
9932         if (n <= 0)
9933                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9934         if (n > loopnest)
9935                 n = loopnest;
9936         if (n > 0) {
9937                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9938                 skipcount = n;
9939         }
9940         return 0;
9941 }
9942
9943
9944 /*
9945  * This implements the input routines used by the parser.
9946  */
9947
9948 enum {
9949         INPUT_PUSH_FILE = 1,
9950         INPUT_NOFILE_OK = 2,
9951 };
9952
9953 static smallint checkkwd;
9954 /* values of checkkwd variable */
9955 #define CHKALIAS        0x1
9956 #define CHKKWD          0x2
9957 #define CHKNL           0x4
9958
9959 /*
9960  * Push a string back onto the input at this current parsefile level.
9961  * We handle aliases this way.
9962  */
9963 #if !ENABLE_ASH_ALIAS
9964 #define pushstring(s, ap) pushstring(s)
9965 #endif
9966 static void
9967 pushstring(char *s, struct alias *ap)
9968 {
9969         struct strpush *sp;
9970         int len;
9971
9972         len = strlen(s);
9973         INT_OFF;
9974         if (g_parsefile->strpush) {
9975                 sp = ckzalloc(sizeof(*sp));
9976                 sp->prev = g_parsefile->strpush;
9977         } else {
9978                 sp = &(g_parsefile->basestrpush);
9979         }
9980         g_parsefile->strpush = sp;
9981         sp->prev_string = g_parsefile->next_to_pgetc;
9982         sp->prev_left_in_line = g_parsefile->left_in_line;
9983         sp->unget = g_parsefile->unget;
9984         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9985 #if ENABLE_ASH_ALIAS
9986         sp->ap = ap;
9987         if (ap) {
9988                 ap->flag |= ALIASINUSE;
9989                 sp->string = s;
9990         }
9991 #endif
9992         g_parsefile->next_to_pgetc = s;
9993         g_parsefile->left_in_line = len;
9994         g_parsefile->unget = 0;
9995         INT_ON;
9996 }
9997
9998 static void
9999 popstring(void)
10000 {
10001         struct strpush *sp = g_parsefile->strpush;
10002
10003         INT_OFF;
10004 #if ENABLE_ASH_ALIAS
10005         if (sp->ap) {
10006                 if (g_parsefile->next_to_pgetc[-1] == ' '
10007                  || g_parsefile->next_to_pgetc[-1] == '\t'
10008                 ) {
10009                         checkkwd |= CHKALIAS;
10010                 }
10011                 if (sp->string != sp->ap->val) {
10012                         free(sp->string);
10013                 }
10014                 sp->ap->flag &= ~ALIASINUSE;
10015                 if (sp->ap->flag & ALIASDEAD) {
10016                         unalias(sp->ap->name);
10017                 }
10018         }
10019 #endif
10020         g_parsefile->next_to_pgetc = sp->prev_string;
10021         g_parsefile->left_in_line = sp->prev_left_in_line;
10022         g_parsefile->unget = sp->unget;
10023         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10024         g_parsefile->strpush = sp->prev;
10025         if (sp != &(g_parsefile->basestrpush))
10026                 free(sp);
10027         INT_ON;
10028 }
10029
10030 static int
10031 preadfd(void)
10032 {
10033         int nr;
10034         char *buf = g_parsefile->buf;
10035
10036         g_parsefile->next_to_pgetc = buf;
10037 #if ENABLE_FEATURE_EDITING
10038  retry:
10039         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10040                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10041         else {
10042                 int timeout = -1;
10043 # if ENABLE_ASH_IDLE_TIMEOUT
10044                 if (iflag) {
10045                         const char *tmout_var = lookupvar("TMOUT");
10046                         if (tmout_var) {
10047                                 timeout = atoi(tmout_var) * 1000;
10048                                 if (timeout <= 0)
10049                                         timeout = -1;
10050                         }
10051                 }
10052 # endif
10053 # if ENABLE_FEATURE_TAB_COMPLETION
10054                 line_input_state->path_lookup = pathval();
10055 # endif
10056                 reinit_unicode_for_ash();
10057                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10058                 if (nr == 0) {
10059                         /* ^C pressed, "convert" to SIGINT */
10060                         write(STDOUT_FILENO, "^C", 2);
10061                         if (trap[SIGINT]) {
10062                                 buf[0] = '\n';
10063                                 buf[1] = '\0';
10064                                 raise(SIGINT);
10065                                 return 1;
10066                         }
10067                         exitstatus = 128 + SIGINT;
10068                         bb_putchar('\n');
10069                         goto retry;
10070                 }
10071                 if (nr < 0) {
10072                         if (errno == 0) {
10073                                 /* Ctrl+D pressed */
10074                                 nr = 0;
10075                         }
10076 # if ENABLE_ASH_IDLE_TIMEOUT
10077                         else if (errno == EAGAIN && timeout > 0) {
10078                                 puts("\007timed out waiting for input: auto-logout");
10079                                 exitshell();
10080                         }
10081 # endif
10082                 }
10083         }
10084 #else
10085         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10086 #endif
10087
10088 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10089         if (nr < 0) {
10090                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10091                         int flags = fcntl(0, F_GETFL);
10092                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10093                                 flags &= ~O_NONBLOCK;
10094                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10095                                         out2str("sh: turning off NDELAY mode\n");
10096                                         goto retry;
10097                                 }
10098                         }
10099                 }
10100         }
10101 #endif
10102         return nr;
10103 }
10104
10105 /*
10106  * Refill the input buffer and return the next input character:
10107  *
10108  * 1) If a string was pushed back on the input, pop it;
10109  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10110  *    or we are reading from a string so we can't refill the buffer,
10111  *    return EOF.
10112  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10113  * 4) Process input up to the next newline, deleting nul characters.
10114  */
10115 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10116 #define pgetc_debug(...) ((void)0)
10117 static int pgetc(void);
10118 static int
10119 preadbuffer(void)
10120 {
10121         char *q;
10122         int more;
10123
10124         if (g_parsefile->strpush) {
10125 #if ENABLE_ASH_ALIAS
10126                 if (g_parsefile->left_in_line == -1
10127                  && g_parsefile->strpush->ap
10128                  && g_parsefile->next_to_pgetc[-1] != ' '
10129                  && g_parsefile->next_to_pgetc[-1] != '\t'
10130                 ) {
10131                         pgetc_debug("preadbuffer PEOA");
10132                         return PEOA;
10133                 }
10134 #endif
10135                 popstring();
10136                 return pgetc();
10137         }
10138         /* on both branches above g_parsefile->left_in_line < 0.
10139          * "pgetc" needs refilling.
10140          */
10141
10142         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10143          * pungetc() may increment it a few times.
10144          * Assuming it won't increment it to less than -90.
10145          */
10146         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10147                 pgetc_debug("preadbuffer PEOF1");
10148                 /* even in failure keep left_in_line and next_to_pgetc
10149                  * in lock step, for correct multi-layer pungetc.
10150                  * left_in_line was decremented before preadbuffer(),
10151                  * must inc next_to_pgetc: */
10152                 g_parsefile->next_to_pgetc++;
10153                 return PEOF;
10154         }
10155
10156         more = g_parsefile->left_in_buffer;
10157         if (more <= 0) {
10158                 flush_stdout_stderr();
10159  again:
10160                 more = preadfd();
10161                 if (more <= 0) {
10162                         /* don't try reading again */
10163                         g_parsefile->left_in_line = -99;
10164                         pgetc_debug("preadbuffer PEOF2");
10165                         g_parsefile->next_to_pgetc++;
10166                         return PEOF;
10167                 }
10168         }
10169
10170         /* Find out where's the end of line.
10171          * Set g_parsefile->left_in_line
10172          * and g_parsefile->left_in_buffer acordingly.
10173          * NUL chars are deleted.
10174          */
10175         q = g_parsefile->next_to_pgetc;
10176         for (;;) {
10177                 char c;
10178
10179                 more--;
10180
10181                 c = *q;
10182                 if (c == '\0') {
10183                         memmove(q, q + 1, more);
10184                 } else {
10185                         q++;
10186                         if (c == '\n') {
10187                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10188                                 break;
10189                         }
10190                 }
10191
10192                 if (more <= 0) {
10193                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10194                         if (g_parsefile->left_in_line < 0)
10195                                 goto again;
10196                         break;
10197                 }
10198         }
10199         g_parsefile->left_in_buffer = more;
10200
10201         if (vflag) {
10202                 char save = *q;
10203                 *q = '\0';
10204                 out2str(g_parsefile->next_to_pgetc);
10205                 *q = save;
10206         }
10207
10208         pgetc_debug("preadbuffer at %d:%p'%s'",
10209                         g_parsefile->left_in_line,
10210                         g_parsefile->next_to_pgetc,
10211                         g_parsefile->next_to_pgetc);
10212         return (unsigned char)*g_parsefile->next_to_pgetc++;
10213 }
10214
10215 static void
10216 nlprompt(void)
10217 {
10218         g_parsefile->linno++;
10219         setprompt_if(doprompt, 2);
10220 }
10221 static void
10222 nlnoprompt(void)
10223 {
10224         g_parsefile->linno++;
10225         needprompt = doprompt;
10226 }
10227
10228 static int
10229 pgetc(void)
10230 {
10231         int c;
10232
10233         pgetc_debug("pgetc at %d:%p'%s'",
10234                         g_parsefile->left_in_line,
10235                         g_parsefile->next_to_pgetc,
10236                         g_parsefile->next_to_pgetc);
10237         if (g_parsefile->unget)
10238                 return g_parsefile->lastc[--g_parsefile->unget];
10239
10240         if (--g_parsefile->left_in_line >= 0)
10241                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10242         else
10243                 c = preadbuffer();
10244
10245         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10246         g_parsefile->lastc[0] = c;
10247
10248         return c;
10249 }
10250
10251 #if ENABLE_ASH_ALIAS
10252 static int
10253 pgetc_without_PEOA(void)
10254 {
10255         int c;
10256         do {
10257                 pgetc_debug("pgetc at %d:%p'%s'",
10258                                 g_parsefile->left_in_line,
10259                                 g_parsefile->next_to_pgetc,
10260                                 g_parsefile->next_to_pgetc);
10261                 c = pgetc();
10262         } while (c == PEOA);
10263         return c;
10264 }
10265 #else
10266 # define pgetc_without_PEOA() pgetc()
10267 #endif
10268
10269 /*
10270  * Read a line from the script.
10271  */
10272 static char *
10273 pfgets(char *line, int len)
10274 {
10275         char *p = line;
10276         int nleft = len;
10277         int c;
10278
10279         while (--nleft > 0) {
10280                 c = pgetc_without_PEOA();
10281                 if (c == PEOF) {
10282                         if (p == line)
10283                                 return NULL;
10284                         break;
10285                 }
10286                 *p++ = c;
10287                 if (c == '\n')
10288                         break;
10289         }
10290         *p = '\0';
10291         return line;
10292 }
10293
10294 /*
10295  * Undo a call to pgetc.  Only two characters may be pushed back.
10296  * PEOF may be pushed back.
10297  */
10298 static void
10299 pungetc(void)
10300 {
10301         g_parsefile->unget++;
10302 }
10303
10304 /* This one eats backslash+newline */
10305 static int
10306 pgetc_eatbnl(void)
10307 {
10308         int c;
10309
10310         while ((c = pgetc()) == '\\') {
10311                 if (pgetc() != '\n') {
10312                         pungetc();
10313                         break;
10314                 }
10315
10316                 nlprompt();
10317         }
10318
10319         return c;
10320 }
10321
10322 /*
10323  * To handle the "." command, a stack of input files is used.  Pushfile
10324  * adds a new entry to the stack and popfile restores the previous level.
10325  */
10326 static void
10327 pushfile(void)
10328 {
10329         struct parsefile *pf;
10330
10331         pf = ckzalloc(sizeof(*pf));
10332         pf->prev = g_parsefile;
10333         pf->pf_fd = -1;
10334         /*pf->strpush = NULL; - ckzalloc did it */
10335         /*pf->basestrpush.prev = NULL;*/
10336         /*pf->unget = 0;*/
10337         g_parsefile = pf;
10338 }
10339
10340 static void
10341 popfile(void)
10342 {
10343         struct parsefile *pf = g_parsefile;
10344
10345         if (pf == &basepf)
10346                 return;
10347
10348         INT_OFF;
10349         if (pf->pf_fd >= 0)
10350                 close(pf->pf_fd);
10351         free(pf->buf);
10352         while (pf->strpush)
10353                 popstring();
10354         g_parsefile = pf->prev;
10355         free(pf);
10356         INT_ON;
10357 }
10358
10359 /*
10360  * Return to top level.
10361  */
10362 static void
10363 popallfiles(void)
10364 {
10365         while (g_parsefile != &basepf)
10366                 popfile();
10367 }
10368
10369 /*
10370  * Close the file(s) that the shell is reading commands from.  Called
10371  * after a fork is done.
10372  */
10373 static void
10374 closescript(void)
10375 {
10376         popallfiles();
10377         if (g_parsefile->pf_fd > 0) {
10378                 close(g_parsefile->pf_fd);
10379                 g_parsefile->pf_fd = 0;
10380         }
10381 }
10382
10383 /*
10384  * Like setinputfile, but takes an open file descriptor.  Call this with
10385  * interrupts off.
10386  */
10387 static void
10388 setinputfd(int fd, int push)
10389 {
10390         if (push) {
10391                 pushfile();
10392                 g_parsefile->buf = NULL;
10393         }
10394         g_parsefile->pf_fd = fd;
10395         if (g_parsefile->buf == NULL)
10396                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10397         g_parsefile->left_in_buffer = 0;
10398         g_parsefile->left_in_line = 0;
10399         g_parsefile->linno = 1;
10400 }
10401
10402 /*
10403  * Set the input to take input from a file.  If push is set, push the
10404  * old input onto the stack first.
10405  */
10406 static int
10407 setinputfile(const char *fname, int flags)
10408 {
10409         int fd;
10410
10411         INT_OFF;
10412         fd = open(fname, O_RDONLY);
10413         if (fd < 0) {
10414                 if (flags & INPUT_NOFILE_OK)
10415                         goto out;
10416                 exitstatus = 127;
10417                 ash_msg_and_raise_error("can't open '%s'", fname);
10418         }
10419         if (fd < 10)
10420                 fd = savefd(fd);
10421         else
10422                 close_on_exec_on(fd);
10423         setinputfd(fd, flags & INPUT_PUSH_FILE);
10424  out:
10425         INT_ON;
10426         return fd;
10427 }
10428
10429 /*
10430  * Like setinputfile, but takes input from a string.
10431  */
10432 static void
10433 setinputstring(char *string)
10434 {
10435         INT_OFF;
10436         pushfile();
10437         g_parsefile->next_to_pgetc = string;
10438         g_parsefile->left_in_line = strlen(string);
10439         g_parsefile->buf = NULL;
10440         g_parsefile->linno = 1;
10441         INT_ON;
10442 }
10443
10444
10445 /*
10446  * Routines to check for mail.
10447  */
10448
10449 #if ENABLE_ASH_MAIL
10450
10451 /* Hash of mtimes of mailboxes */
10452 static unsigned mailtime_hash;
10453 /* Set if MAIL or MAILPATH is changed. */
10454 static smallint mail_var_path_changed;
10455
10456 /*
10457  * Print appropriate message(s) if mail has arrived.
10458  * If mail_var_path_changed is set,
10459  * then the value of MAIL has mail_var_path_changed,
10460  * so we just update the values.
10461  */
10462 static void
10463 chkmail(void)
10464 {
10465         const char *mpath;
10466         char *p;
10467         char *q;
10468         unsigned new_hash;
10469         struct stackmark smark;
10470         struct stat statb;
10471
10472         setstackmark(&smark);
10473         mpath = mpathset() ? mpathval() : mailval();
10474         new_hash = 0;
10475         for (;;) {
10476                 p = path_advance(&mpath, nullstr);
10477                 if (p == NULL)
10478                         break;
10479                 if (*p == '\0')
10480                         continue;
10481                 for (q = p; *q; q++)
10482                         continue;
10483 #if DEBUG
10484                 if (q[-1] != '/')
10485                         abort();
10486 #endif
10487                 q[-1] = '\0';                   /* delete trailing '/' */
10488                 if (stat(p, &statb) < 0) {
10489                         continue;
10490                 }
10491                 /* Very simplistic "hash": just a sum of all mtimes */
10492                 new_hash += (unsigned)statb.st_mtime;
10493         }
10494         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10495                 if (mailtime_hash != 0)
10496                         out2str("you have mail\n");
10497                 mailtime_hash = new_hash;
10498         }
10499         mail_var_path_changed = 0;
10500         popstackmark(&smark);
10501 }
10502
10503 static void FAST_FUNC
10504 changemail(const char *val UNUSED_PARAM)
10505 {
10506         mail_var_path_changed = 1;
10507 }
10508
10509 #endif /* ASH_MAIL */
10510
10511
10512 /* ============ ??? */
10513
10514 /*
10515  * Set the shell parameters.
10516  */
10517 static void
10518 setparam(char **argv)
10519 {
10520         char **newparam;
10521         char **ap;
10522         int nparam;
10523
10524         for (nparam = 0; argv[nparam]; nparam++)
10525                 continue;
10526         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10527         while (*argv) {
10528                 *ap++ = ckstrdup(*argv++);
10529         }
10530         *ap = NULL;
10531         freeparam(&shellparam);
10532         shellparam.malloced = 1;
10533         shellparam.nparam = nparam;
10534         shellparam.p = newparam;
10535 #if ENABLE_ASH_GETOPTS
10536         shellparam.optind = 1;
10537         shellparam.optoff = -1;
10538 #endif
10539 }
10540
10541 /*
10542  * Process shell options.  The global variable argptr contains a pointer
10543  * to the argument list; we advance it past the options.
10544  *
10545  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10546  * For a non-interactive shell, an error condition encountered
10547  * by a special built-in ... shall cause the shell to write a diagnostic message
10548  * to standard error and exit as shown in the following table:
10549  * Error                                           Special Built-In
10550  * ...
10551  * Utility syntax error (option or operand error)  Shall exit
10552  * ...
10553  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10554  * we see that bash does not do that (set "finishes" with error code 1 instead,
10555  * and shell continues), and people rely on this behavior!
10556  * Testcase:
10557  * set -o barfoo 2>/dev/null
10558  * echo $?
10559  *
10560  * Oh well. Let's mimic that.
10561  */
10562 static int
10563 plus_minus_o(char *name, int val)
10564 {
10565         int i;
10566
10567         if (name) {
10568                 for (i = 0; i < NOPTS; i++) {
10569                         if (strcmp(name, optnames(i)) == 0) {
10570                                 optlist[i] = val;
10571                                 return 0;
10572                         }
10573                 }
10574                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10575                 return 1;
10576         }
10577         for (i = 0; i < NOPTS; i++) {
10578                 if (val) {
10579                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10580                 } else {
10581                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10582                 }
10583         }
10584         return 0;
10585 }
10586 static void
10587 setoption(int flag, int val)
10588 {
10589         int i;
10590
10591         for (i = 0; i < NOPTS; i++) {
10592                 if (optletters(i) == flag) {
10593                         optlist[i] = val;
10594                         return;
10595                 }
10596         }
10597         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10598         /* NOTREACHED */
10599 }
10600 static int
10601 options(int cmdline)
10602 {
10603         char *p;
10604         int val;
10605         int c;
10606
10607         if (cmdline)
10608                 minusc = NULL;
10609         while ((p = *argptr) != NULL) {
10610                 c = *p++;
10611                 if (c != '-' && c != '+')
10612                         break;
10613                 argptr++;
10614                 val = 0; /* val = 0 if c == '+' */
10615                 if (c == '-') {
10616                         val = 1;
10617                         if (p[0] == '\0' || LONE_DASH(p)) {
10618                                 if (!cmdline) {
10619                                         /* "-" means turn off -x and -v */
10620                                         if (p[0] == '\0')
10621                                                 xflag = vflag = 0;
10622                                         /* "--" means reset params */
10623                                         else if (*argptr == NULL)
10624                                                 setparam(argptr);
10625                                 }
10626                                 break;    /* "-" or "--" terminates options */
10627                         }
10628                 }
10629                 /* first char was + or - */
10630                 while ((c = *p++) != '\0') {
10631                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10632                         if (c == 'c' && cmdline) {
10633                                 minusc = p;     /* command is after shell args */
10634                         } else if (c == 'o') {
10635                                 if (plus_minus_o(*argptr, val)) {
10636                                         /* it already printed err message */
10637                                         return 1; /* error */
10638                                 }
10639                                 if (*argptr)
10640                                         argptr++;
10641                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10642                                 isloginsh = 1;
10643                         /* bash does not accept +-login, we also won't */
10644                         } else if (cmdline && val && (c == '-')) { /* long options */
10645                                 if (strcmp(p, "login") == 0)
10646                                         isloginsh = 1;
10647                                 break;
10648                         } else {
10649                                 setoption(c, val);
10650                         }
10651                 }
10652         }
10653         return 0;
10654 }
10655
10656 /*
10657  * The shift builtin command.
10658  */
10659 static int FAST_FUNC
10660 shiftcmd(int argc UNUSED_PARAM, char **argv)
10661 {
10662         int n;
10663         char **ap1, **ap2;
10664
10665         n = 1;
10666         if (argv[1])
10667                 n = number(argv[1]);
10668         if (n > shellparam.nparam)
10669                 n = 0; /* bash compat, was = shellparam.nparam; */
10670         INT_OFF;
10671         shellparam.nparam -= n;
10672         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10673                 if (shellparam.malloced)
10674                         free(*ap1);
10675         }
10676         ap2 = shellparam.p;
10677         while ((*ap2++ = *ap1++) != NULL)
10678                 continue;
10679 #if ENABLE_ASH_GETOPTS
10680         shellparam.optind = 1;
10681         shellparam.optoff = -1;
10682 #endif
10683         INT_ON;
10684         return 0;
10685 }
10686
10687 /*
10688  * POSIX requires that 'set' (but not export or readonly) output the
10689  * variables in lexicographic order - by the locale's collating order (sigh).
10690  * Maybe we could keep them in an ordered balanced binary tree
10691  * instead of hashed lists.
10692  * For now just roll 'em through qsort for printing...
10693  */
10694 static int
10695 showvars(const char *sep_prefix, int on, int off)
10696 {
10697         const char *sep;
10698         char **ep, **epend;
10699
10700         ep = listvars(on, off, &epend);
10701         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10702
10703         sep = *sep_prefix ? " " : sep_prefix;
10704
10705         for (; ep < epend; ep++) {
10706                 const char *p;
10707                 const char *q;
10708
10709                 p = strchrnul(*ep, '=');
10710                 q = nullstr;
10711                 if (*p)
10712                         q = single_quote(++p);
10713                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10714         }
10715         return 0;
10716 }
10717
10718 /*
10719  * The set command builtin.
10720  */
10721 static int FAST_FUNC
10722 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10723 {
10724         int retval;
10725
10726         if (!argv[1])
10727                 return showvars(nullstr, 0, VUNSET);
10728
10729         INT_OFF;
10730         retval = options(/*cmdline:*/ 0);
10731         if (retval == 0) { /* if no parse error... */
10732                 optschanged();
10733                 if (*argptr != NULL) {
10734                         setparam(argptr);
10735                 }
10736         }
10737         INT_ON;
10738         return retval;
10739 }
10740
10741 #if ENABLE_ASH_RANDOM_SUPPORT
10742 static void FAST_FUNC
10743 change_random(const char *value)
10744 {
10745         uint32_t t;
10746
10747         if (value == NULL) {
10748                 /* "get", generate */
10749                 t = next_random(&random_gen);
10750                 /* set without recursion */
10751                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10752                 vrandom.flags &= ~VNOFUNC;
10753         } else {
10754                 /* set/reset */
10755                 t = strtoul(value, NULL, 10);
10756                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10757         }
10758 }
10759 #endif
10760
10761 #if ENABLE_ASH_GETOPTS
10762 static int
10763 getopts(char *optstr, char *optvar, char **optfirst)
10764 {
10765         char *p, *q;
10766         char c = '?';
10767         int done = 0;
10768         char sbuf[2];
10769         char **optnext;
10770         int ind = shellparam.optind;
10771         int off = shellparam.optoff;
10772
10773         sbuf[1] = '\0';
10774
10775         shellparam.optind = -1;
10776         optnext = optfirst + ind - 1;
10777
10778         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10779                 p = NULL;
10780         else
10781                 p = optnext[-1] + off;
10782         if (p == NULL || *p == '\0') {
10783                 /* Current word is done, advance */
10784                 p = *optnext;
10785                 if (p == NULL || *p != '-' || *++p == '\0') {
10786  atend:
10787                         p = NULL;
10788                         done = 1;
10789                         goto out;
10790                 }
10791                 optnext++;
10792                 if (LONE_DASH(p))        /* check for "--" */
10793                         goto atend;
10794         }
10795
10796         c = *p++;
10797         for (q = optstr; *q != c;) {
10798                 if (*q == '\0') {
10799                         if (optstr[0] == ':') {
10800                                 sbuf[0] = c;
10801                                 /*sbuf[1] = '\0'; - already is */
10802                                 setvar0("OPTARG", sbuf);
10803                         } else {
10804                                 fprintf(stderr, "Illegal option -%c\n", c);
10805                                 unsetvar("OPTARG");
10806                         }
10807                         c = '?';
10808                         goto out;
10809                 }
10810                 if (*++q == ':')
10811                         q++;
10812         }
10813
10814         if (*++q == ':') {
10815                 if (*p == '\0' && (p = *optnext) == NULL) {
10816                         if (optstr[0] == ':') {
10817                                 sbuf[0] = c;
10818                                 /*sbuf[1] = '\0'; - already is */
10819                                 setvar0("OPTARG", sbuf);
10820                                 c = ':';
10821                         } else {
10822                                 fprintf(stderr, "No arg for -%c option\n", c);
10823                                 unsetvar("OPTARG");
10824                                 c = '?';
10825                         }
10826                         goto out;
10827                 }
10828
10829                 if (p == *optnext)
10830                         optnext++;
10831                 setvar0("OPTARG", p);
10832                 p = NULL;
10833         } else
10834                 setvar0("OPTARG", nullstr);
10835  out:
10836         ind = optnext - optfirst + 1;
10837         setvar("OPTIND", itoa(ind), VNOFUNC);
10838         sbuf[0] = c;
10839         /*sbuf[1] = '\0'; - already is */
10840         setvar0(optvar, sbuf);
10841
10842         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10843         shellparam.optind = ind;
10844
10845         return done;
10846 }
10847
10848 /*
10849  * The getopts builtin.  Shellparam.optnext points to the next argument
10850  * to be processed.  Shellparam.optptr points to the next character to
10851  * be processed in the current argument.  If shellparam.optnext is NULL,
10852  * then it's the first time getopts has been called.
10853  */
10854 static int FAST_FUNC
10855 getoptscmd(int argc, char **argv)
10856 {
10857         char **optbase;
10858
10859         if (argc < 3)
10860                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10861         if (argc == 3) {
10862                 optbase = shellparam.p;
10863                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10864                         shellparam.optind = 1;
10865                         shellparam.optoff = -1;
10866                 }
10867         } else {
10868                 optbase = &argv[3];
10869                 if ((unsigned)shellparam.optind > argc - 2) {
10870                         shellparam.optind = 1;
10871                         shellparam.optoff = -1;
10872                 }
10873         }
10874
10875         return getopts(argv[1], argv[2], optbase);
10876 }
10877 #endif /* ASH_GETOPTS */
10878
10879
10880 /* ============ Shell parser */
10881
10882 struct heredoc {
10883         struct heredoc *next;   /* next here document in list */
10884         union node *here;       /* redirection node */
10885         char *eofmark;          /* string indicating end of input */
10886         smallint striptabs;     /* if set, strip leading tabs */
10887 };
10888
10889 static smallint tokpushback;           /* last token pushed back */
10890 static smallint quoteflag;             /* set if (part of) last token was quoted */
10891 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10892 static struct heredoc *heredoclist;    /* list of here documents to read */
10893 static char *wordtext;                 /* text of last word returned by readtoken */
10894 static struct nodelist *backquotelist;
10895 static union node *redirnode;
10896 static struct heredoc *heredoc;
10897
10898 static const char *
10899 tokname(char *buf, int tok)
10900 {
10901         if (tok < TSEMI)
10902                 return tokname_array[tok];
10903         sprintf(buf, "\"%s\"", tokname_array[tok]);
10904         return buf;
10905 }
10906
10907 /* raise_error_unexpected_syntax:
10908  * Called when an unexpected token is read during the parse.  The argument
10909  * is the token that is expected, or -1 if more than one type of token can
10910  * occur at this point.
10911  */
10912 static void raise_error_unexpected_syntax(int) NORETURN;
10913 static void
10914 raise_error_unexpected_syntax(int token)
10915 {
10916         char msg[64];
10917         char buf[16];
10918         int l;
10919
10920         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10921         if (token >= 0)
10922                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10923         raise_error_syntax(msg);
10924         /* NOTREACHED */
10925 }
10926
10927 #define EOFMARKLEN 79
10928
10929 /* parsing is heavily cross-recursive, need these forward decls */
10930 static union node *andor(void);
10931 static union node *pipeline(void);
10932 static union node *parse_command(void);
10933 static void parseheredoc(void);
10934 static int peektoken(void);
10935 static int readtoken(void);
10936
10937 static union node *
10938 list(int nlflag)
10939 {
10940         union node *n1, *n2, *n3;
10941         int tok;
10942
10943         n1 = NULL;
10944         for (;;) {
10945                 switch (peektoken()) {
10946                 case TNL:
10947                         if (!(nlflag & 1))
10948                                 break;
10949                         parseheredoc();
10950                         return n1;
10951
10952                 case TEOF:
10953                         if (!n1 && (nlflag & 1))
10954                                 n1 = NODE_EOF;
10955                         parseheredoc();
10956                         return n1;
10957                 }
10958
10959                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10960                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10961                         return n1;
10962                 nlflag |= 2;
10963
10964                 n2 = andor();
10965                 tok = readtoken();
10966                 if (tok == TBACKGND) {
10967                         if (n2->type == NPIPE) {
10968                                 n2->npipe.pipe_backgnd = 1;
10969                         } else {
10970                                 if (n2->type != NREDIR) {
10971                                         n3 = stzalloc(sizeof(struct nredir));
10972                                         n3->nredir.n = n2;
10973                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10974                                         n2 = n3;
10975                                 }
10976                                 n2->type = NBACKGND;
10977                         }
10978                 }
10979                 if (n1 == NULL) {
10980                         n1 = n2;
10981                 } else {
10982                         n3 = stzalloc(sizeof(struct nbinary));
10983                         n3->type = NSEMI;
10984                         n3->nbinary.ch1 = n1;
10985                         n3->nbinary.ch2 = n2;
10986                         n1 = n3;
10987                 }
10988                 switch (tok) {
10989                 case TNL:
10990                 case TEOF:
10991                         tokpushback = 1;
10992                         /* fall through */
10993                 case TBACKGND:
10994                 case TSEMI:
10995                         break;
10996                 default:
10997                         if ((nlflag & 1))
10998                                 raise_error_unexpected_syntax(-1);
10999                         tokpushback = 1;
11000                         return n1;
11001                 }
11002         }
11003 }
11004
11005 static union node *
11006 andor(void)
11007 {
11008         union node *n1, *n2, *n3;
11009         int t;
11010
11011         n1 = pipeline();
11012         for (;;) {
11013                 t = readtoken();
11014                 if (t == TAND) {
11015                         t = NAND;
11016                 } else if (t == TOR) {
11017                         t = NOR;
11018                 } else {
11019                         tokpushback = 1;
11020                         return n1;
11021                 }
11022                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11023                 n2 = pipeline();
11024                 n3 = stzalloc(sizeof(struct nbinary));
11025                 n3->type = t;
11026                 n3->nbinary.ch1 = n1;
11027                 n3->nbinary.ch2 = n2;
11028                 n1 = n3;
11029         }
11030 }
11031
11032 static union node *
11033 pipeline(void)
11034 {
11035         union node *n1, *n2, *pipenode;
11036         struct nodelist *lp, *prev;
11037         int negate;
11038
11039         negate = 0;
11040         TRACE(("pipeline: entered\n"));
11041         if (readtoken() == TNOT) {
11042                 negate = !negate;
11043                 checkkwd = CHKKWD | CHKALIAS;
11044         } else
11045                 tokpushback = 1;
11046         n1 = parse_command();
11047         if (readtoken() == TPIPE) {
11048                 pipenode = stzalloc(sizeof(struct npipe));
11049                 pipenode->type = NPIPE;
11050                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11051                 lp = stzalloc(sizeof(struct nodelist));
11052                 pipenode->npipe.cmdlist = lp;
11053                 lp->n = n1;
11054                 do {
11055                         prev = lp;
11056                         lp = stzalloc(sizeof(struct nodelist));
11057                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11058                         lp->n = parse_command();
11059                         prev->next = lp;
11060                 } while (readtoken() == TPIPE);
11061                 lp->next = NULL;
11062                 n1 = pipenode;
11063         }
11064         tokpushback = 1;
11065         if (negate) {
11066                 n2 = stzalloc(sizeof(struct nnot));
11067                 n2->type = NNOT;
11068                 n2->nnot.com = n1;
11069                 return n2;
11070         }
11071         return n1;
11072 }
11073
11074 static union node *
11075 makename(void)
11076 {
11077         union node *n;
11078
11079         n = stzalloc(sizeof(struct narg));
11080         n->type = NARG;
11081         /*n->narg.next = NULL; - stzalloc did it */
11082         n->narg.text = wordtext;
11083         n->narg.backquote = backquotelist;
11084         return n;
11085 }
11086
11087 static void
11088 fixredir(union node *n, const char *text, int err)
11089 {
11090         int fd;
11091
11092         TRACE(("Fix redir %s %d\n", text, err));
11093         if (!err)
11094                 n->ndup.vname = NULL;
11095
11096         fd = bb_strtou(text, NULL, 10);
11097         if (!errno && fd >= 0)
11098                 n->ndup.dupfd = fd;
11099         else if (LONE_DASH(text))
11100                 n->ndup.dupfd = -1;
11101         else {
11102                 if (err)
11103                         raise_error_syntax("bad fd number");
11104                 n->ndup.vname = makename();
11105         }
11106 }
11107
11108 /*
11109  * Returns true if the text contains nothing to expand (no dollar signs
11110  * or backquotes).
11111  */
11112 static int
11113 noexpand(const char *text)
11114 {
11115         unsigned char c;
11116
11117         while ((c = *text++) != '\0') {
11118                 if (c == CTLQUOTEMARK)
11119                         continue;
11120                 if (c == CTLESC)
11121                         text++;
11122                 else if (SIT(c, BASESYNTAX) == CCTL)
11123                         return 0;
11124         }
11125         return 1;
11126 }
11127
11128 static void
11129 parsefname(void)
11130 {
11131         union node *n = redirnode;
11132
11133         if (readtoken() != TWORD)
11134                 raise_error_unexpected_syntax(-1);
11135         if (n->type == NHERE) {
11136                 struct heredoc *here = heredoc;
11137                 struct heredoc *p;
11138                 int i;
11139
11140                 if (quoteflag == 0)
11141                         n->type = NXHERE;
11142                 TRACE(("Here document %d\n", n->type));
11143                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11144                         raise_error_syntax("illegal eof marker for << redirection");
11145                 rmescapes(wordtext, 0);
11146                 here->eofmark = wordtext;
11147                 here->next = NULL;
11148                 if (heredoclist == NULL)
11149                         heredoclist = here;
11150                 else {
11151                         for (p = heredoclist; p->next; p = p->next)
11152                                 continue;
11153                         p->next = here;
11154                 }
11155         } else if (n->type == NTOFD || n->type == NFROMFD) {
11156                 fixredir(n, wordtext, 0);
11157         } else {
11158                 n->nfile.fname = makename();
11159         }
11160 }
11161
11162 static union node *
11163 simplecmd(void)
11164 {
11165         union node *args, **app;
11166         union node *n = NULL;
11167         union node *vars, **vpp;
11168         union node **rpp, *redir;
11169         int savecheckkwd;
11170 #if BASH_TEST2
11171         smallint double_brackets_flag = 0;
11172 #endif
11173         IF_BASH_FUNCTION(smallint function_flag = 0;)
11174
11175         args = NULL;
11176         app = &args;
11177         vars = NULL;
11178         vpp = &vars;
11179         redir = NULL;
11180         rpp = &redir;
11181
11182         savecheckkwd = CHKALIAS;
11183         for (;;) {
11184                 int t;
11185                 checkkwd = savecheckkwd;
11186                 t = readtoken();
11187                 switch (t) {
11188 #if BASH_FUNCTION
11189                 case TFUNCTION:
11190                         if (peektoken() != TWORD)
11191                                 raise_error_unexpected_syntax(TWORD);
11192                         function_flag = 1;
11193                         break;
11194 #endif
11195 #if BASH_TEST2
11196                 case TAND: /* "&&" */
11197                 case TOR: /* "||" */
11198                         if (!double_brackets_flag) {
11199                                 tokpushback = 1;
11200                                 goto out;
11201                         }
11202                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11203 #endif
11204                 case TWORD:
11205                         n = stzalloc(sizeof(struct narg));
11206                         n->type = NARG;
11207                         /*n->narg.next = NULL; - stzalloc did it */
11208                         n->narg.text = wordtext;
11209 #if BASH_TEST2
11210                         if (strcmp("[[", wordtext) == 0)
11211                                 double_brackets_flag = 1;
11212                         else if (strcmp("]]", wordtext) == 0)
11213                                 double_brackets_flag = 0;
11214 #endif
11215                         n->narg.backquote = backquotelist;
11216                         if (savecheckkwd && isassignment(wordtext)) {
11217                                 *vpp = n;
11218                                 vpp = &n->narg.next;
11219                         } else {
11220                                 *app = n;
11221                                 app = &n->narg.next;
11222                                 savecheckkwd = 0;
11223                         }
11224 #if BASH_FUNCTION
11225                         if (function_flag) {
11226                                 checkkwd = CHKNL | CHKKWD;
11227                                 switch (peektoken()) {
11228                                 case TBEGIN:
11229                                 case TIF:
11230                                 case TCASE:
11231                                 case TUNTIL:
11232                                 case TWHILE:
11233                                 case TFOR:
11234                                         goto do_func;
11235                                 case TLP:
11236                                         function_flag = 0;
11237                                         break;
11238                                 case TWORD:
11239                                         if (strcmp("[[", wordtext) == 0)
11240                                                 goto do_func;
11241                                         /* fall through */
11242                                 default:
11243                                         raise_error_unexpected_syntax(-1);
11244                                 }
11245                         }
11246 #endif
11247                         break;
11248                 case TREDIR:
11249                         *rpp = n = redirnode;
11250                         rpp = &n->nfile.next;
11251                         parsefname();   /* read name of redirection file */
11252                         break;
11253                 case TLP:
11254  IF_BASH_FUNCTION(do_func:)
11255                         if (args && app == &args->narg.next
11256                          && !vars && !redir
11257                         ) {
11258                                 struct builtincmd *bcmd;
11259                                 const char *name;
11260
11261                                 /* We have a function */
11262                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11263                                         raise_error_unexpected_syntax(TRP);
11264                                 name = n->narg.text;
11265                                 if (!goodname(name)
11266                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11267                                 ) {
11268                                         raise_error_syntax("bad function name");
11269                                 }
11270                                 n->type = NDEFUN;
11271                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11272                                 n->narg.next = parse_command();
11273                                 return n;
11274                         }
11275                         IF_BASH_FUNCTION(function_flag = 0;)
11276                         /* fall through */
11277                 default:
11278                         tokpushback = 1;
11279                         goto out;
11280                 }
11281         }
11282  out:
11283         *app = NULL;
11284         *vpp = NULL;
11285         *rpp = NULL;
11286         n = stzalloc(sizeof(struct ncmd));
11287         n->type = NCMD;
11288         n->ncmd.args = args;
11289         n->ncmd.assign = vars;
11290         n->ncmd.redirect = redir;
11291         return n;
11292 }
11293
11294 static union node *
11295 parse_command(void)
11296 {
11297         union node *n1, *n2;
11298         union node *ap, **app;
11299         union node *cp, **cpp;
11300         union node *redir, **rpp;
11301         union node **rpp2;
11302         int t;
11303
11304         redir = NULL;
11305         rpp2 = &redir;
11306
11307         switch (readtoken()) {
11308         default:
11309                 raise_error_unexpected_syntax(-1);
11310                 /* NOTREACHED */
11311         case TIF:
11312                 n1 = stzalloc(sizeof(struct nif));
11313                 n1->type = NIF;
11314                 n1->nif.test = list(0);
11315                 if (readtoken() != TTHEN)
11316                         raise_error_unexpected_syntax(TTHEN);
11317                 n1->nif.ifpart = list(0);
11318                 n2 = n1;
11319                 while (readtoken() == TELIF) {
11320                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11321                         n2 = n2->nif.elsepart;
11322                         n2->type = NIF;
11323                         n2->nif.test = list(0);
11324                         if (readtoken() != TTHEN)
11325                                 raise_error_unexpected_syntax(TTHEN);
11326                         n2->nif.ifpart = list(0);
11327                 }
11328                 if (lasttoken == TELSE)
11329                         n2->nif.elsepart = list(0);
11330                 else {
11331                         n2->nif.elsepart = NULL;
11332                         tokpushback = 1;
11333                 }
11334                 t = TFI;
11335                 break;
11336         case TWHILE:
11337         case TUNTIL: {
11338                 int got;
11339                 n1 = stzalloc(sizeof(struct nbinary));
11340                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11341                 n1->nbinary.ch1 = list(0);
11342                 got = readtoken();
11343                 if (got != TDO) {
11344                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11345                                         got == TWORD ? wordtext : ""));
11346                         raise_error_unexpected_syntax(TDO);
11347                 }
11348                 n1->nbinary.ch2 = list(0);
11349                 t = TDONE;
11350                 break;
11351         }
11352         case TFOR:
11353                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11354                         raise_error_syntax("bad for loop variable");
11355                 n1 = stzalloc(sizeof(struct nfor));
11356                 n1->type = NFOR;
11357                 n1->nfor.var = wordtext;
11358                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11359                 if (readtoken() == TIN) {
11360                         app = &ap;
11361                         while (readtoken() == TWORD) {
11362                                 n2 = stzalloc(sizeof(struct narg));
11363                                 n2->type = NARG;
11364                                 /*n2->narg.next = NULL; - stzalloc did it */
11365                                 n2->narg.text = wordtext;
11366                                 n2->narg.backquote = backquotelist;
11367                                 *app = n2;
11368                                 app = &n2->narg.next;
11369                         }
11370                         *app = NULL;
11371                         n1->nfor.args = ap;
11372                         if (lasttoken != TNL && lasttoken != TSEMI)
11373                                 raise_error_unexpected_syntax(-1);
11374                 } else {
11375                         n2 = stzalloc(sizeof(struct narg));
11376                         n2->type = NARG;
11377                         /*n2->narg.next = NULL; - stzalloc did it */
11378                         n2->narg.text = (char *)dolatstr;
11379                         /*n2->narg.backquote = NULL;*/
11380                         n1->nfor.args = n2;
11381                         /*
11382                          * Newline or semicolon here is optional (but note
11383                          * that the original Bourne shell only allowed NL).
11384                          */
11385                         if (lasttoken != TSEMI)
11386                                 tokpushback = 1;
11387                 }
11388                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11389                 if (readtoken() != TDO)
11390                         raise_error_unexpected_syntax(TDO);
11391                 n1->nfor.body = list(0);
11392                 t = TDONE;
11393                 break;
11394         case TCASE:
11395                 n1 = stzalloc(sizeof(struct ncase));
11396                 n1->type = NCASE;
11397                 if (readtoken() != TWORD)
11398                         raise_error_unexpected_syntax(TWORD);
11399                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11400                 n2->type = NARG;
11401                 /*n2->narg.next = NULL; - stzalloc did it */
11402                 n2->narg.text = wordtext;
11403                 n2->narg.backquote = backquotelist;
11404                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11405                 if (readtoken() != TIN)
11406                         raise_error_unexpected_syntax(TIN);
11407                 cpp = &n1->ncase.cases;
11408  next_case:
11409                 checkkwd = CHKNL | CHKKWD;
11410                 t = readtoken();
11411                 while (t != TESAC) {
11412                         if (lasttoken == TLP)
11413                                 readtoken();
11414                         *cpp = cp = stzalloc(sizeof(struct nclist));
11415                         cp->type = NCLIST;
11416                         app = &cp->nclist.pattern;
11417                         for (;;) {
11418                                 *app = ap = stzalloc(sizeof(struct narg));
11419                                 ap->type = NARG;
11420                                 /*ap->narg.next = NULL; - stzalloc did it */
11421                                 ap->narg.text = wordtext;
11422                                 ap->narg.backquote = backquotelist;
11423                                 if (readtoken() != TPIPE)
11424                                         break;
11425                                 app = &ap->narg.next;
11426                                 readtoken();
11427                         }
11428                         //ap->narg.next = NULL;
11429                         if (lasttoken != TRP)
11430                                 raise_error_unexpected_syntax(TRP);
11431                         cp->nclist.body = list(2);
11432
11433                         cpp = &cp->nclist.next;
11434
11435                         checkkwd = CHKNL | CHKKWD;
11436                         t = readtoken();
11437                         if (t != TESAC) {
11438                                 if (t != TENDCASE)
11439                                         raise_error_unexpected_syntax(TENDCASE);
11440                                 goto next_case;
11441                         }
11442                 }
11443                 *cpp = NULL;
11444                 goto redir;
11445         case TLP:
11446                 n1 = stzalloc(sizeof(struct nredir));
11447                 n1->type = NSUBSHELL;
11448                 n1->nredir.n = list(0);
11449                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11450                 t = TRP;
11451                 break;
11452         case TBEGIN:
11453                 n1 = list(0);
11454                 t = TEND;
11455                 break;
11456         IF_BASH_FUNCTION(case TFUNCTION:)
11457         case TWORD:
11458         case TREDIR:
11459                 tokpushback = 1;
11460                 return simplecmd();
11461         }
11462
11463         if (readtoken() != t)
11464                 raise_error_unexpected_syntax(t);
11465
11466  redir:
11467         /* Now check for redirection which may follow command */
11468         checkkwd = CHKKWD | CHKALIAS;
11469         rpp = rpp2;
11470         while (readtoken() == TREDIR) {
11471                 *rpp = n2 = redirnode;
11472                 rpp = &n2->nfile.next;
11473                 parsefname();
11474         }
11475         tokpushback = 1;
11476         *rpp = NULL;
11477         if (redir) {
11478                 if (n1->type != NSUBSHELL) {
11479                         n2 = stzalloc(sizeof(struct nredir));
11480                         n2->type = NREDIR;
11481                         n2->nredir.n = n1;
11482                         n1 = n2;
11483                 }
11484                 n1->nredir.redirect = redir;
11485         }
11486         return n1;
11487 }
11488
11489 #if BASH_DOLLAR_SQUOTE
11490 static int
11491 decode_dollar_squote(void)
11492 {
11493         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11494         int c, cnt;
11495         char *p;
11496         char buf[4];
11497
11498         c = pgetc();
11499         p = strchr(C_escapes, c);
11500         if (p) {
11501                 buf[0] = c;
11502                 p = buf;
11503                 cnt = 3;
11504                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11505                         do {
11506                                 c = pgetc();
11507                                 *++p = c;
11508                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11509                         pungetc();
11510                 } else if (c == 'x') { /* \xHH */
11511                         do {
11512                                 c = pgetc();
11513                                 *++p = c;
11514                         } while (isxdigit(c) && --cnt);
11515                         pungetc();
11516                         if (cnt == 3) { /* \x but next char is "bad" */
11517                                 c = 'x';
11518                                 goto unrecognized;
11519                         }
11520                 } else { /* simple seq like \\ or \t */
11521                         p++;
11522                 }
11523                 *p = '\0';
11524                 p = buf;
11525                 c = bb_process_escape_sequence((void*)&p);
11526         } else { /* unrecognized "\z": print both chars unless ' or " */
11527                 if (c != '\'' && c != '"') {
11528  unrecognized:
11529                         c |= 0x100; /* "please encode \, then me" */
11530                 }
11531         }
11532         return c;
11533 }
11534 #endif
11535
11536 /*
11537  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11538  * is not NULL, read a here document.  In the latter case, eofmark is the
11539  * word which marks the end of the document and striptabs is true if
11540  * leading tabs should be stripped from the document.  The argument c
11541  * is the first character of the input token or document.
11542  *
11543  * Because C does not have internal subroutines, I have simulated them
11544  * using goto's to implement the subroutine linkage.  The following macros
11545  * will run code that appears at the end of readtoken1.
11546  */
11547 #define CHECKEND()      {goto checkend; checkend_return:;}
11548 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11549 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11550 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11551 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11552 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11553 static int
11554 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11555 {
11556         /* NB: syntax parameter fits into smallint */
11557         /* c parameter is an unsigned char or PEOF or PEOA */
11558         char *out;
11559         size_t len;
11560         char line[EOFMARKLEN + 1];
11561         struct nodelist *bqlist;
11562         smallint quotef;
11563         smallint dblquote;
11564         smallint oldstyle;
11565         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11566         smallint pssyntax;   /* we are expanding a prompt string */
11567         int varnest;         /* levels of variables expansion */
11568         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11569         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11570         int dqvarnest;       /* levels of variables expansion within double quotes */
11571
11572         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11573
11574         startlinno = g_parsefile->linno;
11575         bqlist = NULL;
11576         quotef = 0;
11577         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11578         pssyntax = (syntax == PSSYNTAX);
11579         if (pssyntax)
11580                 syntax = DQSYNTAX;
11581         dblquote = (syntax == DQSYNTAX);
11582         varnest = 0;
11583         IF_FEATURE_SH_MATH(arinest = 0;)
11584         IF_FEATURE_SH_MATH(parenlevel = 0;)
11585         dqvarnest = 0;
11586
11587         STARTSTACKSTR(out);
11588  loop:
11589         /* For each line, until end of word */
11590         CHECKEND();     /* set c to PEOF if at end of here document */
11591         for (;;) {      /* until end of line or end of word */
11592                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11593                 switch (SIT(c, syntax)) {
11594                 case CNL:       /* '\n' */
11595                         if (syntax == BASESYNTAX)
11596                                 goto endword;   /* exit outer loop */
11597                         USTPUTC(c, out);
11598                         nlprompt();
11599                         c = pgetc();
11600                         goto loop;              /* continue outer loop */
11601                 case CWORD:
11602                         USTPUTC(c, out);
11603                         break;
11604                 case CCTL:
11605 #if BASH_DOLLAR_SQUOTE
11606                         if (c == '\\' && bash_dollar_squote) {
11607                                 c = decode_dollar_squote();
11608                                 if (c == '\0') {
11609                                         /* skip $'\000', $'\x00' (like bash) */
11610                                         break;
11611                                 }
11612                                 if (c & 0x100) {
11613                                         /* Unknown escape. Encode as '\z' */
11614                                         c = (unsigned char)c;
11615                                         if (eofmark == NULL || dblquote)
11616                                                 USTPUTC(CTLESC, out);
11617                                         USTPUTC('\\', out);
11618                                 }
11619                         }
11620 #endif
11621                         if (eofmark == NULL || dblquote)
11622                                 USTPUTC(CTLESC, out);
11623                         USTPUTC(c, out);
11624                         break;
11625                 case CBACK:     /* backslash */
11626                         c = pgetc_without_PEOA();
11627                         if (c == PEOF) {
11628                                 USTPUTC(CTLESC, out);
11629                                 USTPUTC('\\', out);
11630                                 pungetc();
11631                         } else if (c == '\n') {
11632                                 nlprompt();
11633                         } else {
11634                                 if (c == '$' && pssyntax) {
11635                                         USTPUTC(CTLESC, out);
11636                                         USTPUTC('\\', out);
11637                                 }
11638                                 /* Backslash is retained if we are in "str" and next char isn't special */
11639                                 if (dblquote
11640                                  && c != '\\'
11641                                  && c != '`'
11642                                  && c != '$'
11643                                  && (c != '"' || eofmark != NULL)
11644                                 ) {
11645                                         USTPUTC('\\', out);
11646                                 }
11647                                 USTPUTC(CTLESC, out);
11648                                 USTPUTC(c, out);
11649                                 quotef = 1;
11650                         }
11651                         break;
11652                 case CSQUOTE:
11653                         syntax = SQSYNTAX;
11654  quotemark:
11655                         if (eofmark == NULL) {
11656                                 USTPUTC(CTLQUOTEMARK, out);
11657                         }
11658                         break;
11659                 case CDQUOTE:
11660                         syntax = DQSYNTAX;
11661                         dblquote = 1;
11662                         goto quotemark;
11663                 case CENDQUOTE:
11664                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11665                         if (eofmark != NULL && varnest == 0) {
11666                                 USTPUTC(c, out);
11667                         } else {
11668                                 if (dqvarnest == 0) {
11669                                         syntax = BASESYNTAX;
11670                                         dblquote = 0;
11671                                 }
11672                                 quotef = 1;
11673                                 goto quotemark;
11674                         }
11675                         break;
11676                 case CVAR:      /* '$' */
11677                         PARSESUB();             /* parse substitution */
11678                         break;
11679                 case CENDVAR:   /* '}' */
11680                         if (varnest > 0) {
11681                                 varnest--;
11682                                 if (dqvarnest > 0) {
11683                                         dqvarnest--;
11684                                 }
11685                                 c = CTLENDVAR;
11686                         }
11687                         USTPUTC(c, out);
11688                         break;
11689 #if ENABLE_FEATURE_SH_MATH
11690                 case CLP:       /* '(' in arithmetic */
11691                         parenlevel++;
11692                         USTPUTC(c, out);
11693                         break;
11694                 case CRP:       /* ')' in arithmetic */
11695                         if (parenlevel > 0) {
11696                                 parenlevel--;
11697                         } else {
11698                                 if (pgetc_eatbnl() == ')') {
11699                                         c = CTLENDARI;
11700                                         if (--arinest == 0) {
11701                                                 syntax = prevsyntax;
11702                                         }
11703                                 } else {
11704                                         /*
11705                                          * unbalanced parens
11706                                          * (don't 2nd guess - no error)
11707                                          */
11708                                         pungetc();
11709                                 }
11710                         }
11711                         USTPUTC(c, out);
11712                         break;
11713 #endif
11714                 case CBQUOTE:   /* '`' */
11715                         PARSEBACKQOLD();
11716                         break;
11717                 case CENDFILE:
11718                         goto endword;           /* exit outer loop */
11719                 case CIGN:
11720                         break;
11721                 default:
11722                         if (varnest == 0) {
11723 #if BASH_REDIR_OUTPUT
11724                                 if (c == '&') {
11725 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11726                                         if (pgetc() == '>')
11727                                                 c = 0x100 + '>'; /* flag &> */
11728                                         pungetc();
11729                                 }
11730 #endif
11731                                 goto endword;   /* exit outer loop */
11732                         }
11733                         IF_ASH_ALIAS(if (c != PEOA))
11734                                 USTPUTC(c, out);
11735                 }
11736                 c = pgetc();
11737         } /* for (;;) */
11738  endword:
11739
11740 #if ENABLE_FEATURE_SH_MATH
11741         if (syntax == ARISYNTAX)
11742                 raise_error_syntax("missing '))'");
11743 #endif
11744         if (syntax != BASESYNTAX && eofmark == NULL)
11745                 raise_error_syntax("unterminated quoted string");
11746         if (varnest != 0) {
11747                 startlinno = g_parsefile->linno;
11748                 /* { */
11749                 raise_error_syntax("missing '}'");
11750         }
11751         USTPUTC('\0', out);
11752         len = out - (char *)stackblock();
11753         out = stackblock();
11754         if (eofmark == NULL) {
11755                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11756                  && quotef == 0
11757                 ) {
11758                         if (isdigit_str9(out)) {
11759                                 PARSEREDIR(); /* passed as params: out, c */
11760                                 lasttoken = TREDIR;
11761                                 return lasttoken;
11762                         }
11763                         /* else: non-number X seen, interpret it
11764                          * as "NNNX>file" = "NNNX >file" */
11765                 }
11766                 pungetc();
11767         }
11768         quoteflag = quotef;
11769         backquotelist = bqlist;
11770         grabstackblock(len);
11771         wordtext = out;
11772         lasttoken = TWORD;
11773         return lasttoken;
11774 /* end of readtoken routine */
11775
11776 /*
11777  * Check to see whether we are at the end of the here document.  When this
11778  * is called, c is set to the first character of the next input line.  If
11779  * we are at the end of the here document, this routine sets the c to PEOF.
11780  */
11781 checkend: {
11782         if (eofmark) {
11783 #if ENABLE_ASH_ALIAS
11784                 if (c == PEOA)
11785                         c = pgetc_without_PEOA();
11786 #endif
11787                 if (striptabs) {
11788                         while (c == '\t') {
11789                                 c = pgetc_without_PEOA();
11790                         }
11791                 }
11792                 if (c == *eofmark) {
11793                         if (pfgets(line, sizeof(line)) != NULL) {
11794                                 char *p, *q;
11795                                 int cc;
11796
11797                                 p = line;
11798                                 for (q = eofmark + 1;; p++, q++) {
11799                                         cc = *p;
11800                                         if (cc == '\n')
11801                                                 cc = 0;
11802                                         if (!*q || cc != *q)
11803                                                 break;
11804                                 }
11805                                 if (cc == *q) {
11806                                         c = PEOF;
11807                                         nlnoprompt();
11808                                 } else {
11809                                         pushstring(line, NULL);
11810                                 }
11811                         }
11812                 }
11813         }
11814         goto checkend_return;
11815 }
11816
11817 /*
11818  * Parse a redirection operator.  The variable "out" points to a string
11819  * specifying the fd to be redirected.  The variable "c" contains the
11820  * first character of the redirection operator.
11821  */
11822 parseredir: {
11823         /* out is already checked to be a valid number or "" */
11824         int fd = (*out == '\0' ? -1 : atoi(out));
11825         union node *np;
11826
11827         np = stzalloc(sizeof(struct nfile));
11828         if (c == '>') {
11829                 np->nfile.fd = 1;
11830                 c = pgetc();
11831                 if (c == '>')
11832                         np->type = NAPPEND;
11833                 else if (c == '|')
11834                         np->type = NCLOBBER;
11835                 else if (c == '&')
11836                         np->type = NTOFD;
11837                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11838                 else {
11839                         np->type = NTO;
11840                         pungetc();
11841                 }
11842         }
11843 #if BASH_REDIR_OUTPUT
11844         else if (c == 0x100 + '>') { /* this flags &> redirection */
11845                 np->nfile.fd = 1;
11846                 pgetc(); /* this is '>', no need to check */
11847                 np->type = NTO2;
11848         }
11849 #endif
11850         else { /* c == '<' */
11851                 /*np->nfile.fd = 0; - stzalloc did it */
11852                 c = pgetc();
11853                 switch (c) {
11854                 case '<':
11855                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11856                                 np = stzalloc(sizeof(struct nhere));
11857                                 /*np->nfile.fd = 0; - stzalloc did it */
11858                         }
11859                         np->type = NHERE;
11860                         heredoc = stzalloc(sizeof(struct heredoc));
11861                         heredoc->here = np;
11862                         c = pgetc();
11863                         if (c == '-') {
11864                                 heredoc->striptabs = 1;
11865                         } else {
11866                                 /*heredoc->striptabs = 0; - stzalloc did it */
11867                                 pungetc();
11868                         }
11869                         break;
11870
11871                 case '&':
11872                         np->type = NFROMFD;
11873                         break;
11874
11875                 case '>':
11876                         np->type = NFROMTO;
11877                         break;
11878
11879                 default:
11880                         np->type = NFROM;
11881                         pungetc();
11882                         break;
11883                 }
11884         }
11885         if (fd >= 0)
11886                 np->nfile.fd = fd;
11887         redirnode = np;
11888         goto parseredir_return;
11889 }
11890
11891 /*
11892  * Parse a substitution.  At this point, we have read the dollar sign
11893  * and nothing else.
11894  */
11895
11896 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11897  * (assuming ascii char codes, as the original implementation did) */
11898 #define is_special(c) \
11899         (((unsigned)(c) - 33 < 32) \
11900                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11901 parsesub: {
11902         unsigned char subtype;
11903         int typeloc;
11904
11905         c = pgetc_eatbnl();
11906         if (c > 255 /* PEOA or PEOF */
11907          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11908         ) {
11909 #if BASH_DOLLAR_SQUOTE
11910                 if (syntax != DQSYNTAX && c == '\'')
11911                         bash_dollar_squote = 1;
11912                 else
11913 #endif
11914                         USTPUTC('$', out);
11915                 pungetc();
11916         } else if (c == '(') {
11917                 /* $(command) or $((arith)) */
11918                 if (pgetc_eatbnl() == '(') {
11919 #if ENABLE_FEATURE_SH_MATH
11920                         PARSEARITH();
11921 #else
11922                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11923 #endif
11924                 } else {
11925                         pungetc();
11926                         PARSEBACKQNEW();
11927                 }
11928         } else {
11929                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11930                 USTPUTC(CTLVAR, out);
11931                 typeloc = out - (char *)stackblock();
11932                 STADJUST(1, out);
11933                 subtype = VSNORMAL;
11934                 if (c == '{') {
11935                         c = pgetc_eatbnl();
11936                         subtype = 0;
11937                 }
11938  varname:
11939                 if (is_name(c)) {
11940                         /* $[{[#]]NAME[}] */
11941                         do {
11942                                 STPUTC(c, out);
11943                                 c = pgetc_eatbnl();
11944                         } while (is_in_name(c));
11945                 } else if (isdigit(c)) {
11946                         /* $[{[#]]NUM[}] */
11947                         do {
11948                                 STPUTC(c, out);
11949                                 c = pgetc_eatbnl();
11950                         } while (isdigit(c));
11951                 } else if (is_special(c)) {
11952                         /* $[{[#]]<specialchar>[}] */
11953                         int cc = c;
11954
11955                         c = pgetc_eatbnl();
11956                         if (!subtype && cc == '#') {
11957                                 subtype = VSLENGTH;
11958                                 if (c == '_' || isalnum(c))
11959                                         goto varname;
11960                                 cc = c;
11961                                 c = pgetc_eatbnl();
11962                                 if (cc == '}' || c != '}') {
11963                                         pungetc();
11964                                         subtype = 0;
11965                                         c = cc;
11966                                         cc = '#';
11967                                 }
11968                         }
11969                         USTPUTC(cc, out);
11970                 } else {
11971                         goto badsub;
11972                 }
11973                 if (c != '}' && subtype == VSLENGTH) {
11974                         /* ${#VAR didn't end with } */
11975                         goto badsub;
11976                 }
11977
11978                 if (subtype == 0) {
11979                         static const char types[] ALIGN1 = "}-+?=";
11980                         /* ${VAR...} but not $VAR or ${#VAR} */
11981                         /* c == first char after VAR */
11982                         switch (c) {
11983                         case ':':
11984                                 c = pgetc_eatbnl();
11985 #if BASH_SUBSTR
11986                                 /* This check is only needed to not misinterpret
11987                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11988                                  * constructs.
11989                                  */
11990                                 if (!strchr(types, c)) {
11991                                         subtype = VSSUBSTR;
11992                                         pungetc();
11993                                         break; /* "goto badsub" is bigger (!) */
11994                                 }
11995 #endif
11996                                 subtype = VSNUL;
11997                                 /*FALLTHROUGH*/
11998                         default: {
11999                                 const char *p = strchr(types, c);
12000                                 if (p == NULL)
12001                                         break;
12002                                 subtype |= p - types + VSNORMAL;
12003                                 break;
12004                         }
12005                         case '%':
12006                         case '#': {
12007                                 int cc = c;
12008                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12009                                 c = pgetc_eatbnl();
12010                                 if (c != cc)
12011                                         goto badsub;
12012                                 subtype++;
12013                                 break;
12014                         }
12015 #if BASH_PATTERN_SUBST
12016                         case '/':
12017                                 /* ${v/[/]pattern/repl} */
12018 //TODO: encode pattern and repl separately.
12019 // Currently ${v/$var_with_slash/repl} is horribly broken
12020                                 subtype = VSREPLACE;
12021                                 c = pgetc_eatbnl();
12022                                 if (c != '/')
12023                                         goto badsub;
12024                                 subtype++; /* VSREPLACEALL */
12025                                 break;
12026 #endif
12027                         }
12028                 } else {
12029  badsub:
12030                         pungetc();
12031                 }
12032                 ((unsigned char *)stackblock())[typeloc] = subtype;
12033                 if (subtype != VSNORMAL) {
12034                         varnest++;
12035                         if (dblquote)
12036                                 dqvarnest++;
12037                 }
12038                 STPUTC('=', out);
12039         }
12040         goto parsesub_return;
12041 }
12042
12043 /*
12044  * Called to parse command substitutions.  Newstyle is set if the command
12045  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12046  * list of commands (passed by reference), and savelen is the number of
12047  * characters on the top of the stack which must be preserved.
12048  */
12049 parsebackq: {
12050         struct nodelist **nlpp;
12051         union node *n;
12052         char *str;
12053         size_t savelen;
12054         smallint saveprompt = 0;
12055
12056         str = NULL;
12057         savelen = out - (char *)stackblock();
12058         if (savelen > 0) {
12059                 /*
12060                  * FIXME: this can allocate very large block on stack and SEGV.
12061                  * Example:
12062                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12063                  * allocates 100kb for every command subst. With about
12064                  * a hundred command substitutions stack overflows.
12065                  * With larger prepended string, SEGV happens sooner.
12066                  */
12067                 str = alloca(savelen);
12068                 memcpy(str, stackblock(), savelen);
12069         }
12070
12071         if (oldstyle) {
12072                 /* We must read until the closing backquote, giving special
12073                  * treatment to some slashes, and then push the string and
12074                  * reread it as input, interpreting it normally.
12075                  */
12076                 char *pout;
12077                 size_t psavelen;
12078                 char *pstr;
12079
12080                 STARTSTACKSTR(pout);
12081                 for (;;) {
12082                         int pc;
12083
12084                         setprompt_if(needprompt, 2);
12085                         pc = pgetc();
12086                         switch (pc) {
12087                         case '`':
12088                                 goto done;
12089
12090                         case '\\':
12091                                 pc = pgetc();
12092                                 if (pc == '\n') {
12093                                         nlprompt();
12094                                         /*
12095                                          * If eating a newline, avoid putting
12096                                          * the newline into the new character
12097                                          * stream (via the STPUTC after the
12098                                          * switch).
12099                                          */
12100                                         continue;
12101                                 }
12102                                 if (pc != '\\' && pc != '`' && pc != '$'
12103                                  && (!dblquote || pc != '"')
12104                                 ) {
12105                                         STPUTC('\\', pout);
12106                                 }
12107                                 if (pc <= 255 /* not PEOA or PEOF */) {
12108                                         break;
12109                                 }
12110                                 /* fall through */
12111
12112                         case PEOF:
12113                         IF_ASH_ALIAS(case PEOA:)
12114                                 startlinno = g_parsefile->linno;
12115                                 raise_error_syntax("EOF in backquote substitution");
12116
12117                         case '\n':
12118                                 nlnoprompt();
12119                                 break;
12120
12121                         default:
12122                                 break;
12123                         }
12124                         STPUTC(pc, pout);
12125                 }
12126  done:
12127                 STPUTC('\0', pout);
12128                 psavelen = pout - (char *)stackblock();
12129                 if (psavelen > 0) {
12130                         pstr = grabstackstr(pout);
12131                         setinputstring(pstr);
12132                 }
12133         }
12134         nlpp = &bqlist;
12135         while (*nlpp)
12136                 nlpp = &(*nlpp)->next;
12137         *nlpp = stzalloc(sizeof(**nlpp));
12138         /* (*nlpp)->next = NULL; - stzalloc did it */
12139
12140         if (oldstyle) {
12141                 saveprompt = doprompt;
12142                 doprompt = 0;
12143         }
12144
12145         n = list(2);
12146
12147         if (oldstyle)
12148                 doprompt = saveprompt;
12149         else if (readtoken() != TRP)
12150                 raise_error_unexpected_syntax(TRP);
12151
12152         (*nlpp)->n = n;
12153         if (oldstyle) {
12154                 /*
12155                  * Start reading from old file again, ignoring any pushed back
12156                  * tokens left from the backquote parsing
12157                  */
12158                 popfile();
12159                 tokpushback = 0;
12160         }
12161         while (stackblocksize() <= savelen)
12162                 growstackblock();
12163         STARTSTACKSTR(out);
12164         if (str) {
12165                 memcpy(out, str, savelen);
12166                 STADJUST(savelen, out);
12167         }
12168         USTPUTC(CTLBACKQ, out);
12169         if (oldstyle)
12170                 goto parsebackq_oldreturn;
12171         goto parsebackq_newreturn;
12172 }
12173
12174 #if ENABLE_FEATURE_SH_MATH
12175 /*
12176  * Parse an arithmetic expansion (indicate start of one and set state)
12177  */
12178 parsearith: {
12179         if (++arinest == 1) {
12180                 prevsyntax = syntax;
12181                 syntax = ARISYNTAX;
12182         }
12183         USTPUTC(CTLARI, out);
12184         goto parsearith_return;
12185 }
12186 #endif
12187 } /* end of readtoken */
12188
12189 /*
12190  * Read the next input token.
12191  * If the token is a word, we set backquotelist to the list of cmds in
12192  *      backquotes.  We set quoteflag to true if any part of the word was
12193  *      quoted.
12194  * If the token is TREDIR, then we set redirnode to a structure containing
12195  *      the redirection.
12196  * In all cases, the variable startlinno is set to the number of the line
12197  *      on which the token starts.
12198  *
12199  * [Change comment:  here documents and internal procedures]
12200  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12201  *  word parsing code into a separate routine.  In this case, readtoken
12202  *  doesn't need to have any internal procedures, but parseword does.
12203  *  We could also make parseoperator in essence the main routine, and
12204  *  have parseword (readtoken1?) handle both words and redirection.]
12205  */
12206 #define NEW_xxreadtoken
12207 #ifdef NEW_xxreadtoken
12208 /* singles must be first! */
12209 static const char xxreadtoken_chars[7] ALIGN1 = {
12210         '\n', '(', ')', /* singles */
12211         '&', '|', ';',  /* doubles */
12212         0
12213 };
12214
12215 #define xxreadtoken_singles 3
12216 #define xxreadtoken_doubles 3
12217
12218 static const char xxreadtoken_tokens[] ALIGN1 = {
12219         TNL, TLP, TRP,          /* only single occurrence allowed */
12220         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12221         TEOF,                   /* corresponds to trailing nul */
12222         TAND, TOR, TENDCASE     /* if double occurrence */
12223 };
12224
12225 static int
12226 xxreadtoken(void)
12227 {
12228         int c;
12229
12230         if (tokpushback) {
12231                 tokpushback = 0;
12232                 return lasttoken;
12233         }
12234         setprompt_if(needprompt, 2);
12235         startlinno = g_parsefile->linno;
12236         for (;;) {                      /* until token or start of word found */
12237                 c = pgetc();
12238                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12239                         continue;
12240
12241                 if (c == '#') {
12242                         while ((c = pgetc()) != '\n' && c != PEOF)
12243                                 continue;
12244                         pungetc();
12245                 } else if (c == '\\') {
12246                         if (pgetc() != '\n') {
12247                                 pungetc();
12248                                 break; /* return readtoken1(...) */
12249                         }
12250                         nlprompt();
12251                 } else {
12252                         const char *p;
12253
12254                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12255                         if (c != PEOF) {
12256                                 if (c == '\n') {
12257                                         nlnoprompt();
12258                                 }
12259
12260                                 p = strchr(xxreadtoken_chars, c);
12261                                 if (p == NULL)
12262                                         break; /* return readtoken1(...) */
12263
12264                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12265                                         int cc = pgetc();
12266                                         if (cc == c) {    /* double occurrence? */
12267                                                 p += xxreadtoken_doubles + 1;
12268                                         } else {
12269                                                 pungetc();
12270 #if BASH_REDIR_OUTPUT
12271                                                 if (c == '&' && cc == '>') /* &> */
12272                                                         break; /* return readtoken1(...) */
12273 #endif
12274                                         }
12275                                 }
12276                         }
12277                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12278                         return lasttoken;
12279                 }
12280         } /* for (;;) */
12281
12282         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12283 }
12284 #else /* old xxreadtoken */
12285 #define RETURN(token)   return lasttoken = token
12286 static int
12287 xxreadtoken(void)
12288 {
12289         int c;
12290
12291         if (tokpushback) {
12292                 tokpushback = 0;
12293                 return lasttoken;
12294         }
12295         setprompt_if(needprompt, 2);
12296         startlinno = g_parsefile->linno;
12297         for (;;) {      /* until token or start of word found */
12298                 c = pgetc();
12299                 switch (c) {
12300                 case ' ': case '\t':
12301                 IF_ASH_ALIAS(case PEOA:)
12302                         continue;
12303                 case '#':
12304                         while ((c = pgetc()) != '\n' && c != PEOF)
12305                                 continue;
12306                         pungetc();
12307                         continue;
12308                 case '\\':
12309                         if (pgetc() == '\n') {
12310                                 nlprompt();
12311                                 continue;
12312                         }
12313                         pungetc();
12314                         goto breakloop;
12315                 case '\n':
12316                         nlnoprompt();
12317                         RETURN(TNL);
12318                 case PEOF:
12319                         RETURN(TEOF);
12320                 case '&':
12321                         if (pgetc() == '&')
12322                                 RETURN(TAND);
12323                         pungetc();
12324                         RETURN(TBACKGND);
12325                 case '|':
12326                         if (pgetc() == '|')
12327                                 RETURN(TOR);
12328                         pungetc();
12329                         RETURN(TPIPE);
12330                 case ';':
12331                         if (pgetc() == ';')
12332                                 RETURN(TENDCASE);
12333                         pungetc();
12334                         RETURN(TSEMI);
12335                 case '(':
12336                         RETURN(TLP);
12337                 case ')':
12338                         RETURN(TRP);
12339                 default:
12340                         goto breakloop;
12341                 }
12342         }
12343  breakloop:
12344         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12345 #undef RETURN
12346 }
12347 #endif /* old xxreadtoken */
12348
12349 static int
12350 readtoken(void)
12351 {
12352         int t;
12353         int kwd = checkkwd;
12354 #if DEBUG
12355         smallint alreadyseen = tokpushback;
12356 #endif
12357
12358 #if ENABLE_ASH_ALIAS
12359  top:
12360 #endif
12361
12362         t = xxreadtoken();
12363
12364         /*
12365          * eat newlines
12366          */
12367         if (kwd & CHKNL) {
12368                 while (t == TNL) {
12369                         parseheredoc();
12370                         t = xxreadtoken();
12371                 }
12372         }
12373
12374         if (t != TWORD || quoteflag) {
12375                 goto out;
12376         }
12377
12378         /*
12379          * check for keywords
12380          */
12381         if (kwd & CHKKWD) {
12382                 const char *const *pp;
12383
12384                 pp = findkwd(wordtext);
12385                 if (pp) {
12386                         lasttoken = t = pp - tokname_array;
12387                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12388                         goto out;
12389                 }
12390         }
12391
12392         if (checkkwd & CHKALIAS) {
12393 #if ENABLE_ASH_ALIAS
12394                 struct alias *ap;
12395                 ap = lookupalias(wordtext, 1);
12396                 if (ap != NULL) {
12397                         if (*ap->val) {
12398                                 pushstring(ap->val, ap);
12399                         }
12400                         goto top;
12401                 }
12402 #endif
12403         }
12404  out:
12405         checkkwd = 0;
12406 #if DEBUG
12407         if (!alreadyseen)
12408                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12409         else
12410                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12411 #endif
12412         return t;
12413 }
12414
12415 static int
12416 peektoken(void)
12417 {
12418         int t;
12419
12420         t = readtoken();
12421         tokpushback = 1;
12422         return t;
12423 }
12424
12425 /*
12426  * Read and parse a command.  Returns NODE_EOF on end of file.
12427  * (NULL is a valid parse tree indicating a blank line.)
12428  */
12429 static union node *
12430 parsecmd(int interact)
12431 {
12432         tokpushback = 0;
12433         checkkwd = 0;
12434         heredoclist = 0;
12435         doprompt = interact;
12436         setprompt_if(doprompt, doprompt);
12437         needprompt = 0;
12438         return list(1);
12439 }
12440
12441 /*
12442  * Input any here documents.
12443  */
12444 static void
12445 parseheredoc(void)
12446 {
12447         struct heredoc *here;
12448         union node *n;
12449
12450         here = heredoclist;
12451         heredoclist = NULL;
12452
12453         while (here) {
12454                 setprompt_if(needprompt, 2);
12455                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12456                                 here->eofmark, here->striptabs);
12457                 n = stzalloc(sizeof(struct narg));
12458                 n->narg.type = NARG;
12459                 /*n->narg.next = NULL; - stzalloc did it */
12460                 n->narg.text = wordtext;
12461                 n->narg.backquote = backquotelist;
12462                 here->here->nhere.doc = n;
12463                 here = here->next;
12464         }
12465 }
12466
12467
12468 /*
12469  * called by editline -- any expansions to the prompt should be added here.
12470  */
12471 static const char *
12472 expandstr(const char *ps)
12473 {
12474         union node n;
12475         int saveprompt;
12476
12477         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12478          * and token processing _can_ alter it (delete NULs etc). */
12479         setinputstring((char *)ps);
12480
12481         saveprompt = doprompt;
12482         doprompt = 0;
12483         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12484         doprompt = saveprompt;
12485
12486         popfile();
12487
12488         n.narg.type = NARG;
12489         n.narg.next = NULL;
12490         n.narg.text = wordtext;
12491         n.narg.backquote = backquotelist;
12492
12493         expandarg(&n, NULL, EXP_QUOTED);
12494         return stackblock();
12495 }
12496
12497 /*
12498  * Execute a command or commands contained in a string.
12499  */
12500 static int
12501 evalstring(char *s, int flags)
12502 {
12503         struct jmploc *volatile savehandler;
12504         struct jmploc jmploc;
12505         int ex;
12506
12507         union node *n;
12508         struct stackmark smark;
12509         int status;
12510
12511         s = sstrdup(s);
12512         setinputstring(s);
12513         setstackmark(&smark);
12514
12515         status = 0;
12516         /* On exception inside execution loop, we must popfile().
12517          * Try interactively:
12518          *      readonly a=a
12519          *      command eval "a=b"  # throws "is read only" error
12520          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12521          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12522          */
12523         savehandler = exception_handler;
12524         ex = setjmp(jmploc.loc);
12525         if (ex)
12526                 goto out;
12527         exception_handler = &jmploc;
12528
12529         while ((n = parsecmd(0)) != NODE_EOF) {
12530                 int i;
12531
12532                 i = evaltree(n, flags);
12533                 if (n)
12534                         status = i;
12535                 popstackmark(&smark);
12536                 if (evalskip)
12537                         break;
12538         }
12539  out:
12540         popstackmark(&smark);
12541         popfile();
12542         stunalloc(s);
12543
12544         exception_handler = savehandler;
12545         if (ex)
12546                 longjmp(exception_handler->loc, ex);
12547
12548         return status;
12549 }
12550
12551 /*
12552  * The eval command.
12553  */
12554 static int FAST_FUNC
12555 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12556 {
12557         char *p;
12558         char *concat;
12559
12560         if (argv[1]) {
12561                 p = argv[1];
12562                 argv += 2;
12563                 if (argv[0]) {
12564                         STARTSTACKSTR(concat);
12565                         for (;;) {
12566                                 concat = stack_putstr(p, concat);
12567                                 p = *argv++;
12568                                 if (p == NULL)
12569                                         break;
12570                                 STPUTC(' ', concat);
12571                         }
12572                         STPUTC('\0', concat);
12573                         p = grabstackstr(concat);
12574                 }
12575                 return evalstring(p, flags & EV_TESTED);
12576         }
12577         return 0;
12578 }
12579
12580 /*
12581  * Read and execute commands.
12582  * "Top" is nonzero for the top level command loop;
12583  * it turns on prompting if the shell is interactive.
12584  */
12585 static int
12586 cmdloop(int top)
12587 {
12588         union node *n;
12589         struct stackmark smark;
12590         int inter;
12591         int status = 0;
12592         int numeof = 0;
12593
12594         TRACE(("cmdloop(%d) called\n", top));
12595         for (;;) {
12596                 int skip;
12597
12598                 setstackmark(&smark);
12599 #if JOBS
12600                 if (doing_jobctl)
12601                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12602 #endif
12603                 inter = 0;
12604                 if (iflag && top) {
12605                         inter++;
12606                         chkmail();
12607                 }
12608                 n = parsecmd(inter);
12609 #if DEBUG
12610                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12611                         showtree(n);
12612 #endif
12613                 if (n == NODE_EOF) {
12614                         if (!top || numeof >= 50)
12615                                 break;
12616                         if (!stoppedjobs()) {
12617                                 if (!Iflag)
12618                                         break;
12619                                 out2str("\nUse \"exit\" to leave shell.\n");
12620                         }
12621                         numeof++;
12622                 } else if (nflag == 0) {
12623                         int i;
12624
12625                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12626                         job_warning >>= 1;
12627                         numeof = 0;
12628                         i = evaltree(n, 0);
12629                         if (n)
12630                                 status = i;
12631                 }
12632                 popstackmark(&smark);
12633                 skip = evalskip;
12634
12635                 if (skip) {
12636                         evalskip &= ~SKIPFUNC;
12637                         break;
12638                 }
12639         }
12640         return status;
12641 }
12642
12643 /*
12644  * Take commands from a file.  To be compatible we should do a path
12645  * search for the file, which is necessary to find sub-commands.
12646  */
12647 static char *
12648 find_dot_file(char *name)
12649 {
12650         char *fullname;
12651         const char *path = pathval();
12652         struct stat statb;
12653
12654         /* don't try this for absolute or relative paths */
12655         if (strchr(name, '/'))
12656                 return name;
12657
12658         while ((fullname = path_advance(&path, name)) != NULL) {
12659                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12660                         /*
12661                          * Don't bother freeing here, since it will
12662                          * be freed by the caller.
12663                          */
12664                         return fullname;
12665                 }
12666                 if (fullname != name)
12667                         stunalloc(fullname);
12668         }
12669
12670         /* not found in the PATH */
12671         ash_msg_and_raise_error("%s: not found", name);
12672         /* NOTREACHED */
12673 }
12674
12675 static int FAST_FUNC
12676 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12677 {
12678         /* "false; . empty_file; echo $?" should print 0, not 1: */
12679         int status = 0;
12680         char *fullname;
12681         char **argv;
12682         char *args_need_save;
12683         struct strlist *sp;
12684         volatile struct shparam saveparam;
12685
12686         for (sp = cmdenviron; sp; sp = sp->next)
12687                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12688
12689         nextopt(nullstr); /* handle possible "--" */
12690         argv = argptr;
12691
12692         if (!argv[0]) {
12693                 /* bash says: "bash: .: filename argument required" */
12694                 return 2; /* bash compat */
12695         }
12696
12697         /* This aborts if file isn't found, which is POSIXly correct.
12698          * bash returns exitcode 1 instead.
12699          */
12700         fullname = find_dot_file(argv[0]);
12701         argv++;
12702         args_need_save = argv[0];
12703         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12704                 int argc;
12705                 saveparam = shellparam;
12706                 shellparam.malloced = 0;
12707                 argc = 1;
12708                 while (argv[argc])
12709                         argc++;
12710                 shellparam.nparam = argc;
12711                 shellparam.p = argv;
12712         };
12713
12714         /* This aborts if file can't be opened, which is POSIXly correct.
12715          * bash returns exitcode 1 instead.
12716          */
12717         setinputfile(fullname, INPUT_PUSH_FILE);
12718         commandname = fullname;
12719         status = cmdloop(0);
12720         popfile();
12721
12722         if (args_need_save) {
12723                 freeparam(&shellparam);
12724                 shellparam = saveparam;
12725         };
12726
12727         return status;
12728 }
12729
12730 static int FAST_FUNC
12731 exitcmd(int argc UNUSED_PARAM, char **argv)
12732 {
12733         if (stoppedjobs())
12734                 return 0;
12735         if (argv[1])
12736                 exitstatus = number(argv[1]);
12737         raise_exception(EXEXIT);
12738         /* NOTREACHED */
12739 }
12740
12741 /*
12742  * Read a file containing shell functions.
12743  */
12744 static void
12745 readcmdfile(char *name)
12746 {
12747         setinputfile(name, INPUT_PUSH_FILE);
12748         cmdloop(0);
12749         popfile();
12750 }
12751
12752
12753 /* ============ find_command inplementation */
12754
12755 /*
12756  * Resolve a command name.  If you change this routine, you may have to
12757  * change the shellexec routine as well.
12758  */
12759 static void
12760 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12761 {
12762         struct tblentry *cmdp;
12763         int idx;
12764         int prev;
12765         char *fullname;
12766         struct stat statb;
12767         int e;
12768         int updatetbl;
12769         struct builtincmd *bcmd;
12770
12771         /* If name contains a slash, don't use PATH or hash table */
12772         if (strchr(name, '/') != NULL) {
12773                 entry->u.index = -1;
12774                 if (act & DO_ABS) {
12775                         while (stat(name, &statb) < 0) {
12776 #ifdef SYSV
12777                                 if (errno == EINTR)
12778                                         continue;
12779 #endif
12780                                 entry->cmdtype = CMDUNKNOWN;
12781                                 return;
12782                         }
12783                 }
12784                 entry->cmdtype = CMDNORMAL;
12785                 return;
12786         }
12787
12788 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12789
12790         updatetbl = (path == pathval());
12791         if (!updatetbl) {
12792                 act |= DO_ALTPATH;
12793                 if (strstr(path, "%builtin") != NULL)
12794                         act |= DO_ALTBLTIN;
12795         }
12796
12797         /* If name is in the table, check answer will be ok */
12798         cmdp = cmdlookup(name, 0);
12799         if (cmdp != NULL) {
12800                 int bit;
12801
12802                 switch (cmdp->cmdtype) {
12803                 default:
12804 #if DEBUG
12805                         abort();
12806 #endif
12807                 case CMDNORMAL:
12808                         bit = DO_ALTPATH;
12809                         break;
12810                 case CMDFUNCTION:
12811                         bit = DO_NOFUNC;
12812                         break;
12813                 case CMDBUILTIN:
12814                         bit = DO_ALTBLTIN;
12815                         break;
12816                 }
12817                 if (act & bit) {
12818                         updatetbl = 0;
12819                         cmdp = NULL;
12820                 } else if (cmdp->rehash == 0)
12821                         /* if not invalidated by cd, we're done */
12822                         goto success;
12823         }
12824
12825         /* If %builtin not in path, check for builtin next */
12826         bcmd = find_builtin(name);
12827         if (bcmd) {
12828                 if (IS_BUILTIN_REGULAR(bcmd))
12829                         goto builtin_success;
12830                 if (act & DO_ALTPATH) {
12831                         if (!(act & DO_ALTBLTIN))
12832                                 goto builtin_success;
12833                 } else if (builtinloc <= 0) {
12834                         goto builtin_success;
12835                 }
12836         }
12837
12838 #if ENABLE_FEATURE_SH_STANDALONE
12839         {
12840                 int applet_no = find_applet_by_name(name);
12841                 if (applet_no >= 0) {
12842                         entry->cmdtype = CMDNORMAL;
12843                         entry->u.index = -2 - applet_no;
12844                         return;
12845                 }
12846         }
12847 #endif
12848
12849         /* We have to search path. */
12850         prev = -1;              /* where to start */
12851         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12852                 if (cmdp->cmdtype == CMDBUILTIN)
12853                         prev = builtinloc;
12854                 else
12855                         prev = cmdp->param.index;
12856         }
12857
12858         e = ENOENT;
12859         idx = -1;
12860  loop:
12861         while ((fullname = path_advance(&path, name)) != NULL) {
12862                 stunalloc(fullname);
12863                 /* NB: code below will still use fullname
12864                  * despite it being "unallocated" */
12865                 idx++;
12866                 if (pathopt) {
12867                         if (prefix(pathopt, "builtin")) {
12868                                 if (bcmd)
12869                                         goto builtin_success;
12870                                 continue;
12871                         }
12872                         if ((act & DO_NOFUNC)
12873                          || !prefix(pathopt, "func")
12874                         ) {     /* ignore unimplemented options */
12875                                 continue;
12876                         }
12877                 }
12878                 /* if rehash, don't redo absolute path names */
12879                 if (fullname[0] == '/' && idx <= prev) {
12880                         if (idx < prev)
12881                                 continue;
12882                         TRACE(("searchexec \"%s\": no change\n", name));
12883                         goto success;
12884                 }
12885                 while (stat(fullname, &statb) < 0) {
12886 #ifdef SYSV
12887                         if (errno == EINTR)
12888                                 continue;
12889 #endif
12890                         if (errno != ENOENT && errno != ENOTDIR)
12891                                 e = errno;
12892                         goto loop;
12893                 }
12894                 e = EACCES;     /* if we fail, this will be the error */
12895                 if (!S_ISREG(statb.st_mode))
12896                         continue;
12897                 if (pathopt) {          /* this is a %func directory */
12898                         stalloc(strlen(fullname) + 1);
12899                         /* NB: stalloc will return space pointed by fullname
12900                          * (because we don't have any intervening allocations
12901                          * between stunalloc above and this stalloc) */
12902                         readcmdfile(fullname);
12903                         cmdp = cmdlookup(name, 0);
12904                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12905                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12906                         stunalloc(fullname);
12907                         goto success;
12908                 }
12909                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12910                 if (!updatetbl) {
12911                         entry->cmdtype = CMDNORMAL;
12912                         entry->u.index = idx;
12913                         return;
12914                 }
12915                 INT_OFF;
12916                 cmdp = cmdlookup(name, 1);
12917                 cmdp->cmdtype = CMDNORMAL;
12918                 cmdp->param.index = idx;
12919                 INT_ON;
12920                 goto success;
12921         }
12922
12923         /* We failed.  If there was an entry for this command, delete it */
12924         if (cmdp && updatetbl)
12925                 delete_cmd_entry();
12926         if (act & DO_ERR)
12927                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12928         entry->cmdtype = CMDUNKNOWN;
12929         return;
12930
12931  builtin_success:
12932         if (!updatetbl) {
12933                 entry->cmdtype = CMDBUILTIN;
12934                 entry->u.cmd = bcmd;
12935                 return;
12936         }
12937         INT_OFF;
12938         cmdp = cmdlookup(name, 1);
12939         cmdp->cmdtype = CMDBUILTIN;
12940         cmdp->param.cmd = bcmd;
12941         INT_ON;
12942  success:
12943         cmdp->rehash = 0;
12944         entry->cmdtype = cmdp->cmdtype;
12945         entry->u = cmdp->param;
12946 }
12947
12948
12949 /*
12950  * The trap builtin.
12951  */
12952 static int FAST_FUNC
12953 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12954 {
12955         char *action;
12956         char **ap;
12957         int signo, exitcode;
12958
12959         nextopt(nullstr);
12960         ap = argptr;
12961         if (!*ap) {
12962                 for (signo = 0; signo < NSIG; signo++) {
12963                         char *tr = trap_ptr[signo];
12964                         if (tr) {
12965                                 /* note: bash adds "SIG", but only if invoked
12966                                  * as "bash". If called as "sh", or if set -o posix,
12967                                  * then it prints short signal names.
12968                                  * We are printing short names: */
12969                                 out1fmt("trap -- %s %s\n",
12970                                                 single_quote(tr),
12971                                                 get_signame(signo));
12972                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12973                  * In this case, we will exit very soon, no need to free(). */
12974                                 /* if (trap_ptr != trap && tp[0]) */
12975                                 /*      free(tr); */
12976                         }
12977                 }
12978                 /*
12979                 if (trap_ptr != trap) {
12980                         free(trap_ptr);
12981                         trap_ptr = trap;
12982                 }
12983                 */
12984                 return 0;
12985         }
12986
12987         action = NULL;
12988         if (ap[1])
12989                 action = *ap++;
12990         exitcode = 0;
12991         while (*ap) {
12992                 signo = get_signum(*ap);
12993                 if (signo < 0 || signo >= NSIG) {
12994                         /* Mimic bash message exactly */
12995                         ash_msg("%s: invalid signal specification", *ap);
12996                         exitcode = 1;
12997                         goto next;
12998                 }
12999                 INT_OFF;
13000                 if (action) {
13001                         if (LONE_DASH(action))
13002                                 action = NULL;
13003                         else {
13004                                 if (action[0]) /* not NULL and not "" and not "-" */
13005                                         may_have_traps = 1;
13006                                 action = ckstrdup(action);
13007                         }
13008                 }
13009                 free(trap[signo]);
13010                 trap[signo] = action;
13011                 if (signo != 0)
13012                         setsignal(signo);
13013                 INT_ON;
13014  next:
13015                 ap++;
13016         }
13017         return exitcode;
13018 }
13019
13020
13021 /* ============ Builtins */
13022
13023 #if ENABLE_ASH_HELP
13024 static int FAST_FUNC
13025 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13026 {
13027         unsigned col;
13028         unsigned i;
13029
13030         out1fmt(
13031                 "Built-in commands:\n"
13032                 "------------------\n");
13033         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13034                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13035                                         builtintab[i].name + 1);
13036                 if (col > 60) {
13037                         out1fmt("\n");
13038                         col = 0;
13039                 }
13040         }
13041 # if ENABLE_FEATURE_SH_STANDALONE
13042         {
13043                 const char *a = applet_names;
13044                 while (*a) {
13045                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13046                         if (col > 60) {
13047                                 out1fmt("\n");
13048                                 col = 0;
13049                         }
13050                         while (*a++ != '\0')
13051                                 continue;
13052                 }
13053         }
13054 # endif
13055         newline_and_flush(stdout);
13056         return EXIT_SUCCESS;
13057 }
13058 #endif
13059
13060 #if MAX_HISTORY
13061 static int FAST_FUNC
13062 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13063 {
13064         show_history(line_input_state);
13065         return EXIT_SUCCESS;
13066 }
13067 #endif
13068
13069 /*
13070  * The export and readonly commands.
13071  */
13072 static int FAST_FUNC
13073 exportcmd(int argc UNUSED_PARAM, char **argv)
13074 {
13075         struct var *vp;
13076         char *name;
13077         const char *p;
13078         char **aptr;
13079         char opt;
13080         int flag;
13081         int flag_off;
13082
13083         /* "readonly" in bash accepts, but ignores -n.
13084          * We do the same: it saves a conditional in nextopt's param.
13085          */
13086         flag_off = 0;
13087         while ((opt = nextopt("np")) != '\0') {
13088                 if (opt == 'n')
13089                         flag_off = VEXPORT;
13090         }
13091         flag = VEXPORT;
13092         if (argv[0][0] == 'r') {
13093                 flag = VREADONLY;
13094                 flag_off = 0; /* readonly ignores -n */
13095         }
13096         flag_off = ~flag_off;
13097
13098         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13099         {
13100                 aptr = argptr;
13101                 name = *aptr;
13102                 if (name) {
13103                         do {
13104                                 p = strchr(name, '=');
13105                                 if (p != NULL) {
13106                                         p++;
13107                                 } else {
13108                                         vp = *findvar(hashvar(name), name);
13109                                         if (vp) {
13110                                                 vp->flags = ((vp->flags | flag) & flag_off);
13111                                                 continue;
13112                                         }
13113                                 }
13114                                 setvar(name, p, (flag & flag_off));
13115                         } while ((name = *++aptr) != NULL);
13116                         return 0;
13117                 }
13118         }
13119
13120         /* No arguments. Show the list of exported or readonly vars.
13121          * -n is ignored.
13122          */
13123         showvars(argv[0], flag, 0);
13124         return 0;
13125 }
13126
13127 /*
13128  * Delete a function if it exists.
13129  */
13130 static void
13131 unsetfunc(const char *name)
13132 {
13133         struct tblentry *cmdp;
13134
13135         cmdp = cmdlookup(name, 0);
13136         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13137                 delete_cmd_entry();
13138 }
13139
13140 /*
13141  * The unset builtin command.  We unset the function before we unset the
13142  * variable to allow a function to be unset when there is a readonly variable
13143  * with the same name.
13144  */
13145 static int FAST_FUNC
13146 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13147 {
13148         char **ap;
13149         int i;
13150         int flag = 0;
13151         int ret = 0;
13152
13153         while ((i = nextopt("vf")) != 0) {
13154                 flag = i;
13155         }
13156
13157         for (ap = argptr; *ap; ap++) {
13158                 if (flag != 'f') {
13159                         i = unsetvar(*ap);
13160                         ret |= i;
13161                         if (!(i & 2))
13162                                 continue;
13163                 }
13164                 if (flag != 'v')
13165                         unsetfunc(*ap);
13166         }
13167         return ret & 1;
13168 }
13169
13170 static const unsigned char timescmd_str[] ALIGN1 = {
13171         ' ',  offsetof(struct tms, tms_utime),
13172         '\n', offsetof(struct tms, tms_stime),
13173         ' ',  offsetof(struct tms, tms_cutime),
13174         '\n', offsetof(struct tms, tms_cstime),
13175         0
13176 };
13177 static int FAST_FUNC
13178 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13179 {
13180         unsigned long clk_tck, s, t;
13181         const unsigned char *p;
13182         struct tms buf;
13183
13184         clk_tck = bb_clk_tck();
13185         times(&buf);
13186
13187         p = timescmd_str;
13188         do {
13189                 t = *(clock_t *)(((char *) &buf) + p[1]);
13190                 s = t / clk_tck;
13191                 t = t % clk_tck;
13192                 out1fmt("%lum%lu.%03lus%c",
13193                         s / 60, s % 60,
13194                         (t * 1000) / clk_tck,
13195                         p[0]);
13196                 p += 2;
13197         } while (*p);
13198
13199         return 0;
13200 }
13201
13202 #if ENABLE_FEATURE_SH_MATH
13203 /*
13204  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13205  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13206  *
13207  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13208  */
13209 static int FAST_FUNC
13210 letcmd(int argc UNUSED_PARAM, char **argv)
13211 {
13212         arith_t i;
13213
13214         argv++;
13215         if (!*argv)
13216                 ash_msg_and_raise_error("expression expected");
13217         do {
13218                 i = ash_arith(*argv);
13219         } while (*++argv);
13220
13221         return !i;
13222 }
13223 #endif
13224
13225 /*
13226  * The read builtin. Options:
13227  *      -r              Do not interpret '\' specially
13228  *      -s              Turn off echo (tty only)
13229  *      -n NCHARS       Read NCHARS max
13230  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13231  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13232  *      -u FD           Read from given FD instead of fd 0
13233  * This uses unbuffered input, which may be avoidable in some cases.
13234  * TODO: bash also has:
13235  *      -a ARRAY        Read into array[0],[1],etc
13236  *      -d DELIM        End on DELIM char, not newline
13237  *      -e              Use line editing (tty only)
13238  */
13239 static int FAST_FUNC
13240 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13241 {
13242         char *opt_n = NULL;
13243         char *opt_p = NULL;
13244         char *opt_t = NULL;
13245         char *opt_u = NULL;
13246         int read_flags = 0;
13247         const char *r;
13248         int i;
13249
13250         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13251                 switch (i) {
13252                 case 'p':
13253                         opt_p = optionarg;
13254                         break;
13255                 case 'n':
13256                         opt_n = optionarg;
13257                         break;
13258                 case 's':
13259                         read_flags |= BUILTIN_READ_SILENT;
13260                         break;
13261                 case 't':
13262                         opt_t = optionarg;
13263                         break;
13264                 case 'r':
13265                         read_flags |= BUILTIN_READ_RAW;
13266                         break;
13267                 case 'u':
13268                         opt_u = optionarg;
13269                         break;
13270                 default:
13271                         break;
13272                 }
13273         }
13274
13275         /* "read -s" needs to save/restore termios, can't allow ^C
13276          * to jump out of it.
13277          */
13278  again:
13279         INT_OFF;
13280         r = shell_builtin_read(setvar0,
13281                 argptr,
13282                 bltinlookup("IFS"), /* can be NULL */
13283                 read_flags,
13284                 opt_n,
13285                 opt_p,
13286                 opt_t,
13287                 opt_u
13288         );
13289         INT_ON;
13290
13291         if ((uintptr_t)r == 1 && errno == EINTR) {
13292                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13293                 if (pending_sig == 0)
13294                         goto again;
13295         }
13296
13297         if ((uintptr_t)r > 1)
13298                 ash_msg_and_raise_error(r);
13299
13300         return (uintptr_t)r;
13301 }
13302
13303 static int FAST_FUNC
13304 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13305 {
13306         static const char permuser[3] ALIGN1 = "ogu";
13307
13308         mode_t mask;
13309         int symbolic_mode = 0;
13310
13311         while (nextopt("S") != '\0') {
13312                 symbolic_mode = 1;
13313         }
13314
13315         INT_OFF;
13316         mask = umask(0);
13317         umask(mask);
13318         INT_ON;
13319
13320         if (*argptr == NULL) {
13321                 if (symbolic_mode) {
13322                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13323                         char *p = buf;
13324                         int i;
13325
13326                         i = 2;
13327                         for (;;) {
13328                                 *p++ = ',';
13329                                 *p++ = permuser[i];
13330                                 *p++ = '=';
13331                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13332                                 if (!(mask & 0400)) *p++ = 'r';
13333                                 if (!(mask & 0200)) *p++ = 'w';
13334                                 if (!(mask & 0100)) *p++ = 'x';
13335                                 mask <<= 3;
13336                                 if (--i < 0)
13337                                         break;
13338                         }
13339                         *p = '\0';
13340                         puts(buf + 1);
13341                 } else {
13342                         out1fmt("%04o\n", mask);
13343                 }
13344         } else {
13345                 char *modestr = *argptr;
13346                 /* numeric umasks are taken as-is */
13347                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13348                 if (!isdigit(modestr[0]))
13349                         mask ^= 0777;
13350                 mask = bb_parse_mode(modestr, mask);
13351                 if ((unsigned)mask > 0777) {
13352                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13353                 }
13354                 if (!isdigit(modestr[0]))
13355                         mask ^= 0777;
13356                 umask(mask);
13357         }
13358         return 0;
13359 }
13360
13361 static int FAST_FUNC
13362 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13363 {
13364         return shell_builtin_ulimit(argv);
13365 }
13366
13367 /* ============ main() and helpers */
13368
13369 /*
13370  * Called to exit the shell.
13371  */
13372 static void
13373 exitshell(void)
13374 {
13375         struct jmploc loc;
13376         char *p;
13377         int status;
13378
13379 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13380         save_history(line_input_state);
13381 #endif
13382         status = exitstatus;
13383         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13384         if (setjmp(loc.loc)) {
13385                 if (exception_type == EXEXIT)
13386                         status = exitstatus;
13387                 goto out;
13388         }
13389         exception_handler = &loc;
13390         p = trap[0];
13391         if (p) {
13392                 trap[0] = NULL;
13393                 evalskip = 0;
13394                 evalstring(p, 0);
13395                 /*free(p); - we'll exit soon */
13396         }
13397  out:
13398         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13399          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13400          */
13401         setjobctl(0);
13402         flush_stdout_stderr();
13403         _exit(status);
13404         /* NOTREACHED */
13405 }
13406
13407 static void
13408 init(void)
13409 {
13410         /* we will never free this */
13411         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13412
13413         sigmode[SIGCHLD - 1] = S_DFL;
13414         setsignal(SIGCHLD);
13415
13416         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13417          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13418          */
13419         signal(SIGHUP, SIG_DFL);
13420
13421         {
13422                 char **envp;
13423                 const char *p;
13424                 struct stat st1, st2;
13425
13426                 initvar();
13427                 for (envp = environ; envp && *envp; envp++) {
13428                         p = endofname(*envp);
13429                         if (p != *envp && *p == '=') {
13430                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13431                         }
13432                 }
13433
13434                 setvareq((char*)defoptindvar, VTEXTFIXED);
13435
13436                 setvar0("PPID", utoa(getppid()));
13437 #if BASH_SHLVL_VAR
13438                 p = lookupvar("SHLVL");
13439                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13440 #endif
13441 #if BASH_HOSTNAME_VAR
13442                 if (!lookupvar("HOSTNAME")) {
13443                         struct utsname uts;
13444                         uname(&uts);
13445                         setvar0("HOSTNAME", uts.nodename);
13446                 }
13447 #endif
13448                 p = lookupvar("PWD");
13449                 if (p) {
13450                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13451                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13452                         ) {
13453                                 p = NULL;
13454                         }
13455                 }
13456                 setpwd(p, 0);
13457         }
13458 }
13459
13460
13461 //usage:#define ash_trivial_usage
13462 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13463 //usage:#define ash_full_usage "\n\n"
13464 //usage:        "Unix shell interpreter"
13465
13466 /*
13467  * Process the shell command line arguments.
13468  */
13469 static void
13470 procargs(char **argv)
13471 {
13472         int i;
13473         const char *xminusc;
13474         char **xargv;
13475
13476         xargv = argv;
13477         arg0 = xargv[0];
13478         /* if (xargv[0]) - mmm, this is always true! */
13479                 xargv++;
13480         for (i = 0; i < NOPTS; i++)
13481                 optlist[i] = 2;
13482         argptr = xargv;
13483         if (options(/*cmdline:*/ 1)) {
13484                 /* it already printed err message */
13485                 raise_exception(EXERROR);
13486         }
13487         xargv = argptr;
13488         xminusc = minusc;
13489         if (*xargv == NULL) {
13490                 if (xminusc)
13491                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13492                 sflag = 1;
13493         }
13494         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13495                 iflag = 1;
13496         if (mflag == 2)
13497                 mflag = iflag;
13498         for (i = 0; i < NOPTS; i++)
13499                 if (optlist[i] == 2)
13500                         optlist[i] = 0;
13501 #if DEBUG == 2
13502         debug = 1;
13503 #endif
13504         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13505         if (xminusc) {
13506                 minusc = *xargv++;
13507                 if (*xargv)
13508                         goto setarg0;
13509         } else if (!sflag) {
13510                 setinputfile(*xargv, 0);
13511  setarg0:
13512                 arg0 = *xargv++;
13513                 commandname = arg0;
13514         }
13515
13516         shellparam.p = xargv;
13517 #if ENABLE_ASH_GETOPTS
13518         shellparam.optind = 1;
13519         shellparam.optoff = -1;
13520 #endif
13521         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13522         while (*xargv) {
13523                 shellparam.nparam++;
13524                 xargv++;
13525         }
13526         optschanged();
13527 }
13528
13529 /*
13530  * Read /etc/profile, ~/.profile, $ENV.
13531  */
13532 static void
13533 read_profile(const char *name)
13534 {
13535         name = expandstr(name);
13536         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13537                 return;
13538         cmdloop(0);
13539         popfile();
13540 }
13541
13542 /*
13543  * This routine is called when an error or an interrupt occurs in an
13544  * interactive shell and control is returned to the main command loop.
13545  * (In dash, this function is auto-generated by build machinery).
13546  */
13547 static void
13548 reset(void)
13549 {
13550         /* from eval.c: */
13551         evalskip = 0;
13552         loopnest = 0;
13553
13554         /* from expand.c: */
13555         ifsfree();
13556
13557         /* from input.c: */
13558         g_parsefile->left_in_buffer = 0;
13559         g_parsefile->left_in_line = 0;      /* clear input buffer */
13560         popallfiles();
13561
13562         /* from redir.c: */
13563         while (redirlist)
13564                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13565 }
13566
13567 #if PROFILE
13568 static short profile_buf[16384];
13569 extern int etext();
13570 #endif
13571
13572 /*
13573  * Main routine.  We initialize things, parse the arguments, execute
13574  * profiles if we're a login shell, and then call cmdloop to execute
13575  * commands.  The setjmp call sets up the location to jump to when an
13576  * exception occurs.  When an exception occurs the variable "state"
13577  * is used to figure out how far we had gotten.
13578  */
13579 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13580 int ash_main(int argc UNUSED_PARAM, char **argv)
13581 {
13582         volatile smallint state;
13583         struct jmploc jmploc;
13584         struct stackmark smark;
13585
13586         /* Initialize global data */
13587         INIT_G_misc();
13588         INIT_G_memstack();
13589         INIT_G_var();
13590 #if ENABLE_ASH_ALIAS
13591         INIT_G_alias();
13592 #endif
13593         INIT_G_cmdtable();
13594
13595 #if PROFILE
13596         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13597 #endif
13598
13599 #if ENABLE_FEATURE_EDITING
13600         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13601 #endif
13602         state = 0;
13603         if (setjmp(jmploc.loc)) {
13604                 smallint e;
13605                 smallint s;
13606
13607                 reset();
13608
13609                 e = exception_type;
13610                 s = state;
13611                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13612                         exitshell();
13613                 }
13614                 if (e == EXINT) {
13615                         newline_and_flush(stderr);
13616                 }
13617
13618                 popstackmark(&smark);
13619                 FORCE_INT_ON; /* enable interrupts */
13620                 if (s == 1)
13621                         goto state1;
13622                 if (s == 2)
13623                         goto state2;
13624                 if (s == 3)
13625                         goto state3;
13626                 goto state4;
13627         }
13628         exception_handler = &jmploc;
13629         rootpid = getpid();
13630
13631         init();
13632         setstackmark(&smark);
13633         procargs(argv);
13634 #if DEBUG
13635         TRACE(("Shell args: "));
13636         trace_puts_args(argv);
13637 #endif
13638
13639         if (argv[0] && argv[0][0] == '-')
13640                 isloginsh = 1;
13641         if (isloginsh) {
13642                 const char *hp;
13643
13644                 state = 1;
13645                 read_profile("/etc/profile");
13646  state1:
13647                 state = 2;
13648                 hp = lookupvar("HOME");
13649                 if (hp)
13650                         read_profile("$HOME/.profile");
13651         }
13652  state2:
13653         state = 3;
13654         if (
13655 #ifndef linux
13656          getuid() == geteuid() && getgid() == getegid() &&
13657 #endif
13658          iflag
13659         ) {
13660                 const char *shinit = lookupvar("ENV");
13661                 if (shinit != NULL && *shinit != '\0')
13662                         read_profile(shinit);
13663         }
13664         popstackmark(&smark);
13665  state3:
13666         state = 4;
13667         if (minusc) {
13668                 /* evalstring pushes parsefile stack.
13669                  * Ensure we don't falsely claim that 0 (stdin)
13670                  * is one of stacked source fds.
13671                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13672                 // if (!sflag) g_parsefile->pf_fd = -1;
13673                 // ^^ not necessary since now we special-case fd 0
13674                 // in is_hidden_fd() to not be considered "hidden fd"
13675                 evalstring(minusc, 0);
13676         }
13677
13678         if (sflag || minusc == NULL) {
13679 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13680                 if (iflag) {
13681                         const char *hp = lookupvar("HISTFILE");
13682                         if (!hp) {
13683                                 hp = lookupvar("HOME");
13684                                 if (hp) {
13685                                         INT_OFF;
13686                                         hp = concat_path_file(hp, ".ash_history");
13687                                         setvar0("HISTFILE", hp);
13688                                         free((char*)hp);
13689                                         INT_ON;
13690                                         hp = lookupvar("HISTFILE");
13691                                 }
13692                         }
13693                         if (hp)
13694                                 line_input_state->hist_file = hp;
13695 # if ENABLE_FEATURE_SH_HISTFILESIZE
13696                         hp = lookupvar("HISTFILESIZE");
13697                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13698 # endif
13699                 }
13700 #endif
13701  state4: /* XXX ??? - why isn't this before the "if" statement */
13702                 cmdloop(1);
13703         }
13704 #if PROFILE
13705         monitor(0);
13706 #endif
13707 #ifdef GPROF
13708         {
13709                 extern void _mcleanup(void);
13710                 _mcleanup();
13711         }
13712 #endif
13713         TRACE(("End of main reached\n"));
13714         exitshell();
13715         /* NOTREACHED */
13716 }
13717
13718
13719 /*-
13720  * Copyright (c) 1989, 1991, 1993, 1994
13721  *      The Regents of the University of California.  All rights reserved.
13722  *
13723  * This code is derived from software contributed to Berkeley by
13724  * Kenneth Almquist.
13725  *
13726  * Redistribution and use in source and binary forms, with or without
13727  * modification, are permitted provided that the following conditions
13728  * are met:
13729  * 1. Redistributions of source code must retain the above copyright
13730  *    notice, this list of conditions and the following disclaimer.
13731  * 2. Redistributions in binary form must reproduce the above copyright
13732  *    notice, this list of conditions and the following disclaimer in the
13733  *    documentation and/or other materials provided with the distribution.
13734  * 3. Neither the name of the University nor the names of its contributors
13735  *    may be used to endorse or promote products derived from this software
13736  *    without specific prior written permission.
13737  *
13738  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13739  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13740  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13741  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13742  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13743  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13744  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13745  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13746  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13747  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13748  * SUCH DAMAGE.
13749  */