ash,hush: ">&10" redirects to script/tty fds should not work
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps, int syntax_type);
2492 /* Values for syntax param */
2493 #define BASESYNTAX 0    /* not in quotes */
2494 #define DQSYNTAX   1    /* in double quotes */
2495 #define SQSYNTAX   2    /* in single quotes */
2496 #define ARISYNTAX  3    /* in arithmetic */
2497 #if ENABLE_ASH_EXPAND_PRMT
2498 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2499 #endif
2500 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2501
2502 /*
2503  * called by editline -- any expansions to the prompt should be added here.
2504  */
2505 static void
2506 setprompt_if(smallint do_set, int whichprompt)
2507 {
2508         const char *prompt;
2509         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2510
2511         if (!do_set)
2512                 return;
2513
2514         needprompt = 0;
2515
2516         switch (whichprompt) {
2517         case 1:
2518                 prompt = ps1val();
2519                 break;
2520         case 2:
2521                 prompt = ps2val();
2522                 break;
2523         default:                        /* 0 */
2524                 prompt = nullstr;
2525         }
2526 #if ENABLE_ASH_EXPAND_PRMT
2527         pushstackmark(&smark, stackblocksize());
2528         putprompt(expandstr(prompt, PSSYNTAX));
2529         popstackmark(&smark);
2530 #else
2531         putprompt(prompt);
2532 #endif
2533 }
2534
2535
2536 /* ============ The cd and pwd commands */
2537
2538 #define CD_PHYSICAL 1
2539 #define CD_PRINT 2
2540
2541 static int
2542 cdopt(void)
2543 {
2544         int flags = 0;
2545         int i, j;
2546
2547         j = 'L';
2548         while ((i = nextopt("LP")) != '\0') {
2549                 if (i != j) {
2550                         flags ^= CD_PHYSICAL;
2551                         j = i;
2552                 }
2553         }
2554
2555         return flags;
2556 }
2557
2558 /*
2559  * Update curdir (the name of the current directory) in response to a
2560  * cd command.
2561  */
2562 static const char *
2563 updatepwd(const char *dir)
2564 {
2565         char *new;
2566         char *p;
2567         char *cdcomppath;
2568         const char *lim;
2569
2570         cdcomppath = sstrdup(dir);
2571         STARTSTACKSTR(new);
2572         if (*dir != '/') {
2573                 if (curdir == nullstr)
2574                         return 0;
2575                 new = stack_putstr(curdir, new);
2576         }
2577         new = makestrspace(strlen(dir) + 2, new);
2578         lim = (char *)stackblock() + 1;
2579         if (*dir != '/') {
2580                 if (new[-1] != '/')
2581                         USTPUTC('/', new);
2582                 if (new > lim && *lim == '/')
2583                         lim++;
2584         } else {
2585                 USTPUTC('/', new);
2586                 cdcomppath++;
2587                 if (dir[1] == '/' && dir[2] != '/') {
2588                         USTPUTC('/', new);
2589                         cdcomppath++;
2590                         lim++;
2591                 }
2592         }
2593         p = strtok(cdcomppath, "/");
2594         while (p) {
2595                 switch (*p) {
2596                 case '.':
2597                         if (p[1] == '.' && p[2] == '\0') {
2598                                 while (new > lim) {
2599                                         STUNPUTC(new);
2600                                         if (new[-1] == '/')
2601                                                 break;
2602                                 }
2603                                 break;
2604                         }
2605                         if (p[1] == '\0')
2606                                 break;
2607                         /* fall through */
2608                 default:
2609                         new = stack_putstr(p, new);
2610                         USTPUTC('/', new);
2611                 }
2612                 p = strtok(NULL, "/");
2613         }
2614         if (new > lim)
2615                 STUNPUTC(new);
2616         *new = 0;
2617         return stackblock();
2618 }
2619
2620 /*
2621  * Find out what the current directory is. If we already know the current
2622  * directory, this routine returns immediately.
2623  */
2624 static char *
2625 getpwd(void)
2626 {
2627         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2628         return dir ? dir : nullstr;
2629 }
2630
2631 static void
2632 setpwd(const char *val, int setold)
2633 {
2634         char *oldcur, *dir;
2635
2636         oldcur = dir = curdir;
2637
2638         if (setold) {
2639                 setvar("OLDPWD", oldcur, VEXPORT);
2640         }
2641         INT_OFF;
2642         if (physdir != nullstr) {
2643                 if (physdir != oldcur)
2644                         free(physdir);
2645                 physdir = nullstr;
2646         }
2647         if (oldcur == val || !val) {
2648                 char *s = getpwd();
2649                 physdir = s;
2650                 if (!val)
2651                         dir = s;
2652         } else
2653                 dir = ckstrdup(val);
2654         if (oldcur != dir && oldcur != nullstr) {
2655                 free(oldcur);
2656         }
2657         curdir = dir;
2658         INT_ON;
2659         setvar("PWD", dir, VEXPORT);
2660 }
2661
2662 static void hashcd(void);
2663
2664 /*
2665  * Actually do the chdir.  We also call hashcd to let other routines
2666  * know that the current directory has changed.
2667  */
2668 static int
2669 docd(const char *dest, int flags)
2670 {
2671         const char *dir = NULL;
2672         int err;
2673
2674         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2675
2676         INT_OFF;
2677         if (!(flags & CD_PHYSICAL)) {
2678                 dir = updatepwd(dest);
2679                 if (dir)
2680                         dest = dir;
2681         }
2682         err = chdir(dest);
2683         if (err)
2684                 goto out;
2685         setpwd(dir, 1);
2686         hashcd();
2687  out:
2688         INT_ON;
2689         return err;
2690 }
2691
2692 static int FAST_FUNC
2693 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2694 {
2695         const char *dest;
2696         const char *path;
2697         const char *p;
2698         char c;
2699         struct stat statb;
2700         int flags;
2701
2702         flags = cdopt();
2703         dest = *argptr;
2704         if (!dest)
2705                 dest = bltinlookup("HOME");
2706         else if (LONE_DASH(dest)) {
2707                 dest = bltinlookup("OLDPWD");
2708                 flags |= CD_PRINT;
2709         }
2710         if (!dest)
2711                 dest = nullstr;
2712         if (*dest == '/')
2713                 goto step6;
2714         if (*dest == '.') {
2715                 c = dest[1];
2716  dotdot:
2717                 switch (c) {
2718                 case '\0':
2719                 case '/':
2720                         goto step6;
2721                 case '.':
2722                         c = dest[2];
2723                         if (c != '.')
2724                                 goto dotdot;
2725                 }
2726         }
2727         if (!*dest)
2728                 dest = ".";
2729         path = bltinlookup("CDPATH");
2730         while (path) {
2731                 c = *path;
2732                 p = path_advance(&path, dest);
2733                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2734                         if (c && c != ':')
2735                                 flags |= CD_PRINT;
2736  docd:
2737                         if (!docd(p, flags))
2738                                 goto out;
2739                         goto err;
2740                 }
2741         }
2742
2743  step6:
2744         p = dest;
2745         goto docd;
2746
2747  err:
2748         ash_msg_and_raise_error("can't cd to %s", dest);
2749         /* NOTREACHED */
2750  out:
2751         if (flags & CD_PRINT)
2752                 out1fmt("%s\n", curdir);
2753         return 0;
2754 }
2755
2756 static int FAST_FUNC
2757 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2758 {
2759         int flags;
2760         const char *dir = curdir;
2761
2762         flags = cdopt();
2763         if (flags) {
2764                 if (physdir == nullstr)
2765                         setpwd(dir, 0);
2766                 dir = physdir;
2767         }
2768         out1fmt("%s\n", dir);
2769         return 0;
2770 }
2771
2772
2773 /* ============ ... */
2774
2775
2776 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2777
2778 /* Syntax classes */
2779 #define CWORD     0             /* character is nothing special */
2780 #define CNL       1             /* newline character */
2781 #define CBACK     2             /* a backslash character */
2782 #define CSQUOTE   3             /* single quote */
2783 #define CDQUOTE   4             /* double quote */
2784 #define CENDQUOTE 5             /* a terminating quote */
2785 #define CBQUOTE   6             /* backwards single quote */
2786 #define CVAR      7             /* a dollar sign */
2787 #define CENDVAR   8             /* a '}' character */
2788 #define CLP       9             /* a left paren in arithmetic */
2789 #define CRP      10             /* a right paren in arithmetic */
2790 #define CENDFILE 11             /* end of file */
2791 #define CCTL     12             /* like CWORD, except it must be escaped */
2792 #define CSPCL    13             /* these terminate a word */
2793 #define CIGN     14             /* character should be ignored */
2794
2795 #define PEOF     256
2796 #if ENABLE_ASH_ALIAS
2797 # define PEOA    257
2798 #endif
2799
2800 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2801
2802 #if ENABLE_FEATURE_SH_MATH
2803 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2804 #else
2805 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2806 #endif
2807 static const uint16_t S_I_T[] ALIGN2 = {
2808 #if ENABLE_ASH_ALIAS
2809         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2810 #endif
2811         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2812         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2813         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2814         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2815         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2816         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2817         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2818         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2819         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2820         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2821         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2822 #if !USE_SIT_FUNCTION
2823         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2824         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2825         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2826 #endif
2827 #undef SIT_ITEM
2828 };
2829 /* Constants below must match table above */
2830 enum {
2831 #if ENABLE_ASH_ALIAS
2832         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2833 #endif
2834         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2835         CNL_CNL_CNL_CNL                    , /*  2 */
2836         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2837         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2838         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2839         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2840         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2841         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2842         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2843         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2844         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2845         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2846         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2847         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2848 };
2849
2850 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2851  * caller must ensure proper cast on it if c is *char_ptr!
2852  */
2853 #if USE_SIT_FUNCTION
2854
2855 static int
2856 SIT(int c, int syntax)
2857 {
2858         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2859         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2860         /*
2861          * This causes '/' to be prepended with CTLESC in dquoted string,
2862          * making "./file"* treated incorrectly because we feed
2863          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2864          * The "homegrown" glob implementation is okay with that,
2865          * but glibc one isn't. With '/' always treated as CWORD,
2866          * both work fine.
2867          */
2868 # if ENABLE_ASH_ALIAS
2869         static const uint8_t syntax_index_table[] ALIGN1 = {
2870                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2871                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2872                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2873                 11, 3                           /* "}~" */
2874         };
2875 # else
2876         static const uint8_t syntax_index_table[] ALIGN1 = {
2877                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2878                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2879                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2880                 10, 2                           /* "}~" */
2881         };
2882 # endif
2883         const char *s;
2884         int indx;
2885
2886         if (c == PEOF)
2887                 return CENDFILE;
2888 # if ENABLE_ASH_ALIAS
2889         if (c == PEOA)
2890                 indx = 0;
2891         else
2892 # endif
2893         {
2894                 /* Cast is purely for paranoia here,
2895                  * just in case someone passed signed char to us */
2896                 if ((unsigned char)c >= CTL_FIRST
2897                  && (unsigned char)c <= CTL_LAST
2898                 ) {
2899                         return CCTL;
2900                 }
2901                 s = strchrnul(spec_symbls, c);
2902                 if (*s == '\0')
2903                         return CWORD;
2904                 indx = syntax_index_table[s - spec_symbls];
2905         }
2906         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2907 }
2908
2909 #else   /* !USE_SIT_FUNCTION */
2910
2911 static const uint8_t syntax_index_table[] ALIGN1 = {
2912         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2913         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2923         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2924         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2946         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2947         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2948         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2950         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2952         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2953         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2954         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2955         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2956         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2958         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2960 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2961         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2973         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2974         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2975         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2978         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3006         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3007         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3008         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3009         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3011         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3039         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3040         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3041         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3042         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3043         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3044         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3045         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3046         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3047         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3048         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3049         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3050         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3051         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3170         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3171 # if ENABLE_ASH_ALIAS
3172         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3173 # endif
3174 };
3175
3176 #if 1
3177 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3178 #else /* debug version, caught one signed char bug */
3179 # define SIT(c, syntax) \
3180         ({ \
3181                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3182                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3183                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3184                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3185                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3186         })
3187 #endif
3188
3189 #endif  /* !USE_SIT_FUNCTION */
3190
3191
3192 /* ============ Alias handling */
3193
3194 #if ENABLE_ASH_ALIAS
3195
3196 #define ALIASINUSE 1
3197 #define ALIASDEAD  2
3198
3199 struct alias {
3200         struct alias *next;
3201         char *name;
3202         char *val;
3203         int flag;
3204 };
3205
3206
3207 static struct alias **atab; // [ATABSIZE];
3208 #define INIT_G_alias() do { \
3209         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3210 } while (0)
3211
3212
3213 static struct alias **
3214 __lookupalias(const char *name)
3215 {
3216         unsigned int hashval;
3217         struct alias **app;
3218         const char *p;
3219         unsigned int ch;
3220
3221         p = name;
3222
3223         ch = (unsigned char)*p;
3224         hashval = ch << 4;
3225         while (ch) {
3226                 hashval += ch;
3227                 ch = (unsigned char)*++p;
3228         }
3229         app = &atab[hashval % ATABSIZE];
3230
3231         for (; *app; app = &(*app)->next) {
3232                 if (strcmp(name, (*app)->name) == 0) {
3233                         break;
3234                 }
3235         }
3236
3237         return app;
3238 }
3239
3240 static struct alias *
3241 lookupalias(const char *name, int check)
3242 {
3243         struct alias *ap = *__lookupalias(name);
3244
3245         if (check && ap && (ap->flag & ALIASINUSE))
3246                 return NULL;
3247         return ap;
3248 }
3249
3250 static struct alias *
3251 freealias(struct alias *ap)
3252 {
3253         struct alias *next;
3254
3255         if (ap->flag & ALIASINUSE) {
3256                 ap->flag |= ALIASDEAD;
3257                 return ap;
3258         }
3259
3260         next = ap->next;
3261         free(ap->name);
3262         free(ap->val);
3263         free(ap);
3264         return next;
3265 }
3266
3267 static void
3268 setalias(const char *name, const char *val)
3269 {
3270         struct alias *ap, **app;
3271
3272         app = __lookupalias(name);
3273         ap = *app;
3274         INT_OFF;
3275         if (ap) {
3276                 if (!(ap->flag & ALIASINUSE)) {
3277                         free(ap->val);
3278                 }
3279                 ap->val = ckstrdup(val);
3280                 ap->flag &= ~ALIASDEAD;
3281         } else {
3282                 /* not found */
3283                 ap = ckzalloc(sizeof(struct alias));
3284                 ap->name = ckstrdup(name);
3285                 ap->val = ckstrdup(val);
3286                 /*ap->flag = 0; - ckzalloc did it */
3287                 /*ap->next = NULL;*/
3288                 *app = ap;
3289         }
3290         INT_ON;
3291 }
3292
3293 static int
3294 unalias(const char *name)
3295 {
3296         struct alias **app;
3297
3298         app = __lookupalias(name);
3299
3300         if (*app) {
3301                 INT_OFF;
3302                 *app = freealias(*app);
3303                 INT_ON;
3304                 return 0;
3305         }
3306
3307         return 1;
3308 }
3309
3310 static void
3311 rmaliases(void)
3312 {
3313         struct alias *ap, **app;
3314         int i;
3315
3316         INT_OFF;
3317         for (i = 0; i < ATABSIZE; i++) {
3318                 app = &atab[i];
3319                 for (ap = *app; ap; ap = *app) {
3320                         *app = freealias(*app);
3321                         if (ap == *app) {
3322                                 app = &ap->next;
3323                         }
3324                 }
3325         }
3326         INT_ON;
3327 }
3328
3329 static void
3330 printalias(const struct alias *ap)
3331 {
3332         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3333 }
3334
3335 /*
3336  * TODO - sort output
3337  */
3338 static int FAST_FUNC
3339 aliascmd(int argc UNUSED_PARAM, char **argv)
3340 {
3341         char *n, *v;
3342         int ret = 0;
3343         struct alias *ap;
3344
3345         if (!argv[1]) {
3346                 int i;
3347
3348                 for (i = 0; i < ATABSIZE; i++) {
3349                         for (ap = atab[i]; ap; ap = ap->next) {
3350                                 printalias(ap);
3351                         }
3352                 }
3353                 return 0;
3354         }
3355         while ((n = *++argv) != NULL) {
3356                 v = strchr(n+1, '=');
3357                 if (v == NULL) { /* n+1: funny ksh stuff */
3358                         ap = *__lookupalias(n);
3359                         if (ap == NULL) {
3360                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3361                                 ret = 1;
3362                         } else
3363                                 printalias(ap);
3364                 } else {
3365                         *v++ = '\0';
3366                         setalias(n, v);
3367                 }
3368         }
3369
3370         return ret;
3371 }
3372
3373 static int FAST_FUNC
3374 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3375 {
3376         int i;
3377
3378         while (nextopt("a") != '\0') {
3379                 rmaliases();
3380                 return 0;
3381         }
3382         for (i = 0; *argptr; argptr++) {
3383                 if (unalias(*argptr)) {
3384                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3385                         i = 1;
3386                 }
3387         }
3388
3389         return i;
3390 }
3391
3392 #endif /* ASH_ALIAS */
3393
3394
3395 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3396 #define FORK_FG    0
3397 #define FORK_BG    1
3398 #define FORK_NOJOB 2
3399
3400 /* mode flags for showjob(s) */
3401 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3402 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3403 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3404 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3405
3406 /*
3407  * A job structure contains information about a job.  A job is either a
3408  * single process or a set of processes contained in a pipeline.  In the
3409  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3410  * array of pids.
3411  */
3412 struct procstat {
3413         pid_t   ps_pid;         /* process id */
3414         int     ps_status;      /* last process status from wait() */
3415         char    *ps_cmd;        /* text of command being run */
3416 };
3417
3418 struct job {
3419         struct procstat ps0;    /* status of process */
3420         struct procstat *ps;    /* status or processes when more than one */
3421 #if JOBS
3422         int stopstatus;         /* status of a stopped job */
3423 #endif
3424         unsigned nprocs;        /* number of processes */
3425
3426 #define JOBRUNNING      0       /* at least one proc running */
3427 #define JOBSTOPPED      1       /* all procs are stopped */
3428 #define JOBDONE         2       /* all procs are completed */
3429         unsigned
3430                 state: 8,
3431 #if JOBS
3432                 sigint: 1,      /* job was killed by SIGINT */
3433                 jobctl: 1,      /* job running under job control */
3434 #endif
3435                 waited: 1,      /* true if this entry has been waited for */
3436                 used: 1,        /* true if this entry is in used */
3437                 changed: 1;     /* true if status has changed */
3438         struct job *prev_job;   /* previous job */
3439 };
3440
3441 static struct job *makejob(/*union node *,*/ int);
3442 static int forkshell(struct job *, union node *, int);
3443 static int waitforjob(struct job *);
3444
3445 #if !JOBS
3446 enum { doing_jobctl = 0 };
3447 #define setjobctl(on) do {} while (0)
3448 #else
3449 static smallint doing_jobctl; //references:8
3450 static void setjobctl(int);
3451 #endif
3452
3453 /*
3454  * Ignore a signal.
3455  */
3456 static void
3457 ignoresig(int signo)
3458 {
3459         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3460         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3461                 /* No, need to do it */
3462                 signal(signo, SIG_IGN);
3463         }
3464         sigmode[signo - 1] = S_HARD_IGN;
3465 }
3466
3467 /*
3468  * Only one usage site - in setsignal()
3469  */
3470 static void
3471 signal_handler(int signo)
3472 {
3473         if (signo == SIGCHLD) {
3474                 got_sigchld = 1;
3475                 if (!trap[SIGCHLD])
3476                         return;
3477         }
3478
3479         gotsig[signo - 1] = 1;
3480         pending_sig = signo;
3481
3482         if (signo == SIGINT && !trap[SIGINT]) {
3483                 if (!suppress_int) {
3484                         pending_sig = 0;
3485                         raise_interrupt(); /* does not return */
3486                 }
3487                 pending_int = 1;
3488         }
3489 }
3490
3491 /*
3492  * Set the signal handler for the specified signal.  The routine figures
3493  * out what it should be set to.
3494  */
3495 static void
3496 setsignal(int signo)
3497 {
3498         char *t;
3499         char cur_act, new_act;
3500         struct sigaction act;
3501
3502         t = trap[signo];
3503         new_act = S_DFL;
3504         if (t != NULL) { /* trap for this sig is set */
3505                 new_act = S_CATCH;
3506                 if (t[0] == '\0') /* trap is "": ignore this sig */
3507                         new_act = S_IGN;
3508         }
3509
3510         if (rootshell && new_act == S_DFL) {
3511                 switch (signo) {
3512                 case SIGINT:
3513                         if (iflag || minusc || sflag == 0)
3514                                 new_act = S_CATCH;
3515                         break;
3516                 case SIGQUIT:
3517 #if DEBUG
3518                         if (debug)
3519                                 break;
3520 #endif
3521                         /* man bash:
3522                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3523                          * commands run by bash have signal handlers
3524                          * set to the values inherited by the shell
3525                          * from its parent". */
3526                         new_act = S_IGN;
3527                         break;
3528                 case SIGTERM:
3529                         if (iflag)
3530                                 new_act = S_IGN;
3531                         break;
3532 #if JOBS
3533                 case SIGTSTP:
3534                 case SIGTTOU:
3535                         if (mflag)
3536                                 new_act = S_IGN;
3537                         break;
3538 #endif
3539                 }
3540         }
3541 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3542 //whereas we have to restore it to what shell got on entry
3543 //from the parent. See comment above
3544
3545         if (signo == SIGCHLD)
3546                 new_act = S_CATCH;
3547
3548         t = &sigmode[signo - 1];
3549         cur_act = *t;
3550         if (cur_act == 0) {
3551                 /* current setting is not yet known */
3552                 if (sigaction(signo, NULL, &act)) {
3553                         /* pretend it worked; maybe we should give a warning,
3554                          * but other shells don't. We don't alter sigmode,
3555                          * so we retry every time.
3556                          * btw, in Linux it never fails. --vda */
3557                         return;
3558                 }
3559                 if (act.sa_handler == SIG_IGN) {
3560                         cur_act = S_HARD_IGN;
3561                         if (mflag
3562                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3563                         ) {
3564                                 cur_act = S_IGN;   /* don't hard ignore these */
3565                         }
3566                 }
3567         }
3568         if (cur_act == S_HARD_IGN || cur_act == new_act)
3569                 return;
3570
3571         act.sa_handler = SIG_DFL;
3572         switch (new_act) {
3573         case S_CATCH:
3574                 act.sa_handler = signal_handler;
3575                 break;
3576         case S_IGN:
3577                 act.sa_handler = SIG_IGN;
3578                 break;
3579         }
3580
3581         /* flags and mask matter only if !DFL and !IGN, but we do it
3582          * for all cases for more deterministic behavior:
3583          */
3584         act.sa_flags = 0;
3585         sigfillset(&act.sa_mask);
3586
3587         sigaction_set(signo, &act);
3588
3589         *t = new_act;
3590 }
3591
3592 /* mode flags for set_curjob */
3593 #define CUR_DELETE 2
3594 #define CUR_RUNNING 1
3595 #define CUR_STOPPED 0
3596
3597 #if JOBS
3598 /* pgrp of shell on invocation */
3599 static int initialpgrp; //references:2
3600 static int ttyfd = -1; //5
3601 #endif
3602 /* array of jobs */
3603 static struct job *jobtab; //5
3604 /* size of array */
3605 static unsigned njobs; //4
3606 /* current job */
3607 static struct job *curjob; //lots
3608 /* number of presumed living untracked jobs */
3609 static int jobless; //4
3610
3611 #if 0
3612 /* Bash has a feature: it restores termios after a successful wait for
3613  * a foreground job which had at least one stopped or sigkilled member.
3614  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3615  * properly restoring tty state. Should we do this too?
3616  * A reproducer: ^Z an interactive python:
3617  *
3618  * # python
3619  * Python 2.7.12 (...)
3620  * >>> ^Z
3621  *      { python leaves tty in -icanon -echo state. We do survive that... }
3622  *  [1]+  Stopped                    python
3623  *      { ...however, next program (python #2) does not survive it well: }
3624  * # python
3625  * Python 2.7.12 (...)
3626  * >>> Traceback (most recent call last):
3627  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3628  *   File "<stdin>", line 1, in <module>
3629  * NameError: name 'qwerty' is not defined
3630  *
3631  * The implementation below is modeled on bash code and seems to work.
3632  * However, I'm not sure we should do this. For one: what if I'd fg
3633  * the stopped python instead? It'll be confused by "restored" tty state.
3634  */
3635 static struct termios shell_tty_info;
3636 static void
3637 get_tty_state(void)
3638 {
3639         if (rootshell && ttyfd >= 0)
3640                 tcgetattr(ttyfd, &shell_tty_info);
3641 }
3642 static void
3643 set_tty_state(void)
3644 {
3645         /* if (rootshell) - caller ensures this */
3646         if (ttyfd >= 0)
3647                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3648 }
3649 static int
3650 job_signal_status(struct job *jp)
3651 {
3652         int status;
3653         unsigned i;
3654         struct procstat *ps = jp->ps;
3655         for (i = 0; i < jp->nprocs; i++) {
3656                 status = ps[i].ps_status;
3657                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3658                         return status;
3659         }
3660         return 0;
3661 }
3662 static void
3663 restore_tty_if_stopped_or_signaled(struct job *jp)
3664 {
3665 //TODO: check what happens if we come from waitforjob() in expbackq()
3666         if (rootshell) {
3667                 int s = job_signal_status(jp);
3668                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3669                         set_tty_state();
3670         }
3671 }
3672 #else
3673 # define get_tty_state() ((void)0)
3674 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3675 #endif
3676
3677 static void
3678 set_curjob(struct job *jp, unsigned mode)
3679 {
3680         struct job *jp1;
3681         struct job **jpp, **curp;
3682
3683         /* first remove from list */
3684         jpp = curp = &curjob;
3685         while (1) {
3686                 jp1 = *jpp;
3687                 if (jp1 == jp)
3688                         break;
3689                 jpp = &jp1->prev_job;
3690         }
3691         *jpp = jp1->prev_job;
3692
3693         /* Then re-insert in correct position */
3694         jpp = curp;
3695         switch (mode) {
3696         default:
3697 #if DEBUG
3698                 abort();
3699 #endif
3700         case CUR_DELETE:
3701                 /* job being deleted */
3702                 break;
3703         case CUR_RUNNING:
3704                 /* newly created job or backgrounded job,
3705                  * put after all stopped jobs.
3706                  */
3707                 while (1) {
3708                         jp1 = *jpp;
3709 #if JOBS
3710                         if (!jp1 || jp1->state != JOBSTOPPED)
3711 #endif
3712                                 break;
3713                         jpp = &jp1->prev_job;
3714                 }
3715                 /* FALLTHROUGH */
3716 #if JOBS
3717         case CUR_STOPPED:
3718 #endif
3719                 /* newly stopped job - becomes curjob */
3720                 jp->prev_job = *jpp;
3721                 *jpp = jp;
3722                 break;
3723         }
3724 }
3725
3726 #if JOBS || DEBUG
3727 static int
3728 jobno(const struct job *jp)
3729 {
3730         return jp - jobtab + 1;
3731 }
3732 #endif
3733
3734 /*
3735  * Convert a job name to a job structure.
3736  */
3737 #if !JOBS
3738 #define getjob(name, getctl) getjob(name)
3739 #endif
3740 static struct job *
3741 getjob(const char *name, int getctl)
3742 {
3743         struct job *jp;
3744         struct job *found;
3745         const char *err_msg = "%s: no such job";
3746         unsigned num;
3747         int c;
3748         const char *p;
3749         char *(*match)(const char *, const char *);
3750
3751         jp = curjob;
3752         p = name;
3753         if (!p)
3754                 goto currentjob;
3755
3756         if (*p != '%')
3757                 goto err;
3758
3759         c = *++p;
3760         if (!c)
3761                 goto currentjob;
3762
3763         if (!p[1]) {
3764                 if (c == '+' || c == '%') {
3765  currentjob:
3766                         err_msg = "No current job";
3767                         goto check;
3768                 }
3769                 if (c == '-') {
3770                         if (jp)
3771                                 jp = jp->prev_job;
3772                         err_msg = "No previous job";
3773  check:
3774                         if (!jp)
3775                                 goto err;
3776                         goto gotit;
3777                 }
3778         }
3779
3780         if (is_number(p)) {
3781                 num = atoi(p);
3782                 if (num > 0 && num <= njobs) {
3783                         jp = jobtab + num - 1;
3784                         if (jp->used)
3785                                 goto gotit;
3786                         goto err;
3787                 }
3788         }
3789
3790         match = prefix;
3791         if (*p == '?') {
3792                 match = strstr;
3793                 p++;
3794         }
3795
3796         found = NULL;
3797         while (jp) {
3798                 if (match(jp->ps[0].ps_cmd, p)) {
3799                         if (found)
3800                                 goto err;
3801                         found = jp;
3802                         err_msg = "%s: ambiguous";
3803                 }
3804                 jp = jp->prev_job;
3805         }
3806         if (!found)
3807                 goto err;
3808         jp = found;
3809
3810  gotit:
3811 #if JOBS
3812         err_msg = "job %s not created under job control";
3813         if (getctl && jp->jobctl == 0)
3814                 goto err;
3815 #endif
3816         return jp;
3817  err:
3818         ash_msg_and_raise_error(err_msg, name);
3819 }
3820
3821 /*
3822  * Mark a job structure as unused.
3823  */
3824 static void
3825 freejob(struct job *jp)
3826 {
3827         struct procstat *ps;
3828         int i;
3829
3830         INT_OFF;
3831         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3832                 if (ps->ps_cmd != nullstr)
3833                         free(ps->ps_cmd);
3834         }
3835         if (jp->ps != &jp->ps0)
3836                 free(jp->ps);
3837         jp->used = 0;
3838         set_curjob(jp, CUR_DELETE);
3839         INT_ON;
3840 }
3841
3842 #if JOBS
3843 static void
3844 xtcsetpgrp(int fd, pid_t pgrp)
3845 {
3846         if (tcsetpgrp(fd, pgrp))
3847                 ash_msg_and_raise_perror("can't set tty process group");
3848 }
3849
3850 /*
3851  * Turn job control on and off.
3852  *
3853  * Note:  This code assumes that the third arg to ioctl is a character
3854  * pointer, which is true on Berkeley systems but not System V.  Since
3855  * System V doesn't have job control yet, this isn't a problem now.
3856  *
3857  * Called with interrupts off.
3858  */
3859 static void
3860 setjobctl(int on)
3861 {
3862         int fd;
3863         int pgrp;
3864
3865         if (on == doing_jobctl || rootshell == 0)
3866                 return;
3867         if (on) {
3868                 int ofd;
3869                 ofd = fd = open(_PATH_TTY, O_RDWR);
3870                 if (fd < 0) {
3871         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3872          * That sometimes helps to acquire controlling tty.
3873          * Obviously, a workaround for bugs when someone
3874          * failed to provide a controlling tty to bash! :) */
3875                         fd = 2;
3876                         while (!isatty(fd))
3877                                 if (--fd < 0)
3878                                         goto out;
3879                 }
3880                 /* fd is a tty at this point */
3881                 fd = fcntl(fd, F_DUPFD, 10);
3882                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3883                         close(ofd);
3884                 if (fd < 0)
3885                         goto out; /* F_DUPFD failed */
3886                 close_on_exec_on(fd);
3887                 while (1) { /* while we are in the background */
3888                         pgrp = tcgetpgrp(fd);
3889                         if (pgrp < 0) {
3890  out:
3891                                 ash_msg("can't access tty; job control turned off");
3892                                 mflag = on = 0;
3893                                 goto close;
3894                         }
3895                         if (pgrp == getpgrp())
3896                                 break;
3897                         killpg(0, SIGTTIN);
3898                 }
3899                 initialpgrp = pgrp;
3900
3901                 setsignal(SIGTSTP);
3902                 setsignal(SIGTTOU);
3903                 setsignal(SIGTTIN);
3904                 pgrp = rootpid;
3905                 setpgid(0, pgrp);
3906                 xtcsetpgrp(fd, pgrp);
3907         } else {
3908                 /* turning job control off */
3909                 fd = ttyfd;
3910                 pgrp = initialpgrp;
3911                 /* was xtcsetpgrp, but this can make exiting ash
3912                  * loop forever if pty is already deleted */
3913                 tcsetpgrp(fd, pgrp);
3914                 setpgid(0, pgrp);
3915                 setsignal(SIGTSTP);
3916                 setsignal(SIGTTOU);
3917                 setsignal(SIGTTIN);
3918  close:
3919                 if (fd >= 0)
3920                         close(fd);
3921                 fd = -1;
3922         }
3923         ttyfd = fd;
3924         doing_jobctl = on;
3925 }
3926
3927 static int FAST_FUNC
3928 killcmd(int argc, char **argv)
3929 {
3930         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3931                 int i = 1;
3932                 do {
3933                         if (argv[i][0] == '%') {
3934                                 /*
3935                                  * "kill %N" - job kill
3936                                  * Converting to pgrp / pid kill
3937                                  */
3938                                 struct job *jp;
3939                                 char *dst;
3940                                 int j, n;
3941
3942                                 jp = getjob(argv[i], 0);
3943                                 /*
3944                                  * In jobs started under job control, we signal
3945                                  * entire process group by kill -PGRP_ID.
3946                                  * This happens, f.e., in interactive shell.
3947                                  *
3948                                  * Otherwise, we signal each child via
3949                                  * kill PID1 PID2 PID3.
3950                                  * Testcases:
3951                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3952                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3953                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3954                                  */
3955                                 n = jp->nprocs; /* can't be 0 (I hope) */
3956                                 if (jp->jobctl)
3957                                         n = 1;
3958                                 dst = alloca(n * sizeof(int)*4);
3959                                 argv[i] = dst;
3960                                 for (j = 0; j < n; j++) {
3961                                         struct procstat *ps = &jp->ps[j];
3962                                         /* Skip non-running and not-stopped members
3963                                          * (i.e. dead members) of the job
3964                                          */
3965                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3966                                                 continue;
3967                                         /*
3968                                          * kill_main has matching code to expect
3969                                          * leading space. Needed to not confuse
3970                                          * negative pids with "kill -SIGNAL_NO" syntax
3971                                          */
3972                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3973                                 }
3974                                 *dst = '\0';
3975                         }
3976                 } while (argv[++i]);
3977         }
3978         return kill_main(argc, argv);
3979 }
3980
3981 static void
3982 showpipe(struct job *jp /*, FILE *out*/)
3983 {
3984         struct procstat *ps;
3985         struct procstat *psend;
3986
3987         psend = jp->ps + jp->nprocs;
3988         for (ps = jp->ps + 1; ps < psend; ps++)
3989                 printf(" | %s", ps->ps_cmd);
3990         newline_and_flush(stdout);
3991         flush_stdout_stderr();
3992 }
3993
3994
3995 static int
3996 restartjob(struct job *jp, int mode)
3997 {
3998         struct procstat *ps;
3999         int i;
4000         int status;
4001         pid_t pgid;
4002
4003         INT_OFF;
4004         if (jp->state == JOBDONE)
4005                 goto out;
4006         jp->state = JOBRUNNING;
4007         pgid = jp->ps[0].ps_pid;
4008         if (mode == FORK_FG) {
4009                 get_tty_state();
4010                 xtcsetpgrp(ttyfd, pgid);
4011         }
4012         killpg(pgid, SIGCONT);
4013         ps = jp->ps;
4014         i = jp->nprocs;
4015         do {
4016                 if (WIFSTOPPED(ps->ps_status)) {
4017                         ps->ps_status = -1;
4018                 }
4019                 ps++;
4020         } while (--i);
4021  out:
4022         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4023         INT_ON;
4024         return status;
4025 }
4026
4027 static int FAST_FUNC
4028 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4029 {
4030         struct job *jp;
4031         int mode;
4032         int retval;
4033
4034         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4035         nextopt(nullstr);
4036         argv = argptr;
4037         do {
4038                 jp = getjob(*argv, 1);
4039                 if (mode == FORK_BG) {
4040                         set_curjob(jp, CUR_RUNNING);
4041                         printf("[%d] ", jobno(jp));
4042                 }
4043                 out1str(jp->ps[0].ps_cmd);
4044                 showpipe(jp /*, stdout*/);
4045                 retval = restartjob(jp, mode);
4046         } while (*argv && *++argv);
4047         return retval;
4048 }
4049 #endif
4050
4051 static int
4052 sprint_status48(char *s, int status, int sigonly)
4053 {
4054         int col;
4055         int st;
4056
4057         col = 0;
4058         if (!WIFEXITED(status)) {
4059 #if JOBS
4060                 if (WIFSTOPPED(status))
4061                         st = WSTOPSIG(status);
4062                 else
4063 #endif
4064                         st = WTERMSIG(status);
4065                 if (sigonly) {
4066                         if (st == SIGINT || st == SIGPIPE)
4067                                 goto out;
4068 #if JOBS
4069                         if (WIFSTOPPED(status))
4070                                 goto out;
4071 #endif
4072                 }
4073                 st &= 0x7f;
4074 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4075                 col = fmtstr(s, 32, strsignal(st));
4076                 if (WCOREDUMP(status)) {
4077                         strcpy(s + col, " (core dumped)");
4078                         col += sizeof(" (core dumped)")-1;
4079                 }
4080         } else if (!sigonly) {
4081                 st = WEXITSTATUS(status);
4082                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4083         }
4084  out:
4085         return col;
4086 }
4087
4088 static int
4089 wait_block_or_sig(int *status)
4090 {
4091         int pid;
4092
4093         do {
4094                 sigset_t mask;
4095
4096                 /* Poll all children for changes in their state */
4097                 got_sigchld = 0;
4098                 /* if job control is active, accept stopped processes too */
4099                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4100                 if (pid != 0)
4101                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4102
4103                 /* Children exist, but none are ready. Sleep until interesting signal */
4104 #if 1
4105                 sigfillset(&mask);
4106                 sigprocmask(SIG_SETMASK, &mask, &mask);
4107                 while (!got_sigchld && !pending_sig)
4108                         sigsuspend(&mask);
4109                 sigprocmask(SIG_SETMASK, &mask, NULL);
4110 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4111                 while (!got_sigchld && !pending_sig)
4112                         pause();
4113 #endif
4114
4115                 /* If it was SIGCHLD, poll children again */
4116         } while (got_sigchld);
4117
4118         return pid;
4119 }
4120
4121 #define DOWAIT_NONBLOCK 0
4122 #define DOWAIT_BLOCK    1
4123 #define DOWAIT_BLOCK_OR_SIG 2
4124
4125 static int
4126 dowait(int block, struct job *job)
4127 {
4128         int pid;
4129         int status;
4130         struct job *jp;
4131         struct job *thisjob = NULL;
4132
4133         TRACE(("dowait(0x%x) called\n", block));
4134
4135         /* It's wrong to call waitpid() outside of INT_OFF region:
4136          * signal can arrive just after syscall return and handler can
4137          * longjmp away, losing stop/exit notification processing.
4138          * Thus, for "jobs" builtin, and for waiting for a fg job,
4139          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4140          *
4141          * However, for "wait" builtin it is wrong to simply call waitpid()
4142          * in INT_OFF region: "wait" needs to wait for any running job
4143          * to change state, but should exit on any trap too.
4144          * In INT_OFF region, a signal just before syscall entry can set
4145          * pending_sig variables, but we can't check them, and we would
4146          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4147          *
4148          * Because of this, we run inside INT_OFF, but use a special routine
4149          * which combines waitpid() and sigsuspend().
4150          * This is the reason why we need to have a handler for SIGCHLD:
4151          * SIG_DFL handler does not wake sigsuspend().
4152          */
4153         INT_OFF;
4154         if (block == DOWAIT_BLOCK_OR_SIG) {
4155                 pid = wait_block_or_sig(&status);
4156         } else {
4157                 int wait_flags = 0;
4158                 if (block == DOWAIT_NONBLOCK)
4159                         wait_flags = WNOHANG;
4160                 /* if job control is active, accept stopped processes too */
4161                 if (doing_jobctl)
4162                         wait_flags |= WUNTRACED;
4163                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4164                 pid = waitpid(-1, &status, wait_flags);
4165         }
4166         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4167                                 pid, status, errno, strerror(errno)));
4168         if (pid <= 0)
4169                 goto out;
4170
4171         thisjob = NULL;
4172         for (jp = curjob; jp; jp = jp->prev_job) {
4173                 int jobstate;
4174                 struct procstat *ps;
4175                 struct procstat *psend;
4176                 if (jp->state == JOBDONE)
4177                         continue;
4178                 jobstate = JOBDONE;
4179                 ps = jp->ps;
4180                 psend = ps + jp->nprocs;
4181                 do {
4182                         if (ps->ps_pid == pid) {
4183                                 TRACE(("Job %d: changing status of proc %d "
4184                                         "from 0x%x to 0x%x\n",
4185                                         jobno(jp), pid, ps->ps_status, status));
4186                                 ps->ps_status = status;
4187                                 thisjob = jp;
4188                         }
4189                         if (ps->ps_status == -1)
4190                                 jobstate = JOBRUNNING;
4191 #if JOBS
4192                         if (jobstate == JOBRUNNING)
4193                                 continue;
4194                         if (WIFSTOPPED(ps->ps_status)) {
4195                                 jp->stopstatus = ps->ps_status;
4196                                 jobstate = JOBSTOPPED;
4197                         }
4198 #endif
4199                 } while (++ps < psend);
4200                 if (!thisjob)
4201                         continue;
4202
4203                 /* Found the job where one of its processes changed its state.
4204                  * Is there at least one live and running process in this job? */
4205                 if (jobstate != JOBRUNNING) {
4206                         /* No. All live processes in the job are stopped
4207                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4208                          */
4209                         thisjob->changed = 1;
4210                         if (thisjob->state != jobstate) {
4211                                 TRACE(("Job %d: changing state from %d to %d\n",
4212                                         jobno(thisjob), thisjob->state, jobstate));
4213                                 thisjob->state = jobstate;
4214 #if JOBS
4215                                 if (jobstate == JOBSTOPPED)
4216                                         set_curjob(thisjob, CUR_STOPPED);
4217 #endif
4218                         }
4219                 }
4220                 goto out;
4221         }
4222         /* The process wasn't found in job list */
4223 #if JOBS
4224         if (!WIFSTOPPED(status))
4225                 jobless--;
4226 #endif
4227  out:
4228         INT_ON;
4229
4230         if (thisjob && thisjob == job) {
4231                 char s[48 + 1];
4232                 int len;
4233
4234                 len = sprint_status48(s, status, 1);
4235                 if (len) {
4236                         s[len] = '\n';
4237                         s[len + 1] = '\0';
4238                         out2str(s);
4239                 }
4240         }
4241         return pid;
4242 }
4243
4244 #if JOBS
4245 static void
4246 showjob(struct job *jp, int mode)
4247 {
4248         struct procstat *ps;
4249         struct procstat *psend;
4250         int col;
4251         int indent_col;
4252         char s[16 + 16 + 48];
4253         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4254
4255         ps = jp->ps;
4256
4257         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4258                 /* just output process (group) id of pipeline */
4259                 fprintf(out, "%d\n", ps->ps_pid);
4260                 return;
4261         }
4262
4263         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4264         indent_col = col;
4265
4266         if (jp == curjob)
4267                 s[col - 3] = '+';
4268         else if (curjob && jp == curjob->prev_job)
4269                 s[col - 3] = '-';
4270
4271         if (mode & SHOW_PIDS)
4272                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4273
4274         psend = ps + jp->nprocs;
4275
4276         if (jp->state == JOBRUNNING) {
4277                 strcpy(s + col, "Running");
4278                 col += sizeof("Running") - 1;
4279         } else {
4280                 int status = psend[-1].ps_status;
4281                 if (jp->state == JOBSTOPPED)
4282                         status = jp->stopstatus;
4283                 col += sprint_status48(s + col, status, 0);
4284         }
4285         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4286
4287         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4288          * or prints several "PID             | <cmdN>" lines,
4289          * depending on SHOW_PIDS bit.
4290          * We do not print status of individual processes
4291          * between PID and <cmdN>. bash does it, but not very well:
4292          * first line shows overall job status, not process status,
4293          * making it impossible to know 1st process status.
4294          */
4295         goto start;
4296         do {
4297                 /* for each process */
4298                 s[0] = '\0';
4299                 col = 33;
4300                 if (mode & SHOW_PIDS)
4301                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4302  start:
4303                 fprintf(out, "%s%*c%s%s",
4304                                 s,
4305                                 33 - col >= 0 ? 33 - col : 0, ' ',
4306                                 ps == jp->ps ? "" : "| ",
4307                                 ps->ps_cmd
4308                 );
4309         } while (++ps != psend);
4310         newline_and_flush(out);
4311
4312         jp->changed = 0;
4313
4314         if (jp->state == JOBDONE) {
4315                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4316                 freejob(jp);
4317         }
4318 }
4319
4320 /*
4321  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4322  * statuses have changed since the last call to showjobs.
4323  */
4324 static void
4325 showjobs(int mode)
4326 {
4327         struct job *jp;
4328
4329         TRACE(("showjobs(0x%x) called\n", mode));
4330
4331         /* Handle all finished jobs */
4332         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4333                 continue;
4334
4335         for (jp = curjob; jp; jp = jp->prev_job) {
4336                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4337                         showjob(jp, mode);
4338                 }
4339         }
4340 }
4341
4342 static int FAST_FUNC
4343 jobscmd(int argc UNUSED_PARAM, char **argv)
4344 {
4345         int mode, m;
4346
4347         mode = 0;
4348         while ((m = nextopt("lp")) != '\0') {
4349                 if (m == 'l')
4350                         mode |= SHOW_PIDS;
4351                 else
4352                         mode |= SHOW_ONLY_PGID;
4353         }
4354
4355         argv = argptr;
4356         if (*argv) {
4357                 do
4358                         showjob(getjob(*argv, 0), mode);
4359                 while (*++argv);
4360         } else {
4361                 showjobs(mode);
4362         }
4363
4364         return 0;
4365 }
4366 #endif /* JOBS */
4367
4368 /* Called only on finished or stopped jobs (no members are running) */
4369 static int
4370 getstatus(struct job *job)
4371 {
4372         int status;
4373         int retval;
4374         struct procstat *ps;
4375
4376         /* Fetch last member's status */
4377         ps = job->ps + job->nprocs - 1;
4378         status = ps->ps_status;
4379         if (pipefail) {
4380                 /* "set -o pipefail" mode: use last _nonzero_ status */
4381                 while (status == 0 && --ps >= job->ps)
4382                         status = ps->ps_status;
4383         }
4384
4385         retval = WEXITSTATUS(status);
4386         if (!WIFEXITED(status)) {
4387 #if JOBS
4388                 retval = WSTOPSIG(status);
4389                 if (!WIFSTOPPED(status))
4390 #endif
4391                 {
4392                         /* XXX: limits number of signals */
4393                         retval = WTERMSIG(status);
4394 #if JOBS
4395                         if (retval == SIGINT)
4396                                 job->sigint = 1;
4397 #endif
4398                 }
4399                 retval += 128;
4400         }
4401         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4402                 jobno(job), job->nprocs, status, retval));
4403         return retval;
4404 }
4405
4406 static int FAST_FUNC
4407 waitcmd(int argc UNUSED_PARAM, char **argv)
4408 {
4409         struct job *job;
4410         int retval;
4411         struct job *jp;
4412
4413         nextopt(nullstr);
4414         retval = 0;
4415
4416         argv = argptr;
4417         if (!*argv) {
4418                 /* wait for all jobs */
4419                 for (;;) {
4420                         jp = curjob;
4421                         while (1) {
4422                                 if (!jp) /* no running procs */
4423                                         goto ret;
4424                                 if (jp->state == JOBRUNNING)
4425                                         break;
4426                                 jp->waited = 1;
4427                                 jp = jp->prev_job;
4428                         }
4429         /* man bash:
4430          * "When bash is waiting for an asynchronous command via
4431          * the wait builtin, the reception of a signal for which a trap
4432          * has been set will cause the wait builtin to return immediately
4433          * with an exit status greater than 128, immediately after which
4434          * the trap is executed."
4435          */
4436                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4437         /* if child sends us a signal *and immediately exits*,
4438          * dowait() returns pid > 0. Check this case,
4439          * not "if (dowait() < 0)"!
4440          */
4441                         if (pending_sig)
4442                                 goto sigout;
4443                 }
4444         }
4445
4446         retval = 127;
4447         do {
4448                 if (**argv != '%') {
4449                         pid_t pid = number(*argv);
4450                         job = curjob;
4451                         while (1) {
4452                                 if (!job)
4453                                         goto repeat;
4454                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4455                                         break;
4456                                 job = job->prev_job;
4457                         }
4458                 } else {
4459                         job = getjob(*argv, 0);
4460                 }
4461                 /* loop until process terminated or stopped */
4462                 while (job->state == JOBRUNNING) {
4463                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4464                         if (pending_sig)
4465                                 goto sigout;
4466                 }
4467                 job->waited = 1;
4468                 retval = getstatus(job);
4469  repeat: ;
4470         } while (*++argv);
4471
4472  ret:
4473         return retval;
4474  sigout:
4475         retval = 128 + pending_sig;
4476         return retval;
4477 }
4478
4479 static struct job *
4480 growjobtab(void)
4481 {
4482         size_t len;
4483         ptrdiff_t offset;
4484         struct job *jp, *jq;
4485
4486         len = njobs * sizeof(*jp);
4487         jq = jobtab;
4488         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4489
4490         offset = (char *)jp - (char *)jq;
4491         if (offset) {
4492                 /* Relocate pointers */
4493                 size_t l = len;
4494
4495                 jq = (struct job *)((char *)jq + l);
4496                 while (l) {
4497                         l -= sizeof(*jp);
4498                         jq--;
4499 #define joff(p) ((struct job *)((char *)(p) + l))
4500 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4501                         if (joff(jp)->ps == &jq->ps0)
4502                                 jmove(joff(jp)->ps);
4503                         if (joff(jp)->prev_job)
4504                                 jmove(joff(jp)->prev_job);
4505                 }
4506                 if (curjob)
4507                         jmove(curjob);
4508 #undef joff
4509 #undef jmove
4510         }
4511
4512         njobs += 4;
4513         jobtab = jp;
4514         jp = (struct job *)((char *)jp + len);
4515         jq = jp + 3;
4516         do {
4517                 jq->used = 0;
4518         } while (--jq >= jp);
4519         return jp;
4520 }
4521
4522 /*
4523  * Return a new job structure.
4524  * Called with interrupts off.
4525  */
4526 static struct job *
4527 makejob(/*union node *node,*/ int nprocs)
4528 {
4529         int i;
4530         struct job *jp;
4531
4532         for (i = njobs, jp = jobtab; ; jp++) {
4533                 if (--i < 0) {
4534                         jp = growjobtab();
4535                         break;
4536                 }
4537                 if (jp->used == 0)
4538                         break;
4539                 if (jp->state != JOBDONE || !jp->waited)
4540                         continue;
4541 #if JOBS
4542                 if (doing_jobctl)
4543                         continue;
4544 #endif
4545                 freejob(jp);
4546                 break;
4547         }
4548         memset(jp, 0, sizeof(*jp));
4549 #if JOBS
4550         /* jp->jobctl is a bitfield.
4551          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4552         if (doing_jobctl)
4553                 jp->jobctl = 1;
4554 #endif
4555         jp->prev_job = curjob;
4556         curjob = jp;
4557         jp->used = 1;
4558         jp->ps = &jp->ps0;
4559         if (nprocs > 1) {
4560                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4561         }
4562         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4563                                 jobno(jp)));
4564         return jp;
4565 }
4566
4567 #if JOBS
4568 /*
4569  * Return a string identifying a command (to be printed by the
4570  * jobs command).
4571  */
4572 static char *cmdnextc;
4573
4574 static void
4575 cmdputs(const char *s)
4576 {
4577         static const char vstype[VSTYPE + 1][3] = {
4578                 "", "}", "-", "+", "?", "=",
4579                 "%", "%%", "#", "##"
4580                 IF_BASH_SUBSTR(, ":")
4581                 IF_BASH_PATTERN_SUBST(, "/", "//")
4582         };
4583
4584         const char *p, *str;
4585         char cc[2];
4586         char *nextc;
4587         unsigned char c;
4588         unsigned char subtype = 0;
4589         int quoted = 0;
4590
4591         cc[1] = '\0';
4592         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4593         p = s;
4594         while ((c = *p++) != '\0') {
4595                 str = NULL;
4596                 switch (c) {
4597                 case CTLESC:
4598                         c = *p++;
4599                         break;
4600                 case CTLVAR:
4601                         subtype = *p++;
4602                         if ((subtype & VSTYPE) == VSLENGTH)
4603                                 str = "${#";
4604                         else
4605                                 str = "${";
4606                         goto dostr;
4607                 case CTLENDVAR:
4608                         str = "\"}" + !(quoted & 1);
4609                         quoted >>= 1;
4610                         subtype = 0;
4611                         goto dostr;
4612                 case CTLBACKQ:
4613                         str = "$(...)";
4614                         goto dostr;
4615 #if ENABLE_FEATURE_SH_MATH
4616                 case CTLARI:
4617                         str = "$((";
4618                         goto dostr;
4619                 case CTLENDARI:
4620                         str = "))";
4621                         goto dostr;
4622 #endif
4623                 case CTLQUOTEMARK:
4624                         quoted ^= 1;
4625                         c = '"';
4626                         break;
4627                 case '=':
4628                         if (subtype == 0)
4629                                 break;
4630                         if ((subtype & VSTYPE) != VSNORMAL)
4631                                 quoted <<= 1;
4632                         str = vstype[subtype & VSTYPE];
4633                         if (subtype & VSNUL)
4634                                 c = ':';
4635                         else
4636                                 goto checkstr;
4637                         break;
4638                 case '\'':
4639                 case '\\':
4640                 case '"':
4641                 case '$':
4642                         /* These can only happen inside quotes */
4643                         cc[0] = c;
4644                         str = cc;
4645                         c = '\\';
4646                         break;
4647                 default:
4648                         break;
4649                 }
4650                 USTPUTC(c, nextc);
4651  checkstr:
4652                 if (!str)
4653                         continue;
4654  dostr:
4655                 while ((c = *str++) != '\0') {
4656                         USTPUTC(c, nextc);
4657                 }
4658         } /* while *p++ not NUL */
4659
4660         if (quoted & 1) {
4661                 USTPUTC('"', nextc);
4662         }
4663         *nextc = 0;
4664         cmdnextc = nextc;
4665 }
4666
4667 /* cmdtxt() and cmdlist() call each other */
4668 static void cmdtxt(union node *n);
4669
4670 static void
4671 cmdlist(union node *np, int sep)
4672 {
4673         for (; np; np = np->narg.next) {
4674                 if (!sep)
4675                         cmdputs(" ");
4676                 cmdtxt(np);
4677                 if (sep && np->narg.next)
4678                         cmdputs(" ");
4679         }
4680 }
4681
4682 static void
4683 cmdtxt(union node *n)
4684 {
4685         union node *np;
4686         struct nodelist *lp;
4687         const char *p;
4688
4689         if (!n)
4690                 return;
4691         switch (n->type) {
4692         default:
4693 #if DEBUG
4694                 abort();
4695 #endif
4696         case NPIPE:
4697                 lp = n->npipe.cmdlist;
4698                 for (;;) {
4699                         cmdtxt(lp->n);
4700                         lp = lp->next;
4701                         if (!lp)
4702                                 break;
4703                         cmdputs(" | ");
4704                 }
4705                 break;
4706         case NSEMI:
4707                 p = "; ";
4708                 goto binop;
4709         case NAND:
4710                 p = " && ";
4711                 goto binop;
4712         case NOR:
4713                 p = " || ";
4714  binop:
4715                 cmdtxt(n->nbinary.ch1);
4716                 cmdputs(p);
4717                 n = n->nbinary.ch2;
4718                 goto donode;
4719         case NREDIR:
4720         case NBACKGND:
4721                 n = n->nredir.n;
4722                 goto donode;
4723         case NNOT:
4724                 cmdputs("!");
4725                 n = n->nnot.com;
4726  donode:
4727                 cmdtxt(n);
4728                 break;
4729         case NIF:
4730                 cmdputs("if ");
4731                 cmdtxt(n->nif.test);
4732                 cmdputs("; then ");
4733                 if (n->nif.elsepart) {
4734                         cmdtxt(n->nif.ifpart);
4735                         cmdputs("; else ");
4736                         n = n->nif.elsepart;
4737                 } else {
4738                         n = n->nif.ifpart;
4739                 }
4740                 p = "; fi";
4741                 goto dotail;
4742         case NSUBSHELL:
4743                 cmdputs("(");
4744                 n = n->nredir.n;
4745                 p = ")";
4746                 goto dotail;
4747         case NWHILE:
4748                 p = "while ";
4749                 goto until;
4750         case NUNTIL:
4751                 p = "until ";
4752  until:
4753                 cmdputs(p);
4754                 cmdtxt(n->nbinary.ch1);
4755                 n = n->nbinary.ch2;
4756                 p = "; done";
4757  dodo:
4758                 cmdputs("; do ");
4759  dotail:
4760                 cmdtxt(n);
4761                 goto dotail2;
4762         case NFOR:
4763                 cmdputs("for ");
4764                 cmdputs(n->nfor.var);
4765                 cmdputs(" in ");
4766                 cmdlist(n->nfor.args, 1);
4767                 n = n->nfor.body;
4768                 p = "; done";
4769                 goto dodo;
4770         case NDEFUN:
4771                 cmdputs(n->narg.text);
4772                 p = "() { ... }";
4773                 goto dotail2;
4774         case NCMD:
4775                 cmdlist(n->ncmd.args, 1);
4776                 cmdlist(n->ncmd.redirect, 0);
4777                 break;
4778         case NARG:
4779                 p = n->narg.text;
4780  dotail2:
4781                 cmdputs(p);
4782                 break;
4783         case NHERE:
4784         case NXHERE:
4785                 p = "<<...";
4786                 goto dotail2;
4787         case NCASE:
4788                 cmdputs("case ");
4789                 cmdputs(n->ncase.expr->narg.text);
4790                 cmdputs(" in ");
4791                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4792                         cmdtxt(np->nclist.pattern);
4793                         cmdputs(") ");
4794                         cmdtxt(np->nclist.body);
4795                         cmdputs(";; ");
4796                 }
4797                 p = "esac";
4798                 goto dotail2;
4799         case NTO:
4800                 p = ">";
4801                 goto redir;
4802         case NCLOBBER:
4803                 p = ">|";
4804                 goto redir;
4805         case NAPPEND:
4806                 p = ">>";
4807                 goto redir;
4808 #if BASH_REDIR_OUTPUT
4809         case NTO2:
4810 #endif
4811         case NTOFD:
4812                 p = ">&";
4813                 goto redir;
4814         case NFROM:
4815                 p = "<";
4816                 goto redir;
4817         case NFROMFD:
4818                 p = "<&";
4819                 goto redir;
4820         case NFROMTO:
4821                 p = "<>";
4822  redir:
4823                 cmdputs(utoa(n->nfile.fd));
4824                 cmdputs(p);
4825                 if (n->type == NTOFD || n->type == NFROMFD) {
4826                         cmdputs(utoa(n->ndup.dupfd));
4827                         break;
4828                 }
4829                 n = n->nfile.fname;
4830                 goto donode;
4831         }
4832 }
4833
4834 static char *
4835 commandtext(union node *n)
4836 {
4837         char *name;
4838
4839         STARTSTACKSTR(cmdnextc);
4840         cmdtxt(n);
4841         name = stackblock();
4842         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4843         return ckstrdup(name);
4844 }
4845 #endif /* JOBS */
4846
4847 /*
4848  * Fork off a subshell.  If we are doing job control, give the subshell its
4849  * own process group.  Jp is a job structure that the job is to be added to.
4850  * N is the command that will be evaluated by the child.  Both jp and n may
4851  * be NULL.  The mode parameter can be one of the following:
4852  *      FORK_FG - Fork off a foreground process.
4853  *      FORK_BG - Fork off a background process.
4854  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4855  *                   process group even if job control is on.
4856  *
4857  * When job control is turned off, background processes have their standard
4858  * input redirected to /dev/null (except for the second and later processes
4859  * in a pipeline).
4860  *
4861  * Called with interrupts off.
4862  */
4863 /*
4864  * Clear traps on a fork.
4865  */
4866 static void
4867 clear_traps(void)
4868 {
4869         char **tp;
4870
4871         INT_OFF;
4872         for (tp = trap; tp < &trap[NSIG]; tp++) {
4873                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4874                         if (trap_ptr == trap)
4875                                 free(*tp);
4876                         /* else: it "belongs" to trap_ptr vector, don't free */
4877                         *tp = NULL;
4878                         if ((tp - trap) != 0)
4879                                 setsignal(tp - trap);
4880                 }
4881         }
4882         may_have_traps = 0;
4883         INT_ON;
4884 }
4885
4886 /* Lives far away from here, needed for forkchild */
4887 static void closescript(void);
4888
4889 /* Called after fork(), in child */
4890 /* jp and n are NULL when called by openhere() for heredoc support */
4891 static NOINLINE void
4892 forkchild(struct job *jp, union node *n, int mode)
4893 {
4894         int oldlvl;
4895
4896         TRACE(("Child shell %d\n", getpid()));
4897         oldlvl = shlvl;
4898         shlvl++;
4899
4900         /* man bash: "Non-builtin commands run by bash have signal handlers
4901          * set to the values inherited by the shell from its parent".
4902          * Do we do it correctly? */
4903
4904         closescript();
4905
4906         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4907          && n && n->type == NCMD        /* is it single cmd? */
4908         /* && n->ncmd.args->type == NARG - always true? */
4909          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4910          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4911         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4912         ) {
4913                 TRACE(("Trap hack\n"));
4914                 /* Awful hack for `trap` or $(trap).
4915                  *
4916                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4917                  * contains an example where "trap" is executed in a subshell:
4918                  *
4919                  * save_traps=$(trap)
4920                  * ...
4921                  * eval "$save_traps"
4922                  *
4923                  * Standard does not say that "trap" in subshell shall print
4924                  * parent shell's traps. It only says that its output
4925                  * must have suitable form, but then, in the above example
4926                  * (which is not supposed to be normative), it implies that.
4927                  *
4928                  * bash (and probably other shell) does implement it
4929                  * (traps are reset to defaults, but "trap" still shows them),
4930                  * but as a result, "trap" logic is hopelessly messed up:
4931                  *
4932                  * # trap
4933                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4934                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4935                  * # true | trap   <--- trap is in subshell - no output (ditto)
4936                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4937                  * trap -- 'echo Ho' SIGWINCH
4938                  * # echo `(trap)`         <--- in subshell in subshell - output
4939                  * trap -- 'echo Ho' SIGWINCH
4940                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4941                  * trap -- 'echo Ho' SIGWINCH
4942                  *
4943                  * The rules when to forget and when to not forget traps
4944                  * get really complex and nonsensical.
4945                  *
4946                  * Our solution: ONLY bare $(trap) or `trap` is special.
4947                  */
4948                 /* Save trap handler strings for trap builtin to print */
4949                 trap_ptr = xmemdup(trap, sizeof(trap));
4950                 /* Fall through into clearing traps */
4951         }
4952         clear_traps();
4953 #if JOBS
4954         /* do job control only in root shell */
4955         doing_jobctl = 0;
4956         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4957                 pid_t pgrp;
4958
4959                 if (jp->nprocs == 0)
4960                         pgrp = getpid();
4961                 else
4962                         pgrp = jp->ps[0].ps_pid;
4963                 /* this can fail because we are doing it in the parent also */
4964                 setpgid(0, pgrp);
4965                 if (mode == FORK_FG)
4966                         xtcsetpgrp(ttyfd, pgrp);
4967                 setsignal(SIGTSTP);
4968                 setsignal(SIGTTOU);
4969         } else
4970 #endif
4971         if (mode == FORK_BG) {
4972                 /* man bash: "When job control is not in effect,
4973                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4974                 ignoresig(SIGINT);
4975                 ignoresig(SIGQUIT);
4976                 if (jp->nprocs == 0) {
4977                         close(0);
4978                         if (open(bb_dev_null, O_RDONLY) != 0)
4979                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4980                 }
4981         }
4982         if (oldlvl == 0) {
4983                 if (iflag) { /* why if iflag only? */
4984                         setsignal(SIGINT);
4985                         setsignal(SIGTERM);
4986                 }
4987                 /* man bash:
4988                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4989                  * commands run by bash have signal handlers
4990                  * set to the values inherited by the shell
4991                  * from its parent".
4992                  * Take care of the second rule: */
4993                 setsignal(SIGQUIT);
4994         }
4995 #if JOBS
4996         if (n && n->type == NCMD
4997          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4998         ) {
4999                 TRACE(("Job hack\n"));
5000                 /* "jobs": we do not want to clear job list for it,
5001                  * instead we remove only _its_ own_ job from job list.
5002                  * This makes "jobs .... | cat" more useful.
5003                  */
5004                 freejob(curjob);
5005                 return;
5006         }
5007 #endif
5008         for (jp = curjob; jp; jp = jp->prev_job)
5009                 freejob(jp);
5010         jobless = 0;
5011 }
5012
5013 /* Called after fork(), in parent */
5014 #if !JOBS
5015 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5016 #endif
5017 static void
5018 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5019 {
5020         TRACE(("In parent shell: child = %d\n", pid));
5021         if (!jp) {
5022                 /* jp is NULL when called by openhere() for heredoc support */
5023                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5024                         continue;
5025                 jobless++;
5026                 return;
5027         }
5028 #if JOBS
5029         if (mode != FORK_NOJOB && jp->jobctl) {
5030                 int pgrp;
5031
5032                 if (jp->nprocs == 0)
5033                         pgrp = pid;
5034                 else
5035                         pgrp = jp->ps[0].ps_pid;
5036                 /* This can fail because we are doing it in the child also */
5037                 setpgid(pid, pgrp);
5038         }
5039 #endif
5040         if (mode == FORK_BG) {
5041                 backgndpid = pid;               /* set $! */
5042                 set_curjob(jp, CUR_RUNNING);
5043         }
5044         if (jp) {
5045                 struct procstat *ps = &jp->ps[jp->nprocs++];
5046                 ps->ps_pid = pid;
5047                 ps->ps_status = -1;
5048                 ps->ps_cmd = nullstr;
5049 #if JOBS
5050                 if (doing_jobctl && n)
5051                         ps->ps_cmd = commandtext(n);
5052 #endif
5053         }
5054 }
5055
5056 /* jp and n are NULL when called by openhere() for heredoc support */
5057 static int
5058 forkshell(struct job *jp, union node *n, int mode)
5059 {
5060         int pid;
5061
5062         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5063         pid = fork();
5064         if (pid < 0) {
5065                 TRACE(("Fork failed, errno=%d", errno));
5066                 if (jp)
5067                         freejob(jp);
5068                 ash_msg_and_raise_error("can't fork");
5069         }
5070         if (pid == 0) {
5071                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5072                 forkchild(jp, n, mode);
5073         } else {
5074                 forkparent(jp, n, mode, pid);
5075         }
5076         return pid;
5077 }
5078
5079 /*
5080  * Wait for job to finish.
5081  *
5082  * Under job control we have the problem that while a child process
5083  * is running interrupts generated by the user are sent to the child
5084  * but not to the shell.  This means that an infinite loop started by
5085  * an interactive user may be hard to kill.  With job control turned off,
5086  * an interactive user may place an interactive program inside a loop.
5087  * If the interactive program catches interrupts, the user doesn't want
5088  * these interrupts to also abort the loop.  The approach we take here
5089  * is to have the shell ignore interrupt signals while waiting for a
5090  * foreground process to terminate, and then send itself an interrupt
5091  * signal if the child process was terminated by an interrupt signal.
5092  * Unfortunately, some programs want to do a bit of cleanup and then
5093  * exit on interrupt; unless these processes terminate themselves by
5094  * sending a signal to themselves (instead of calling exit) they will
5095  * confuse this approach.
5096  *
5097  * Called with interrupts off.
5098  */
5099 static int
5100 waitforjob(struct job *jp)
5101 {
5102         int st;
5103
5104         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5105
5106         INT_OFF;
5107         while (jp->state == JOBRUNNING) {
5108                 /* In non-interactive shells, we _can_ get
5109                  * a keyboard signal here and be EINTRed,
5110                  * but we just loop back, waiting for command to complete.
5111                  *
5112                  * man bash:
5113                  * "If bash is waiting for a command to complete and receives
5114                  * a signal for which a trap has been set, the trap
5115                  * will not be executed until the command completes."
5116                  *
5117                  * Reality is that even if trap is not set, bash
5118                  * will not act on the signal until command completes.
5119                  * Try this. sleep5intoff.c:
5120                  * #include <signal.h>
5121                  * #include <unistd.h>
5122                  * int main() {
5123                  *         sigset_t set;
5124                  *         sigemptyset(&set);
5125                  *         sigaddset(&set, SIGINT);
5126                  *         sigaddset(&set, SIGQUIT);
5127                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5128                  *         sleep(5);
5129                  *         return 0;
5130                  * }
5131                  * $ bash -c './sleep5intoff; echo hi'
5132                  * ^C^C^C^C <--- pressing ^C once a second
5133                  * $ _
5134                  * $ bash -c './sleep5intoff; echo hi'
5135                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5136                  * $ _
5137                  */
5138                 dowait(DOWAIT_BLOCK, jp);
5139         }
5140         INT_ON;
5141
5142         st = getstatus(jp);
5143 #if JOBS
5144         if (jp->jobctl) {
5145                 xtcsetpgrp(ttyfd, rootpid);
5146                 restore_tty_if_stopped_or_signaled(jp);
5147
5148                 /*
5149                  * This is truly gross.
5150                  * If we're doing job control, then we did a TIOCSPGRP which
5151                  * caused us (the shell) to no longer be in the controlling
5152                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5153                  * intuit from the subprocess exit status whether a SIGINT
5154                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5155                  */
5156                 if (jp->sigint) /* TODO: do the same with all signals */
5157                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5158         }
5159         if (jp->state == JOBDONE)
5160 #endif
5161                 freejob(jp);
5162         return st;
5163 }
5164
5165 /*
5166  * return 1 if there are stopped jobs, otherwise 0
5167  */
5168 static int
5169 stoppedjobs(void)
5170 {
5171         struct job *jp;
5172         int retval;
5173
5174         retval = 0;
5175         if (job_warning)
5176                 goto out;
5177         jp = curjob;
5178         if (jp && jp->state == JOBSTOPPED) {
5179                 out2str("You have stopped jobs.\n");
5180                 job_warning = 2;
5181                 retval++;
5182         }
5183  out:
5184         return retval;
5185 }
5186
5187
5188 /*
5189  * Code for dealing with input/output redirection.
5190  */
5191
5192 #undef EMPTY
5193 #undef CLOSED
5194 #define EMPTY -2                /* marks an unused slot in redirtab */
5195 #define CLOSED -1               /* marks a slot of previously-closed fd */
5196
5197 /*
5198  * Handle here documents.  Normally we fork off a process to write the
5199  * data to a pipe.  If the document is short, we can stuff the data in
5200  * the pipe without forking.
5201  */
5202 /* openhere needs this forward reference */
5203 static void expandhere(union node *arg, int fd);
5204 static int
5205 openhere(union node *redir)
5206 {
5207         int pip[2];
5208         size_t len = 0;
5209
5210         if (pipe(pip) < 0)
5211                 ash_msg_and_raise_error("pipe call failed");
5212         if (redir->type == NHERE) {
5213                 len = strlen(redir->nhere.doc->narg.text);
5214                 if (len <= PIPE_BUF) {
5215                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5216                         goto out;
5217                 }
5218         }
5219         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5220                 /* child */
5221                 close(pip[0]);
5222                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5223                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5224                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5225                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5226                 signal(SIGPIPE, SIG_DFL);
5227                 if (redir->type == NHERE)
5228                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5229                 else /* NXHERE */
5230                         expandhere(redir->nhere.doc, pip[1]);
5231                 _exit(EXIT_SUCCESS);
5232         }
5233  out:
5234         close(pip[1]);
5235         return pip[0];
5236 }
5237
5238 static int
5239 openredirect(union node *redir)
5240 {
5241         struct stat sb;
5242         char *fname;
5243         int f;
5244
5245         switch (redir->nfile.type) {
5246 /* Can't happen, our single caller does this itself */
5247 //      case NTOFD:
5248 //      case NFROMFD:
5249 //              return -1;
5250         case NHERE:
5251         case NXHERE:
5252                 return openhere(redir);
5253         }
5254
5255         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5256          * allocated space. Do it only when we know it is safe.
5257          */
5258         fname = redir->nfile.expfname;
5259
5260         switch (redir->nfile.type) {
5261         default:
5262 #if DEBUG
5263                 abort();
5264 #endif
5265         case NFROM:
5266                 f = open(fname, O_RDONLY);
5267                 if (f < 0)
5268                         goto eopen;
5269                 break;
5270         case NFROMTO:
5271                 f = open(fname, O_RDWR|O_CREAT, 0666);
5272                 if (f < 0)
5273                         goto ecreate;
5274                 break;
5275         case NTO:
5276 #if BASH_REDIR_OUTPUT
5277         case NTO2:
5278 #endif
5279                 /* Take care of noclobber mode. */
5280                 if (Cflag) {
5281                         if (stat(fname, &sb) < 0) {
5282                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5283                                 if (f < 0)
5284                                         goto ecreate;
5285                         } else if (!S_ISREG(sb.st_mode)) {
5286                                 f = open(fname, O_WRONLY, 0666);
5287                                 if (f < 0)
5288                                         goto ecreate;
5289                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5290                                         close(f);
5291                                         errno = EEXIST;
5292                                         goto ecreate;
5293                                 }
5294                         } else {
5295                                 errno = EEXIST;
5296                                 goto ecreate;
5297                         }
5298                         break;
5299                 }
5300                 /* FALLTHROUGH */
5301         case NCLOBBER:
5302                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5303                 if (f < 0)
5304                         goto ecreate;
5305                 break;
5306         case NAPPEND:
5307                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5308                 if (f < 0)
5309                         goto ecreate;
5310                 break;
5311         }
5312
5313         return f;
5314  ecreate:
5315         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5316  eopen:
5317         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5318 }
5319
5320 /*
5321  * Copy a file descriptor to be >= 10. Throws exception on error.
5322  */
5323 static int
5324 savefd(int from)
5325 {
5326         int newfd;
5327         int err;
5328
5329         newfd = fcntl(from, F_DUPFD, 10);
5330         err = newfd < 0 ? errno : 0;
5331         if (err != EBADF) {
5332                 if (err)
5333                         ash_msg_and_raise_perror("%d", from);
5334                 close(from);
5335                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5336         }
5337
5338         return newfd;
5339 }
5340 static int
5341 dup2_or_raise(int from, int to)
5342 {
5343         int newfd;
5344
5345         newfd = (from != to) ? dup2(from, to) : to;
5346         if (newfd < 0) {
5347                 /* Happens when source fd is not open: try "echo >&99" */
5348                 ash_msg_and_raise_perror("%d", from);
5349         }
5350         return newfd;
5351 }
5352 static int
5353 fcntl_F_DUPFD(int fd, int avoid_fd)
5354 {
5355         int newfd;
5356  repeat:
5357         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5358         if (newfd < 0) {
5359                 if (errno == EBUSY)
5360                         goto repeat;
5361                 if (errno == EINTR)
5362                         goto repeat;
5363         }
5364         return newfd;
5365 }
5366 static int
5367 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5368 {
5369         int newfd;
5370  repeat:
5371         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5372         if (newfd < 0) {
5373                 if (errno == EBUSY)
5374                         goto repeat;
5375                 if (errno == EINTR)
5376                         goto repeat;
5377                 /* fd was not open? */
5378                 if (errno == EBADF)
5379                         return fd;
5380                 ash_msg_and_raise_perror("%d", newfd);
5381         }
5382         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5383         close(fd);
5384         return newfd;
5385 }
5386
5387 /* Struct def and variable are moved down to the first usage site */
5388 struct squirrel {
5389         int orig_fd;
5390         int moved_to;
5391 };
5392 struct redirtab {
5393         struct redirtab *next;
5394         int pair_count;
5395         struct squirrel two_fd[];
5396 };
5397 #define redirlist (G_var.redirlist)
5398
5399 static void
5400 add_squirrel_closed(struct redirtab *sq, int fd)
5401 {
5402         int i;
5403
5404         if (!sq)
5405                 return;
5406
5407         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5408                 /* If we collide with an already moved fd... */
5409                 if (fd == sq->two_fd[i].orig_fd) {
5410                         /* Examples:
5411                          * "echo 3>FILE 3>&- 3>FILE"
5412                          * "echo 3>&- 3>FILE"
5413                          * No need for last redirect to insert
5414                          * another "need to close 3" indicator.
5415                          */
5416                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5417                         return;
5418                 }
5419         }
5420         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5421         sq->two_fd[i].orig_fd = fd;
5422         sq->two_fd[i].moved_to = CLOSED;
5423 }
5424
5425 static int
5426 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5427 {
5428         int i, new_fd;
5429
5430         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5431                 avoid_fd = 9;
5432
5433 #if JOBS
5434         if (fd == ttyfd) {
5435                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5436                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5437                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5438                 return 1; /* "we closed fd" */
5439         }
5440 #endif
5441         /* Are we called from redirect(0)? E.g. redirect
5442          * in a forked child. No need to save fds,
5443          * we aren't going to use them anymore, ok to trash.
5444          */
5445         if (!sq)
5446                 return 0;
5447
5448         /* If this one of script's fds? */
5449         if (fd != 0) {
5450                 struct parsefile *pf = g_parsefile;
5451                 while (pf) {
5452                         /* We skip fd == 0 case because of the following:
5453                          * $ ash  # running ash interactively
5454                          * $ . ./script.sh
5455                          * and in script.sh: "exec 9>&0".
5456                          * Even though top-level pf_fd _is_ 0,
5457                          * it's still ok to use it: "read" builtin uses it,
5458                          * why should we cripple "exec" builtin?
5459                          */
5460                         if (fd == pf->pf_fd) {
5461                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5462                                 return 1; /* "we closed fd" */
5463                         }
5464                         pf = pf->prev;
5465                 }
5466         }
5467
5468         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5469
5470         /* First: do we collide with some already moved fds? */
5471         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5472                 /* If we collide with an already moved fd... */
5473                 if (fd == sq->two_fd[i].moved_to) {
5474                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5475                         sq->two_fd[i].moved_to = new_fd;
5476                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5477                         if (new_fd < 0) /* what? */
5478                                 xfunc_die();
5479                         return 0; /* "we did not close fd" */
5480                 }
5481                 if (fd == sq->two_fd[i].orig_fd) {
5482                         /* Example: echo Hello >/dev/null 1>&2 */
5483                         TRACE(("redirect_fd %d: already moved\n", fd));
5484                         return 0; /* "we did not close fd" */
5485                 }
5486         }
5487
5488         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5489         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5490         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5491         if (new_fd < 0) {
5492                 if (errno != EBADF)
5493                         xfunc_die();
5494                 /* new_fd = CLOSED; - already is -1 */
5495         }
5496         sq->two_fd[i].moved_to = new_fd;
5497         sq->two_fd[i].orig_fd = fd;
5498
5499         /* if we move stderr, let "set -x" code know */
5500         if (fd == preverrout_fd)
5501                 preverrout_fd = new_fd;
5502
5503         return 0; /* "we did not close fd" */
5504 }
5505
5506 static int
5507 internally_opened_fd(int fd, struct redirtab *sq)
5508 {
5509         int i;
5510 #if JOBS
5511         if (fd == ttyfd)
5512                 return 1;
5513 #endif
5514         /* If this one of script's fds? */
5515         if (fd != 0) {
5516                 struct parsefile *pf = g_parsefile;
5517                 while (pf) {
5518                         if (fd == pf->pf_fd)
5519                                 return 1;
5520                         pf = pf->prev;
5521                 }
5522         }
5523
5524         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5525                 if (fd == sq->two_fd[i].moved_to)
5526                         return 1;
5527         }
5528         return 0;
5529 }
5530
5531 /*
5532  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5533  * old file descriptors are stashed away so that the redirection can be
5534  * undone by calling popredir.
5535  */
5536 /* flags passed to redirect */
5537 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5538 static void
5539 redirect(union node *redir, int flags)
5540 {
5541         struct redirtab *sv;
5542         int sv_pos;
5543
5544         if (!redir)
5545                 return;
5546
5547         sv_pos = 0;
5548         sv = NULL;
5549         INT_OFF;
5550         if (flags & REDIR_PUSH)
5551                 sv = redirlist;
5552         do {
5553                 int fd;
5554                 int newfd;
5555                 int close_fd;
5556                 int closed;
5557
5558                 fd = redir->nfile.fd;
5559                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5560                         //bb_error_msg("doing %d > %d", fd, newfd);
5561                         newfd = redir->ndup.dupfd;
5562                         close_fd = -1;
5563                 } else {
5564                         newfd = openredirect(redir); /* always >= 0 */
5565                         if (fd == newfd) {
5566                                 /* open() gave us precisely the fd we wanted.
5567                                  * This means that this fd was not busy
5568                                  * (not opened to anywhere).
5569                                  * Remember to close it on restore:
5570                                  */
5571                                 add_squirrel_closed(sv, fd);
5572                                 continue;
5573                         }
5574                         close_fd = newfd;
5575                 }
5576
5577                 if (fd == newfd)
5578                         continue;
5579
5580                 /* if "N>FILE": move newfd to fd */
5581                 /* if "N>&M": dup newfd to fd */
5582                 /* if "N>&-": close fd (newfd is -1) */
5583
5584  IF_BASH_REDIR_OUTPUT(redirect_more:)
5585
5586                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5587                 if (newfd == -1) {
5588                         /* "N>&-" means "close me" */
5589                         if (!closed) {
5590                                 /* ^^^ optimization: saving may already
5591                                  * have closed it. If not... */
5592                                 close(fd);
5593                         }
5594                 } else {
5595                         /* if newfd is a script fd or saved fd, simulate EBADF */
5596                         if (internally_opened_fd(newfd, sv)) {
5597                                 errno = EBADF;
5598                                 ash_msg_and_raise_perror("%d", newfd);
5599                         }
5600                         dup2_or_raise(newfd, fd);
5601                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5602                                 close(close_fd);
5603 #if BASH_REDIR_OUTPUT
5604                         if (redir->nfile.type == NTO2 && fd == 1) {
5605                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5606                                 fd = 2;
5607                                 newfd = 1;
5608                                 close_fd = -1;
5609                                 goto redirect_more;
5610                         }
5611 #endif
5612                 }
5613         } while ((redir = redir->nfile.next) != NULL);
5614         INT_ON;
5615
5616 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5617 #define REDIR_SAVEFD2 0
5618         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5619         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5620         // not only for calls with flags containing REDIR_SAVEFD2.
5621         // We do this unconditionally (see save_fd_on_redirect()).
5622         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5623         //      preverrout_fd = copied_fd2;
5624 }
5625
5626 static int
5627 redirectsafe(union node *redir, int flags)
5628 {
5629         int err;
5630         volatile int saveint;
5631         struct jmploc *volatile savehandler = exception_handler;
5632         struct jmploc jmploc;
5633
5634         SAVE_INT(saveint);
5635         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5636         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5637         if (!err) {
5638                 exception_handler = &jmploc;
5639                 redirect(redir, flags);
5640         }
5641         exception_handler = savehandler;
5642         if (err && exception_type != EXERROR)
5643                 longjmp(exception_handler->loc, 1);
5644         RESTORE_INT(saveint);
5645         return err;
5646 }
5647
5648 static struct redirtab*
5649 pushredir(union node *redir)
5650 {
5651         struct redirtab *sv;
5652         int i;
5653
5654         if (!redir)
5655                 return redirlist;
5656
5657         i = 0;
5658         do {
5659                 i++;
5660 #if BASH_REDIR_OUTPUT
5661                 if (redir->nfile.type == NTO2)
5662                         i++;
5663 #endif
5664                 redir = redir->nfile.next;
5665         } while (redir);
5666
5667         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5668         sv->pair_count = i;
5669         while (--i >= 0)
5670                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5671         sv->next = redirlist;
5672         redirlist = sv;
5673         return sv->next;
5674 }
5675
5676 /*
5677  * Undo the effects of the last redirection.
5678  */
5679 static void
5680 popredir(int drop)
5681 {
5682         struct redirtab *rp;
5683         int i;
5684
5685         if (redirlist == NULL)
5686                 return;
5687         INT_OFF;
5688         rp = redirlist;
5689         for (i = 0; i < rp->pair_count; i++) {
5690                 int fd = rp->two_fd[i].orig_fd;
5691                 int copy = rp->two_fd[i].moved_to;
5692                 if (copy == CLOSED) {
5693                         if (!drop)
5694                                 close(fd);
5695                         continue;
5696                 }
5697                 if (copy != EMPTY) {
5698                         if (!drop) {
5699                                 /*close(fd);*/
5700                                 dup2_or_raise(copy, fd);
5701                         }
5702                         close(copy);
5703                 }
5704         }
5705         redirlist = rp->next;
5706         free(rp);
5707         INT_ON;
5708 }
5709
5710 static void
5711 unwindredir(struct redirtab *stop)
5712 {
5713         while (redirlist != stop)
5714                 popredir(/*drop:*/ 0);
5715 }
5716
5717
5718 /* ============ Routines to expand arguments to commands
5719  *
5720  * We have to deal with backquotes, shell variables, and file metacharacters.
5721  */
5722
5723 #if ENABLE_FEATURE_SH_MATH
5724 static arith_t
5725 ash_arith(const char *s)
5726 {
5727         arith_state_t math_state;
5728         arith_t result;
5729
5730         math_state.lookupvar = lookupvar;
5731         math_state.setvar    = setvar0;
5732         //math_state.endofname = endofname;
5733
5734         INT_OFF;
5735         result = arith(&math_state, s);
5736         if (math_state.errmsg)
5737                 ash_msg_and_raise_error(math_state.errmsg);
5738         INT_ON;
5739
5740         return result;
5741 }
5742 #endif
5743
5744 /*
5745  * expandarg flags
5746  */
5747 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5748 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5749 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5750 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5751 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5752  * POSIX says for this case:
5753  *  Pathname expansion shall not be performed on the word by a
5754  *  non-interactive shell; an interactive shell may perform it, but shall
5755  *  do so only when the expansion would result in one word.
5756  * Currently, our code complies to the above rule by never globbing
5757  * redirection filenames.
5758  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5759  * (this means that on a typical Linux distro, bash almost always
5760  * performs globbing, and thus diverges from what we do).
5761  */
5762 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5763 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5764 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5765 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5766 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5767 /*
5768  * rmescape() flags
5769  */
5770 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5771 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5772 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5773 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5774 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5775
5776 /* Add CTLESC when necessary. */
5777 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5778 /* Do not skip NUL characters. */
5779 #define QUOTES_KEEPNUL EXP_TILDE
5780
5781 /*
5782  * Structure specifying which parts of the string should be searched
5783  * for IFS characters.
5784  */
5785 struct ifsregion {
5786         struct ifsregion *next; /* next region in list */
5787         int begoff;             /* offset of start of region */
5788         int endoff;             /* offset of end of region */
5789         int nulonly;            /* search for nul bytes only */
5790 };
5791
5792 struct arglist {
5793         struct strlist *list;
5794         struct strlist **lastp;
5795 };
5796
5797 /* output of current string */
5798 static char *expdest;
5799 /* list of back quote expressions */
5800 static struct nodelist *argbackq;
5801 /* first struct in list of ifs regions */
5802 static struct ifsregion ifsfirst;
5803 /* last struct in list */
5804 static struct ifsregion *ifslastp;
5805 /* holds expanded arg list */
5806 static struct arglist exparg;
5807
5808 /*
5809  * Our own itoa().
5810  * cvtnum() is used even if math support is off (to prepare $? values and such).
5811  */
5812 static int
5813 cvtnum(arith_t num)
5814 {
5815         int len;
5816
5817         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5818         len = sizeof(arith_t) * 3;
5819         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5820         if (sizeof(arith_t) < 4) len += 2;
5821
5822         expdest = makestrspace(len, expdest);
5823         len = fmtstr(expdest, len, ARITH_FMT, num);
5824         STADJUST(len, expdest);
5825         return len;
5826 }
5827
5828 /*
5829  * Break the argument string into pieces based upon IFS and add the
5830  * strings to the argument list.  The regions of the string to be
5831  * searched for IFS characters have been stored by recordregion.
5832  */
5833 static void
5834 ifsbreakup(char *string, struct arglist *arglist)
5835 {
5836         struct ifsregion *ifsp;
5837         struct strlist *sp;
5838         char *start;
5839         char *p;
5840         char *q;
5841         const char *ifs, *realifs;
5842         int ifsspc;
5843         int nulonly;
5844
5845         start = string;
5846         if (ifslastp != NULL) {
5847                 ifsspc = 0;
5848                 nulonly = 0;
5849                 realifs = ifsset() ? ifsval() : defifs;
5850                 ifsp = &ifsfirst;
5851                 do {
5852                         p = string + ifsp->begoff;
5853                         nulonly = ifsp->nulonly;
5854                         ifs = nulonly ? nullstr : realifs;
5855                         ifsspc = 0;
5856                         while (p < string + ifsp->endoff) {
5857                                 q = p;
5858                                 if ((unsigned char)*p == CTLESC)
5859                                         p++;
5860                                 if (!strchr(ifs, *p)) {
5861                                         p++;
5862                                         continue;
5863                                 }
5864                                 if (!nulonly)
5865                                         ifsspc = (strchr(defifs, *p) != NULL);
5866                                 /* Ignore IFS whitespace at start */
5867                                 if (q == start && ifsspc) {
5868                                         p++;
5869                                         start = p;
5870                                         continue;
5871                                 }
5872                                 *q = '\0';
5873                                 sp = stzalloc(sizeof(*sp));
5874                                 sp->text = start;
5875                                 *arglist->lastp = sp;
5876                                 arglist->lastp = &sp->next;
5877                                 p++;
5878                                 if (!nulonly) {
5879                                         for (;;) {
5880                                                 if (p >= string + ifsp->endoff) {
5881                                                         break;
5882                                                 }
5883                                                 q = p;
5884                                                 if ((unsigned char)*p == CTLESC)
5885                                                         p++;
5886                                                 if (strchr(ifs, *p) == NULL) {
5887                                                         p = q;
5888                                                         break;
5889                                                 }
5890                                                 if (strchr(defifs, *p) == NULL) {
5891                                                         if (ifsspc) {
5892                                                                 p++;
5893                                                                 ifsspc = 0;
5894                                                         } else {
5895                                                                 p = q;
5896                                                                 break;
5897                                                         }
5898                                                 } else
5899                                                         p++;
5900                                         }
5901                                 }
5902                                 start = p;
5903                         } /* while */
5904                         ifsp = ifsp->next;
5905                 } while (ifsp != NULL);
5906                 if (nulonly)
5907                         goto add;
5908         }
5909
5910         if (!*start)
5911                 return;
5912
5913  add:
5914         sp = stzalloc(sizeof(*sp));
5915         sp->text = start;
5916         *arglist->lastp = sp;
5917         arglist->lastp = &sp->next;
5918 }
5919
5920 static void
5921 ifsfree(void)
5922 {
5923         struct ifsregion *p = ifsfirst.next;
5924
5925         if (!p)
5926                 goto out;
5927
5928         INT_OFF;
5929         do {
5930                 struct ifsregion *ifsp;
5931                 ifsp = p->next;
5932                 free(p);
5933                 p = ifsp;
5934         } while (p);
5935         ifsfirst.next = NULL;
5936         INT_ON;
5937  out:
5938         ifslastp = NULL;
5939 }
5940
5941 static size_t
5942 esclen(const char *start, const char *p)
5943 {
5944         size_t esc = 0;
5945
5946         while (p > start && (unsigned char)*--p == CTLESC) {
5947                 esc++;
5948         }
5949         return esc;
5950 }
5951
5952 /*
5953  * Remove any CTLESC characters from a string.
5954  */
5955 static char *
5956 rmescapes(char *str, int flag)
5957 {
5958         static const char qchars[] ALIGN1 = {
5959                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5960
5961         char *p, *q, *r;
5962         unsigned inquotes;
5963         unsigned protect_against_glob;
5964         unsigned globbing;
5965         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5966
5967         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5968         if (!p)
5969                 return str;
5970
5971         q = p;
5972         r = str;
5973         if (flag & RMESCAPE_ALLOC) {
5974                 size_t len = p - str;
5975                 size_t fulllen = len + strlen(p) + 1;
5976
5977                 if (flag & RMESCAPE_GROW) {
5978                         int strloc = str - (char *)stackblock();
5979                         r = makestrspace(fulllen, expdest);
5980                         /* p and str may be invalidated by makestrspace */
5981                         str = (char *)stackblock() + strloc;
5982                         p = str + len;
5983                 } else if (flag & RMESCAPE_HEAP) {
5984                         r = ckmalloc(fulllen);
5985                 } else {
5986                         r = stalloc(fulllen);
5987                 }
5988                 q = r;
5989                 if (len > 0) {
5990                         q = (char *)mempcpy(q, str, len);
5991                 }
5992         }
5993
5994         inquotes = 0;
5995         globbing = flag & RMESCAPE_GLOB;
5996         protect_against_glob = globbing;
5997         while (*p) {
5998                 if ((unsigned char)*p == CTLQUOTEMARK) {
5999 // Note: both inquotes and protect_against_glob only affect whether
6000 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6001                         inquotes = ~inquotes;
6002                         p++;
6003                         protect_against_glob = globbing;
6004                         continue;
6005                 }
6006                 if ((unsigned char)*p == CTLESC) {
6007                         p++;
6008 #if DEBUG
6009                         if (*p == '\0')
6010                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6011 #endif
6012                         if (protect_against_glob) {
6013                                 /*
6014                                  * We used to trust glob() and fnmatch() to eat
6015                                  * superfluous escapes (\z where z has no
6016                                  * special meaning anyway). But this causes
6017                                  * bugs such as string of one greek letter rho
6018                                  * (unicode-encoded as two bytes "cf,81")
6019                                  * getting encoded as "cf,CTLESC,81"
6020                                  * and here, converted to "cf,\,81" -
6021                                  * which does not go well with some flavors
6022                                  * of fnmatch() in unicode locales
6023                                  * (for example, glibc <= 2.22).
6024                                  *
6025                                  * Lets add "\" only on the chars which need it.
6026                                  * Testcases for less obvious chars are shown.
6027                                  */
6028                                 if (*p == '*'
6029                                  || *p == '?'
6030                                  || *p == '['
6031                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6032                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6033                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6034                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6035                                 /* Some libc support [^negate], that's why "^" also needs love */
6036                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6037                                 ) {
6038                                         *q++ = '\\';
6039                                 }
6040                         }
6041                 } else if (*p == '\\' && !inquotes) {
6042                         /* naked back slash */
6043                         protect_against_glob = 0;
6044                         goto copy;
6045                 }
6046 #if BASH_PATTERN_SUBST
6047                 else if (*p == '/' && slash) {
6048                         /* stop handling globbing and mark location of slash */
6049                         globbing = slash = 0;
6050                         *p = CTLESC;
6051                 }
6052 #endif
6053                 protect_against_glob = globbing;
6054  copy:
6055                 *q++ = *p++;
6056         }
6057         *q = '\0';
6058         if (flag & RMESCAPE_GROW) {
6059                 expdest = r;
6060                 STADJUST(q - r + 1, expdest);
6061         }
6062         return r;
6063 }
6064 #define pmatch(a, b) !fnmatch((a), (b), 0)
6065
6066 /*
6067  * Prepare a pattern for a expmeta (internal glob(3)) call.
6068  *
6069  * Returns an stalloced string.
6070  */
6071 static char *
6072 preglob(const char *pattern, int flag)
6073 {
6074         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6075 }
6076
6077 /*
6078  * Put a string on the stack.
6079  */
6080 static void
6081 memtodest(const char *p, size_t len, int syntax, int quotes)
6082 {
6083         char *q;
6084
6085         if (!len)
6086                 return;
6087
6088         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6089
6090         do {
6091                 unsigned char c = *p++;
6092                 if (c) {
6093                         if (quotes & QUOTES_ESC) {
6094                                 int n = SIT(c, syntax);
6095                                 if (n == CCTL
6096                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6097                                      && n == CBACK
6098                                     )
6099                                 ) {
6100                                         USTPUTC(CTLESC, q);
6101                                 }
6102                         }
6103                 } else if (!(quotes & QUOTES_KEEPNUL))
6104                         continue;
6105                 USTPUTC(c, q);
6106         } while (--len);
6107
6108         expdest = q;
6109 }
6110
6111 static size_t
6112 strtodest(const char *p, int syntax, int quotes)
6113 {
6114         size_t len = strlen(p);
6115         memtodest(p, len, syntax, quotes);
6116         return len;
6117 }
6118
6119 /*
6120  * Record the fact that we have to scan this region of the
6121  * string for IFS characters.
6122  */
6123 static void
6124 recordregion(int start, int end, int nulonly)
6125 {
6126         struct ifsregion *ifsp;
6127
6128         if (ifslastp == NULL) {
6129                 ifsp = &ifsfirst;
6130         } else {
6131                 INT_OFF;
6132                 ifsp = ckzalloc(sizeof(*ifsp));
6133                 /*ifsp->next = NULL; - ckzalloc did it */
6134                 ifslastp->next = ifsp;
6135                 INT_ON;
6136         }
6137         ifslastp = ifsp;
6138         ifslastp->begoff = start;
6139         ifslastp->endoff = end;
6140         ifslastp->nulonly = nulonly;
6141 }
6142
6143 static void
6144 removerecordregions(int endoff)
6145 {
6146         if (ifslastp == NULL)
6147                 return;
6148
6149         if (ifsfirst.endoff > endoff) {
6150                 while (ifsfirst.next) {
6151                         struct ifsregion *ifsp;
6152                         INT_OFF;
6153                         ifsp = ifsfirst.next->next;
6154                         free(ifsfirst.next);
6155                         ifsfirst.next = ifsp;
6156                         INT_ON;
6157                 }
6158                 if (ifsfirst.begoff > endoff) {
6159                         ifslastp = NULL;
6160                 } else {
6161                         ifslastp = &ifsfirst;
6162                         ifsfirst.endoff = endoff;
6163                 }
6164                 return;
6165         }
6166
6167         ifslastp = &ifsfirst;
6168         while (ifslastp->next && ifslastp->next->begoff < endoff)
6169                 ifslastp = ifslastp->next;
6170         while (ifslastp->next) {
6171                 struct ifsregion *ifsp;
6172                 INT_OFF;
6173                 ifsp = ifslastp->next->next;
6174                 free(ifslastp->next);
6175                 ifslastp->next = ifsp;
6176                 INT_ON;
6177         }
6178         if (ifslastp->endoff > endoff)
6179                 ifslastp->endoff = endoff;
6180 }
6181
6182 static char *
6183 exptilde(char *startp, char *p, int flags)
6184 {
6185         unsigned char c;
6186         char *name;
6187         struct passwd *pw;
6188         const char *home;
6189         int quotes = flags & QUOTES_ESC;
6190
6191         name = p + 1;
6192
6193         while ((c = *++p) != '\0') {
6194                 switch (c) {
6195                 case CTLESC:
6196                         return startp;
6197                 case CTLQUOTEMARK:
6198                         return startp;
6199                 case ':':
6200                         if (flags & EXP_VARTILDE)
6201                                 goto done;
6202                         break;
6203                 case '/':
6204                 case CTLENDVAR:
6205                         goto done;
6206                 }
6207         }
6208  done:
6209         *p = '\0';
6210         if (*name == '\0') {
6211                 home = lookupvar("HOME");
6212         } else {
6213                 pw = getpwnam(name);
6214                 if (pw == NULL)
6215                         goto lose;
6216                 home = pw->pw_dir;
6217         }
6218         if (!home || !*home)
6219                 goto lose;
6220         *p = c;
6221         strtodest(home, SQSYNTAX, quotes);
6222         return p;
6223  lose:
6224         *p = c;
6225         return startp;
6226 }
6227
6228 /*
6229  * Execute a command inside back quotes.  If it's a builtin command, we
6230  * want to save its output in a block obtained from malloc.  Otherwise
6231  * we fork off a subprocess and get the output of the command via a pipe.
6232  * Should be called with interrupts off.
6233  */
6234 struct backcmd {                /* result of evalbackcmd */
6235         int fd;                 /* file descriptor to read from */
6236         int nleft;              /* number of chars in buffer */
6237         char *buf;              /* buffer */
6238         struct job *jp;         /* job structure for command */
6239 };
6240
6241 /* These forward decls are needed to use "eval" code for backticks handling: */
6242 /* flags in argument to evaltree */
6243 #define EV_EXIT    01           /* exit after evaluating tree */
6244 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6245 static int evaltree(union node *, int);
6246
6247 /* An evaltree() which is known to never return.
6248  * Used to use an alias:
6249  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6250  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6251  */
6252 static ALWAYS_INLINE NORETURN void
6253 evaltreenr(union node *n, int flags)
6254 {
6255         evaltree(n, flags);
6256         bb_unreachable(abort());
6257         /* NOTREACHED */
6258 }
6259
6260 static void FAST_FUNC
6261 evalbackcmd(union node *n, struct backcmd *result)
6262 {
6263         int pip[2];
6264         struct job *jp;
6265
6266         result->fd = -1;
6267         result->buf = NULL;
6268         result->nleft = 0;
6269         result->jp = NULL;
6270         if (n == NULL) {
6271                 goto out;
6272         }
6273
6274         if (pipe(pip) < 0)
6275                 ash_msg_and_raise_error("pipe call failed");
6276         jp = makejob(/*n,*/ 1);
6277         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6278                 /* child */
6279                 FORCE_INT_ON;
6280                 close(pip[0]);
6281                 if (pip[1] != 1) {
6282                         /*close(1);*/
6283                         dup2_or_raise(pip[1], 1);
6284                         close(pip[1]);
6285                 }
6286 /* TODO: eflag clearing makes the following not abort:
6287  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6288  * which is what bash does (unless it is in POSIX mode).
6289  * dash deleted "eflag = 0" line in the commit
6290  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6291  *  [EVAL] Don't clear eflag in evalbackcmd
6292  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6293  */
6294                 eflag = 0;
6295                 ifsfree();
6296                 evaltreenr(n, EV_EXIT);
6297                 /* NOTREACHED */
6298         }
6299         /* parent */
6300         close(pip[1]);
6301         result->fd = pip[0];
6302         result->jp = jp;
6303
6304  out:
6305         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6306                 result->fd, result->buf, result->nleft, result->jp));
6307 }
6308
6309 /*
6310  * Expand stuff in backwards quotes.
6311  */
6312 static void
6313 expbackq(union node *cmd, int flag)
6314 {
6315         struct backcmd in;
6316         int i;
6317         char buf[128];
6318         char *p;
6319         char *dest;
6320         int startloc;
6321         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6322         struct stackmark smark;
6323
6324         INT_OFF;
6325         startloc = expdest - (char *)stackblock();
6326         pushstackmark(&smark, startloc);
6327         evalbackcmd(cmd, &in);
6328         popstackmark(&smark);
6329
6330         p = in.buf;
6331         i = in.nleft;
6332         if (i == 0)
6333                 goto read;
6334         for (;;) {
6335                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6336  read:
6337                 if (in.fd < 0)
6338                         break;
6339                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6340                 TRACE(("expbackq: read returns %d\n", i));
6341                 if (i <= 0)
6342                         break;
6343                 p = buf;
6344         }
6345
6346         free(in.buf);
6347         if (in.fd >= 0) {
6348                 close(in.fd);
6349                 back_exitstatus = waitforjob(in.jp);
6350         }
6351         INT_ON;
6352
6353         /* Eat all trailing newlines */
6354         dest = expdest;
6355         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6356                 STUNPUTC(dest);
6357         expdest = dest;
6358
6359         if (!(flag & EXP_QUOTED))
6360                 recordregion(startloc, dest - (char *)stackblock(), 0);
6361         TRACE(("evalbackq: size:%d:'%.*s'\n",
6362                 (int)((dest - (char *)stackblock()) - startloc),
6363                 (int)((dest - (char *)stackblock()) - startloc),
6364                 stackblock() + startloc));
6365 }
6366
6367 #if ENABLE_FEATURE_SH_MATH
6368 /*
6369  * Expand arithmetic expression.  Backup to start of expression,
6370  * evaluate, place result in (backed up) result, adjust string position.
6371  */
6372 static void
6373 expari(int flag)
6374 {
6375         char *p, *start;
6376         int begoff;
6377         int len;
6378
6379         /* ifsfree(); */
6380
6381         /*
6382          * This routine is slightly over-complicated for
6383          * efficiency.  Next we scan backwards looking for the
6384          * start of arithmetic.
6385          */
6386         start = stackblock();
6387         p = expdest - 1;
6388         *p = '\0';
6389         p--;
6390         while (1) {
6391                 int esc;
6392
6393                 while ((unsigned char)*p != CTLARI) {
6394                         p--;
6395 #if DEBUG
6396                         if (p < start) {
6397                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6398                         }
6399 #endif
6400                 }
6401
6402                 esc = esclen(start, p);
6403                 if (!(esc % 2)) {
6404                         break;
6405                 }
6406
6407                 p -= esc + 1;
6408         }
6409
6410         begoff = p - start;
6411
6412         removerecordregions(begoff);
6413
6414         expdest = p;
6415
6416         if (flag & QUOTES_ESC)
6417                 rmescapes(p + 1, 0);
6418
6419         len = cvtnum(ash_arith(p + 1));
6420
6421         if (!(flag & EXP_QUOTED))
6422                 recordregion(begoff, begoff + len, 0);
6423 }
6424 #endif
6425
6426 /* argstr needs it */
6427 static char *evalvar(char *p, int flags);
6428
6429 /*
6430  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6431  * characters to allow for further processing.  Otherwise treat
6432  * $@ like $* since no splitting will be performed.
6433  */
6434 static void
6435 argstr(char *p, int flags)
6436 {
6437         static const char spclchars[] ALIGN1 = {
6438                 '=',
6439                 ':',
6440                 CTLQUOTEMARK,
6441                 CTLENDVAR,
6442                 CTLESC,
6443                 CTLVAR,
6444                 CTLBACKQ,
6445 #if ENABLE_FEATURE_SH_MATH
6446                 CTLENDARI,
6447 #endif
6448                 '\0'
6449         };
6450         const char *reject = spclchars;
6451         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6452         int inquotes;
6453         size_t length;
6454         int startloc;
6455
6456         if (!(flags & EXP_VARTILDE)) {
6457                 reject += 2;
6458         } else if (flags & EXP_VARTILDE2) {
6459                 reject++;
6460         }
6461         inquotes = 0;
6462         length = 0;
6463         if (flags & EXP_TILDE) {
6464                 char *q;
6465
6466                 flags &= ~EXP_TILDE;
6467  tilde:
6468                 q = p;
6469                 if (*q == '~')
6470                         p = exptilde(p, q, flags);
6471         }
6472  start:
6473         startloc = expdest - (char *)stackblock();
6474         for (;;) {
6475                 unsigned char c;
6476
6477                 length += strcspn(p + length, reject);
6478                 c = p[length];
6479                 if (c) {
6480                         if (!(c & 0x80)
6481                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6482                         ) {
6483                                 /* c == '=' || c == ':' || c == CTLENDARI */
6484                                 length++;
6485                         }
6486                 }
6487                 if (length > 0) {
6488                         int newloc;
6489                         expdest = stack_nputstr(p, length, expdest);
6490                         newloc = expdest - (char *)stackblock();
6491                         if (breakall && !inquotes && newloc > startloc) {
6492                                 recordregion(startloc, newloc, 0);
6493                         }
6494                         startloc = newloc;
6495                 }
6496                 p += length + 1;
6497                 length = 0;
6498
6499                 switch (c) {
6500                 case '\0':
6501                         goto breakloop;
6502                 case '=':
6503                         if (flags & EXP_VARTILDE2) {
6504                                 p--;
6505                                 continue;
6506                         }
6507                         flags |= EXP_VARTILDE2;
6508                         reject++;
6509                         /* fall through */
6510                 case ':':
6511                         /*
6512                          * sort of a hack - expand tildes in variable
6513                          * assignments (after the first '=' and after ':'s).
6514                          */
6515                         if (*--p == '~') {
6516                                 goto tilde;
6517                         }
6518                         continue;
6519                 }
6520
6521                 switch (c) {
6522                 case CTLENDVAR: /* ??? */
6523                         goto breakloop;
6524                 case CTLQUOTEMARK:
6525                         inquotes ^= EXP_QUOTED;
6526                         /* "$@" syntax adherence hack */
6527                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6528                                 p = evalvar(p + 1, flags | inquotes) + 1;
6529                                 goto start;
6530                         }
6531  addquote:
6532                         if (flags & QUOTES_ESC) {
6533                                 p--;
6534                                 length++;
6535                                 startloc++;
6536                         }
6537                         break;
6538                 case CTLESC:
6539                         startloc++;
6540                         length++;
6541
6542                         /*
6543                          * Quoted parameter expansion pattern: remove quote
6544                          * unless inside inner quotes or we have a literal
6545                          * backslash.
6546                          */
6547                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6548                             EXP_QPAT && *p != '\\')
6549                                 break;
6550
6551                         goto addquote;
6552                 case CTLVAR:
6553                         TRACE(("argstr: evalvar('%s')\n", p));
6554                         p = evalvar(p, flags | inquotes);
6555                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6556                         goto start;
6557                 case CTLBACKQ:
6558                         expbackq(argbackq->n, flags | inquotes);
6559                         argbackq = argbackq->next;
6560                         goto start;
6561 #if ENABLE_FEATURE_SH_MATH
6562                 case CTLENDARI:
6563                         p--;
6564                         expari(flags | inquotes);
6565                         goto start;
6566 #endif
6567                 }
6568         }
6569  breakloop: ;
6570 }
6571
6572 static char *
6573 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6574                 char *pattern, int quotes, int zero)
6575 {
6576         char *loc, *loc2;
6577         char c;
6578
6579         loc = startp;
6580         loc2 = rmesc;
6581         do {
6582                 int match;
6583                 const char *s = loc2;
6584
6585                 c = *loc2;
6586                 if (zero) {
6587                         *loc2 = '\0';
6588                         s = rmesc;
6589                 }
6590                 match = pmatch(pattern, s);
6591
6592                 *loc2 = c;
6593                 if (match)
6594                         return loc;
6595                 if (quotes && (unsigned char)*loc == CTLESC)
6596                         loc++;
6597                 loc++;
6598                 loc2++;
6599         } while (c);
6600         return NULL;
6601 }
6602
6603 static char *
6604 scanright(char *startp, char *rmesc, char *rmescend,
6605                 char *pattern, int quotes, int match_at_start)
6606 {
6607 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6608         int try2optimize = match_at_start;
6609 #endif
6610         int esc = 0;
6611         char *loc;
6612         char *loc2;
6613
6614         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6615          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6616          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6617          * Logic:
6618          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6619          * and on each iteration they go back two/one char until they reach the beginning.
6620          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6621          */
6622         /* TODO: document in what other circumstances we are called. */
6623
6624         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6625                 int match;
6626                 char c = *loc2;
6627                 const char *s = loc2;
6628                 if (match_at_start) {
6629                         *loc2 = '\0';
6630                         s = rmesc;
6631                 }
6632                 match = pmatch(pattern, s);
6633                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6634                 *loc2 = c;
6635                 if (match)
6636                         return loc;
6637 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6638                 if (try2optimize) {
6639                         /* Maybe we can optimize this:
6640                          * if pattern ends with unescaped *, we can avoid checking
6641                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6642                          * it won't match truncated "raw_value_of_" strings too.
6643                          */
6644                         unsigned plen = strlen(pattern);
6645                         /* Does it end with "*"? */
6646                         if (plen != 0 && pattern[--plen] == '*') {
6647                                 /* "xxxx*" is not escaped */
6648                                 /* "xxx\*" is escaped */
6649                                 /* "xx\\*" is not escaped */
6650                                 /* "x\\\*" is escaped */
6651                                 int slashes = 0;
6652                                 while (plen != 0 && pattern[--plen] == '\\')
6653                                         slashes++;
6654                                 if (!(slashes & 1))
6655                                         break; /* ends with unescaped "*" */
6656                         }
6657                         try2optimize = 0;
6658                 }
6659 #endif
6660                 loc--;
6661                 if (quotes) {
6662                         if (--esc < 0) {
6663                                 esc = esclen(startp, loc);
6664                         }
6665                         if (esc % 2) {
6666                                 esc--;
6667                                 loc--;
6668                         }
6669                 }
6670         }
6671         return NULL;
6672 }
6673
6674 static void varunset(const char *, const char *, const char *, int) NORETURN;
6675 static void
6676 varunset(const char *end, const char *var, const char *umsg, int varflags)
6677 {
6678         const char *msg;
6679         const char *tail;
6680
6681         tail = nullstr;
6682         msg = "parameter not set";
6683         if (umsg) {
6684                 if ((unsigned char)*end == CTLENDVAR) {
6685                         if (varflags & VSNUL)
6686                                 tail = " or null";
6687                 } else {
6688                         msg = umsg;
6689                 }
6690         }
6691         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6692 }
6693
6694 static const char *
6695 subevalvar(char *p, char *varname, int strloc, int subtype,
6696                 int startloc, int varflags, int flag)
6697 {
6698         struct nodelist *saveargbackq = argbackq;
6699         int quotes = flag & QUOTES_ESC;
6700         char *startp;
6701         char *loc;
6702         char *rmesc, *rmescend;
6703         char *str;
6704         int amount, resetloc;
6705         IF_BASH_PATTERN_SUBST(int workloc;)
6706         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6707         int zero;
6708         char *(*scan)(char*, char*, char*, char*, int, int);
6709
6710         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6711         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6712
6713         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6714                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6715         );
6716         STPUTC('\0', expdest);
6717         argbackq = saveargbackq;
6718         startp = (char *)stackblock() + startloc;
6719
6720         switch (subtype) {
6721         case VSASSIGN:
6722                 setvar0(varname, startp);
6723                 amount = startp - expdest;
6724                 STADJUST(amount, expdest);
6725                 return startp;
6726
6727         case VSQUESTION:
6728                 varunset(p, varname, startp, varflags);
6729                 /* NOTREACHED */
6730
6731 #if BASH_SUBSTR
6732         case VSSUBSTR: {
6733                 int pos, len, orig_len;
6734                 char *colon;
6735
6736                 loc = str = stackblock() + strloc;
6737
6738 # if !ENABLE_FEATURE_SH_MATH
6739 #  define ash_arith number
6740 # endif
6741                 /* Read POS in ${var:POS:LEN} */
6742                 colon = strchr(loc, ':');
6743                 if (colon) *colon = '\0';
6744                 pos = ash_arith(loc);
6745                 if (colon) *colon = ':';
6746
6747                 /* Read LEN in ${var:POS:LEN} */
6748                 len = str - startp - 1;
6749                 /* *loc != '\0', guaranteed by parser */
6750                 if (quotes) {
6751                         char *ptr;
6752
6753                         /* Adjust the length by the number of escapes */
6754                         for (ptr = startp; ptr < (str - 1); ptr++) {
6755                                 if ((unsigned char)*ptr == CTLESC) {
6756                                         len--;
6757                                         ptr++;
6758                                 }
6759                         }
6760                 }
6761                 orig_len = len;
6762                 if (*loc++ == ':') {
6763                         /* ${var::LEN} */
6764                         len = ash_arith(loc);
6765                 } else {
6766                         /* Skip POS in ${var:POS:LEN} */
6767                         len = orig_len;
6768                         while (*loc && *loc != ':') {
6769                                 loc++;
6770                         }
6771                         if (*loc++ == ':') {
6772                                 len = ash_arith(loc);
6773                         }
6774                 }
6775 #  undef ash_arith
6776
6777                 if (pos < 0) {
6778                         /* ${VAR:$((-n)):l} starts n chars from the end */
6779                         pos = orig_len + pos;
6780                 }
6781                 if ((unsigned)pos >= orig_len) {
6782                         /* apart from obvious ${VAR:999999:l},
6783                          * covers ${VAR:$((-9999999)):l} - result is ""
6784                          * (bash compat)
6785                          */
6786                         pos = 0;
6787                         len = 0;
6788                 }
6789                 if (len < 0) {
6790                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6791                         len = (orig_len - pos) + len;
6792                 }
6793                 if ((unsigned)len > (orig_len - pos))
6794                         len = orig_len - pos;
6795
6796                 for (str = startp; pos; str++, pos--) {
6797                         if (quotes && (unsigned char)*str == CTLESC)
6798                                 str++;
6799                 }
6800                 for (loc = startp; len; len--) {
6801                         if (quotes && (unsigned char)*str == CTLESC)
6802                                 *loc++ = *str++;
6803                         *loc++ = *str++;
6804                 }
6805                 *loc = '\0';
6806                 amount = loc - expdest;
6807                 STADJUST(amount, expdest);
6808                 return loc;
6809         }
6810 #endif /* BASH_SUBSTR */
6811         }
6812
6813         resetloc = expdest - (char *)stackblock();
6814
6815 #if BASH_PATTERN_SUBST
6816         /* We'll comeback here if we grow the stack while handling
6817          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6818          * stack will need rebasing, and we'll need to remove our work
6819          * areas each time
6820          */
6821  restart:
6822 #endif
6823
6824         amount = expdest - ((char *)stackblock() + resetloc);
6825         STADJUST(-amount, expdest);
6826         startp = (char *)stackblock() + startloc;
6827
6828         rmesc = startp;
6829         rmescend = (char *)stackblock() + strloc;
6830         if (quotes) {
6831                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6832                 if (rmesc != startp) {
6833                         rmescend = expdest;
6834                         startp = (char *)stackblock() + startloc;
6835                 }
6836         }
6837         rmescend--;
6838         str = (char *)stackblock() + strloc;
6839         /*
6840          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6841          * The result is a_\_z_c (not a\_\_z_c)!
6842          *
6843          * The search pattern and replace string treat backslashes differently!
6844          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6845          * and string.  It's only used on the first call.
6846          */
6847         preglob(str, IF_BASH_PATTERN_SUBST(
6848                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6849                         RMESCAPE_SLASH : ) 0);
6850
6851 #if BASH_PATTERN_SUBST
6852         workloc = expdest - (char *)stackblock();
6853         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6854                 int len;
6855                 char *idx, *end;
6856
6857                 if (!repl) {
6858                         repl = strchr(str, CTLESC);
6859                         if (repl)
6860                                 *repl++ = '\0';
6861                         else
6862                                 repl = nullstr;
6863                 }
6864                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6865
6866                 /* If there's no pattern to match, return the expansion unmolested */
6867                 if (str[0] == '\0')
6868                         return NULL;
6869
6870                 len = 0;
6871                 idx = startp;
6872                 end = str - 1;
6873                 while (idx < end) {
6874  try_to_match:
6875                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6876                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6877                         if (!loc) {
6878                                 /* No match, advance */
6879                                 char *restart_detect = stackblock();
6880  skip_matching:
6881                                 STPUTC(*idx, expdest);
6882                                 if (quotes && (unsigned char)*idx == CTLESC) {
6883                                         idx++;
6884                                         len++;
6885                                         STPUTC(*idx, expdest);
6886                                 }
6887                                 if (stackblock() != restart_detect)
6888                                         goto restart;
6889                                 idx++;
6890                                 len++;
6891                                 rmesc++;
6892                                 /* continue; - prone to quadratic behavior, smarter code: */
6893                                 if (idx >= end)
6894                                         break;
6895                                 if (str[0] == '*') {
6896                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6897                                          * it would never match "ong_string" etc, no point in trying.
6898                                          */
6899                                         goto skip_matching;
6900                                 }
6901                                 goto try_to_match;
6902                         }
6903
6904                         if (subtype == VSREPLACEALL) {
6905                                 while (idx < loc) {
6906                                         if (quotes && (unsigned char)*idx == CTLESC)
6907                                                 idx++;
6908                                         idx++;
6909                                         rmesc++;
6910                                 }
6911                         } else {
6912                                 idx = loc;
6913                         }
6914
6915                         //bb_error_msg("repl:'%s'", repl);
6916                         for (loc = (char*)repl; *loc; loc++) {
6917                                 char *restart_detect = stackblock();
6918                                 if (quotes && *loc == '\\') {
6919                                         STPUTC(CTLESC, expdest);
6920                                         len++;
6921                                 }
6922                                 STPUTC(*loc, expdest);
6923                                 if (stackblock() != restart_detect)
6924                                         goto restart;
6925                                 len++;
6926                         }
6927
6928                         if (subtype == VSREPLACE) {
6929                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6930                                 while (*idx) {
6931                                         char *restart_detect = stackblock();
6932                                         STPUTC(*idx, expdest);
6933                                         if (stackblock() != restart_detect)
6934                                                 goto restart;
6935                                         len++;
6936                                         idx++;
6937                                 }
6938                                 break;
6939                         }
6940                 }
6941
6942                 /* We've put the replaced text into a buffer at workloc, now
6943                  * move it to the right place and adjust the stack.
6944                  */
6945                 STPUTC('\0', expdest);
6946                 startp = (char *)stackblock() + startloc;
6947                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6948                 //bb_error_msg("startp:'%s'", startp);
6949                 amount = expdest - (startp + len);
6950                 STADJUST(-amount, expdest);
6951                 return startp;
6952         }
6953 #endif /* BASH_PATTERN_SUBST */
6954
6955         subtype -= VSTRIMRIGHT;
6956 #if DEBUG
6957         if (subtype < 0 || subtype > 7)
6958                 abort();
6959 #endif
6960         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6961         zero = subtype >> 1;
6962         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6963         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6964
6965         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6966         if (loc) {
6967                 if (zero) {
6968                         memmove(startp, loc, str - loc);
6969                         loc = startp + (str - loc) - 1;
6970                 }
6971                 *loc = '\0';
6972                 amount = loc - expdest;
6973                 STADJUST(amount, expdest);
6974         }
6975         return loc;
6976 }
6977
6978 /*
6979  * Add the value of a specialized variable to the stack string.
6980  * name parameter (examples):
6981  * ash -c 'echo $1'      name:'1='
6982  * ash -c 'echo $qwe'    name:'qwe='
6983  * ash -c 'echo $$'      name:'$='
6984  * ash -c 'echo ${$}'    name:'$='
6985  * ash -c 'echo ${$##q}' name:'$=q'
6986  * ash -c 'echo ${#$}'   name:'$='
6987  * note: examples with bad shell syntax:
6988  * ash -c 'echo ${#$1}'  name:'$=1'
6989  * ash -c 'echo ${#1#}'  name:'1=#'
6990  */
6991 static NOINLINE ssize_t
6992 varvalue(char *name, int varflags, int flags, int *quotedp)
6993 {
6994         const char *p;
6995         int num;
6996         int i;
6997         ssize_t len = 0;
6998         int sep;
6999         int quoted = *quotedp;
7000         int subtype = varflags & VSTYPE;
7001         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7002         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7003         int syntax;
7004
7005         sep = (flags & EXP_FULL) << CHAR_BIT;
7006         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7007
7008         switch (*name) {
7009         case '$':
7010                 num = rootpid;
7011                 goto numvar;
7012         case '?':
7013                 num = exitstatus;
7014                 goto numvar;
7015         case '#':
7016                 num = shellparam.nparam;
7017                 goto numvar;
7018         case '!':
7019                 num = backgndpid;
7020                 if (num == 0)
7021                         return -1;
7022  numvar:
7023                 len = cvtnum(num);
7024                 goto check_1char_name;
7025         case '-':
7026                 expdest = makestrspace(NOPTS, expdest);
7027                 for (i = NOPTS - 1; i >= 0; i--) {
7028                         if (optlist[i]) {
7029                                 USTPUTC(optletters(i), expdest);
7030                                 len++;
7031                         }
7032                 }
7033  check_1char_name:
7034 #if 0
7035                 /* handles cases similar to ${#$1} */
7036                 if (name[2] != '\0')
7037                         raise_error_syntax("bad substitution");
7038 #endif
7039                 break;
7040         case '@':
7041                 if (quoted && sep)
7042                         goto param;
7043                 /* fall through */
7044         case '*': {
7045                 char **ap;
7046                 char sepc;
7047
7048                 if (quoted)
7049                         sep = 0;
7050                 sep |= ifsset() ? ifsval()[0] : ' ';
7051  param:
7052                 sepc = sep;
7053                 *quotedp = !sepc;
7054                 ap = shellparam.p;
7055                 if (!ap)
7056                         return -1;
7057                 while ((p = *ap++) != NULL) {
7058                         len += strtodest(p, syntax, quotes);
7059
7060                         if (*ap && sep) {
7061                                 len++;
7062                                 memtodest(&sepc, 1, syntax, quotes);
7063                         }
7064                 }
7065                 break;
7066         } /* case '*' */
7067         case '0':
7068         case '1':
7069         case '2':
7070         case '3':
7071         case '4':
7072         case '5':
7073         case '6':
7074         case '7':
7075         case '8':
7076         case '9':
7077                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7078                 if (num < 0 || num > shellparam.nparam)
7079                         return -1;
7080                 p = num ? shellparam.p[num - 1] : arg0;
7081                 goto value;
7082         default:
7083                 /* NB: name has form "VAR=..." */
7084                 p = lookupvar(name);
7085  value:
7086                 if (!p)
7087                         return -1;
7088
7089                 len = strtodest(p, syntax, quotes);
7090 #if ENABLE_UNICODE_SUPPORT
7091                 if (subtype == VSLENGTH && len > 0) {
7092                         reinit_unicode_for_ash();
7093                         if (unicode_status == UNICODE_ON) {
7094                                 STADJUST(-len, expdest);
7095                                 discard = 0;
7096                                 len = unicode_strlen(p);
7097                         }
7098                 }
7099 #endif
7100                 break;
7101         }
7102
7103         if (discard)
7104                 STADJUST(-len, expdest);
7105         return len;
7106 }
7107
7108 /*
7109  * Expand a variable, and return a pointer to the next character in the
7110  * input string.
7111  */
7112 static char *
7113 evalvar(char *p, int flag)
7114 {
7115         char varflags;
7116         char subtype;
7117         int quoted;
7118         char easy;
7119         char *var;
7120         int patloc;
7121         int startloc;
7122         ssize_t varlen;
7123
7124         varflags = (unsigned char) *p++;
7125         subtype = varflags & VSTYPE;
7126
7127         if (!subtype)
7128                 raise_error_syntax("bad substitution");
7129
7130         quoted = flag & EXP_QUOTED;
7131         var = p;
7132         easy = (!quoted || (*var == '@' && shellparam.nparam));
7133         startloc = expdest - (char *)stackblock();
7134         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7135
7136  again:
7137         varlen = varvalue(var, varflags, flag, &quoted);
7138         if (varflags & VSNUL)
7139                 varlen--;
7140
7141         if (subtype == VSPLUS) {
7142                 varlen = -1 - varlen;
7143                 goto vsplus;
7144         }
7145
7146         if (subtype == VSMINUS) {
7147  vsplus:
7148                 if (varlen < 0) {
7149                         argstr(
7150                                 p,
7151                                 flag | EXP_TILDE | EXP_WORD
7152                         );
7153                         goto end;
7154                 }
7155                 goto record;
7156         }
7157
7158         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7159                 if (varlen >= 0)
7160                         goto record;
7161
7162                 subevalvar(p, var, 0, subtype, startloc, varflags,
7163                            flag & ~QUOTES_ESC);
7164                 varflags &= ~VSNUL;
7165                 /*
7166                  * Remove any recorded regions beyond
7167                  * start of variable
7168                  */
7169                 removerecordregions(startloc);
7170                 goto again;
7171         }
7172
7173         if (varlen < 0 && uflag)
7174                 varunset(p, var, 0, 0);
7175
7176         if (subtype == VSLENGTH) {
7177                 cvtnum(varlen > 0 ? varlen : 0);
7178                 goto record;
7179         }
7180
7181         if (subtype == VSNORMAL) {
7182  record:
7183                 if (!easy)
7184                         goto end;
7185                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7186                 goto end;
7187         }
7188
7189 #if DEBUG
7190         switch (subtype) {
7191         case VSTRIMLEFT:
7192         case VSTRIMLEFTMAX:
7193         case VSTRIMRIGHT:
7194         case VSTRIMRIGHTMAX:
7195 #if BASH_SUBSTR
7196         case VSSUBSTR:
7197 #endif
7198 #if BASH_PATTERN_SUBST
7199         case VSREPLACE:
7200         case VSREPLACEALL:
7201 #endif
7202                 break;
7203         default:
7204                 abort();
7205         }
7206 #endif
7207
7208         if (varlen >= 0) {
7209                 /*
7210                  * Terminate the string and start recording the pattern
7211                  * right after it
7212                  */
7213                 STPUTC('\0', expdest);
7214                 patloc = expdest - (char *)stackblock();
7215                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7216                                 startloc, varflags, flag)) {
7217                         int amount = expdest - (
7218                                 (char *)stackblock() + patloc - 1
7219                         );
7220                         STADJUST(-amount, expdest);
7221                 }
7222                 /* Remove any recorded regions beyond start of variable */
7223                 removerecordregions(startloc);
7224                 goto record;
7225         }
7226
7227  end:
7228         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7229                 int nesting = 1;
7230                 for (;;) {
7231                         unsigned char c = *p++;
7232                         if (c == CTLESC)
7233                                 p++;
7234                         else if (c == CTLBACKQ) {
7235                                 if (varlen >= 0)
7236                                         argbackq = argbackq->next;
7237                         } else if (c == CTLVAR) {
7238                                 if ((*p++ & VSTYPE) != VSNORMAL)
7239                                         nesting++;
7240                         } else if (c == CTLENDVAR) {
7241                                 if (--nesting == 0)
7242                                         break;
7243                         }
7244                 }
7245         }
7246         return p;
7247 }
7248
7249 /*
7250  * Add a file name to the list.
7251  */
7252 static void
7253 addfname(const char *name)
7254 {
7255         struct strlist *sp;
7256
7257         sp = stzalloc(sizeof(*sp));
7258         sp->text = sstrdup(name);
7259         *exparg.lastp = sp;
7260         exparg.lastp = &sp->next;
7261 }
7262
7263 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7264 static int
7265 hasmeta(const char *p)
7266 {
7267         static const char chars[] ALIGN1 = {
7268                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7269         };
7270
7271         for (;;) {
7272                 p = strpbrk(p, chars);
7273                 if (!p)
7274                         break;
7275                 switch ((unsigned char) *p) {
7276                 case CTLQUOTEMARK:
7277                         for (;;) {
7278                                 p++;
7279                                 if (*p == CTLQUOTEMARK)
7280                                         break;
7281                                 if (*p == CTLESC)
7282                                         p++;
7283                                 if (*p == '\0') /* huh? */
7284                                         return 0;
7285                         }
7286                         break;
7287                 case '\\':
7288                 case CTLESC:
7289                         p++;
7290                         if (*p == '\0')
7291                                 return 0;
7292                         break;
7293                 case '[':
7294                         if (!strchr(p + 1, ']')) {
7295                                 /* It's not a properly closed [] pattern,
7296                                  * but other metas may follow. Continue checking.
7297                                  * my[file* _is_ globbed by bash
7298                                  * and matches filenames like "my[file1".
7299                                  */
7300                                 break;
7301                         }
7302                         /* fallthrough */
7303                 default:
7304                 /* case '*': */
7305                 /* case '?': */
7306                         return 1;
7307                 }
7308                 p++;
7309         }
7310
7311         return 0;
7312 }
7313
7314 /* If we want to use glob() from libc... */
7315 #if !ENABLE_ASH_INTERNAL_GLOB
7316
7317 /* Add the result of glob() to the list */
7318 static void
7319 addglob(const glob_t *pglob)
7320 {
7321         char **p = pglob->gl_pathv;
7322
7323         do {
7324                 addfname(*p);
7325         } while (*++p);
7326 }
7327 static void
7328 expandmeta(struct strlist *str /*, int flag*/)
7329 {
7330         /* TODO - EXP_REDIR */
7331
7332         while (str) {
7333                 char *p;
7334                 glob_t pglob;
7335                 int i;
7336
7337                 if (fflag)
7338                         goto nometa;
7339
7340                 if (!hasmeta(str->text))
7341                         goto nometa;
7342
7343                 INT_OFF;
7344                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7345 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7346 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7347 //
7348 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7349 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7350 // Which means you need to unescape the string, right? Not so fast:
7351 // if there _is_ a file named "file\?" (with backslash), it is returned
7352 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7353 // You DON'T KNOW by looking at the result whether you need to unescape it.
7354 //
7355 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7356 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7357 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7358 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7359 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7360 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7361                 i = glob(p, 0, NULL, &pglob);
7362                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7363                 if (p != str->text)
7364                         free(p);
7365                 switch (i) {
7366                 case 0:
7367 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7368                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7369                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7370                                 goto nometa2;
7371 #endif
7372                         addglob(&pglob);
7373                         globfree(&pglob);
7374                         INT_ON;
7375                         break;
7376                 case GLOB_NOMATCH:
7377  //nometa2:
7378                         globfree(&pglob);
7379                         INT_ON;
7380  nometa:
7381                         *exparg.lastp = str;
7382                         rmescapes(str->text, 0);
7383                         exparg.lastp = &str->next;
7384                         break;
7385                 default:        /* GLOB_NOSPACE */
7386                         globfree(&pglob);
7387                         INT_ON;
7388                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7389                 }
7390                 str = str->next;
7391         }
7392 }
7393
7394 #else
7395 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7396
7397 /*
7398  * Do metacharacter (i.e. *, ?, [...]) expansion.
7399  */
7400 static void
7401 expmeta(char *expdir, char *enddir, char *name)
7402 {
7403         char *p;
7404         const char *cp;
7405         char *start;
7406         char *endname;
7407         int metaflag;
7408         struct stat statb;
7409         DIR *dirp;
7410         struct dirent *dp;
7411         int atend;
7412         int matchdot;
7413         int esc;
7414
7415         metaflag = 0;
7416         start = name;
7417         for (p = name; esc = 0, *p; p += esc + 1) {
7418                 if (*p == '*' || *p == '?')
7419                         metaflag = 1;
7420                 else if (*p == '[') {
7421                         char *q = p + 1;
7422                         if (*q == '!')
7423                                 q++;
7424                         for (;;) {
7425                                 if (*q == '\\')
7426                                         q++;
7427                                 if (*q == '/' || *q == '\0')
7428                                         break;
7429                                 if (*++q == ']') {
7430                                         metaflag = 1;
7431                                         break;
7432                                 }
7433                         }
7434                 } else {
7435                         if (*p == '\\')
7436                                 esc++;
7437                         if (p[esc] == '/') {
7438                                 if (metaflag)
7439                                         break;
7440                                 start = p + esc + 1;
7441                         }
7442                 }
7443         }
7444         if (metaflag == 0) {    /* we've reached the end of the file name */
7445                 if (enddir != expdir)
7446                         metaflag++;
7447                 p = name;
7448                 do {
7449                         if (*p == '\\')
7450                                 p++;
7451                         *enddir++ = *p;
7452                 } while (*p++);
7453                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7454                         addfname(expdir);
7455                 return;
7456         }
7457         endname = p;
7458         if (name < start) {
7459                 p = name;
7460                 do {
7461                         if (*p == '\\')
7462                                 p++;
7463                         *enddir++ = *p++;
7464                 } while (p < start);
7465         }
7466         if (enddir == expdir) {
7467                 cp = ".";
7468         } else if (enddir == expdir + 1 && *expdir == '/') {
7469                 cp = "/";
7470         } else {
7471                 cp = expdir;
7472                 enddir[-1] = '\0';
7473         }
7474         dirp = opendir(cp);
7475         if (dirp == NULL)
7476                 return;
7477         if (enddir != expdir)
7478                 enddir[-1] = '/';
7479         if (*endname == 0) {
7480                 atend = 1;
7481         } else {
7482                 atend = 0;
7483                 *endname = '\0';
7484                 endname += esc + 1;
7485         }
7486         matchdot = 0;
7487         p = start;
7488         if (*p == '\\')
7489                 p++;
7490         if (*p == '.')
7491                 matchdot++;
7492         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7493                 if (dp->d_name[0] == '.' && !matchdot)
7494                         continue;
7495                 if (pmatch(start, dp->d_name)) {
7496                         if (atend) {
7497                                 strcpy(enddir, dp->d_name);
7498                                 addfname(expdir);
7499                         } else {
7500                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7501                                         continue;
7502                                 p[-1] = '/';
7503                                 expmeta(expdir, p, endname);
7504                         }
7505                 }
7506         }
7507         closedir(dirp);
7508         if (!atend)
7509                 endname[-esc - 1] = esc ? '\\' : '/';
7510 }
7511
7512 static struct strlist *
7513 msort(struct strlist *list, int len)
7514 {
7515         struct strlist *p, *q = NULL;
7516         struct strlist **lpp;
7517         int half;
7518         int n;
7519
7520         if (len <= 1)
7521                 return list;
7522         half = len >> 1;
7523         p = list;
7524         for (n = half; --n >= 0;) {
7525                 q = p;
7526                 p = p->next;
7527         }
7528         q->next = NULL;                 /* terminate first half of list */
7529         q = msort(list, half);          /* sort first half of list */
7530         p = msort(p, len - half);               /* sort second half */
7531         lpp = &list;
7532         for (;;) {
7533 #if ENABLE_LOCALE_SUPPORT
7534                 if (strcoll(p->text, q->text) < 0)
7535 #else
7536                 if (strcmp(p->text, q->text) < 0)
7537 #endif
7538                                                 {
7539                         *lpp = p;
7540                         lpp = &p->next;
7541                         p = *lpp;
7542                         if (p == NULL) {
7543                                 *lpp = q;
7544                                 break;
7545                         }
7546                 } else {
7547                         *lpp = q;
7548                         lpp = &q->next;
7549                         q = *lpp;
7550                         if (q == NULL) {
7551                                 *lpp = p;
7552                                 break;
7553                         }
7554                 }
7555         }
7556         return list;
7557 }
7558
7559 /*
7560  * Sort the results of file name expansion.  It calculates the number of
7561  * strings to sort and then calls msort (short for merge sort) to do the
7562  * work.
7563  */
7564 static struct strlist *
7565 expsort(struct strlist *str)
7566 {
7567         int len;
7568         struct strlist *sp;
7569
7570         len = 0;
7571         for (sp = str; sp; sp = sp->next)
7572                 len++;
7573         return msort(str, len);
7574 }
7575
7576 static void
7577 expandmeta(struct strlist *str /*, int flag*/)
7578 {
7579         /* TODO - EXP_REDIR */
7580
7581         while (str) {
7582                 char *expdir;
7583                 struct strlist **savelastp;
7584                 struct strlist *sp;
7585                 char *p;
7586
7587                 if (fflag)
7588                         goto nometa;
7589                 if (!hasmeta(str->text))
7590                         goto nometa;
7591                 savelastp = exparg.lastp;
7592
7593                 INT_OFF;
7594                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7595                 {
7596                         int i = strlen(str->text);
7597 //BUGGY estimation of how long expanded name can be
7598                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7599                 }
7600                 expmeta(expdir, expdir, p);
7601                 free(expdir);
7602                 if (p != str->text)
7603                         free(p);
7604                 INT_ON;
7605                 if (exparg.lastp == savelastp) {
7606                         /*
7607                          * no matches
7608                          */
7609  nometa:
7610                         *exparg.lastp = str;
7611                         rmescapes(str->text, 0);
7612                         exparg.lastp = &str->next;
7613                 } else {
7614                         *exparg.lastp = NULL;
7615                         *savelastp = sp = expsort(*savelastp);
7616                         while (sp->next != NULL)
7617                                 sp = sp->next;
7618                         exparg.lastp = &sp->next;
7619                 }
7620                 str = str->next;
7621         }
7622 }
7623 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7624
7625 /*
7626  * Perform variable substitution and command substitution on an argument,
7627  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7628  * perform splitting and file name expansion.  When arglist is NULL, perform
7629  * here document expansion.
7630  */
7631 static void
7632 expandarg(union node *arg, struct arglist *arglist, int flag)
7633 {
7634         struct strlist *sp;
7635         char *p;
7636
7637         argbackq = arg->narg.backquote;
7638         STARTSTACKSTR(expdest);
7639         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7640         argstr(arg->narg.text, flag);
7641         p = _STPUTC('\0', expdest);
7642         expdest = p - 1;
7643         if (arglist == NULL) {
7644                 /* here document expanded */
7645                 goto out;
7646         }
7647         p = grabstackstr(p);
7648         TRACE(("expandarg: p:'%s'\n", p));
7649         exparg.lastp = &exparg.list;
7650         /*
7651          * TODO - EXP_REDIR
7652          */
7653         if (flag & EXP_FULL) {
7654                 ifsbreakup(p, &exparg);
7655                 *exparg.lastp = NULL;
7656                 exparg.lastp = &exparg.list;
7657                 expandmeta(exparg.list /*, flag*/);
7658         } else {
7659                 sp = stzalloc(sizeof(*sp));
7660                 sp->text = p;
7661                 *exparg.lastp = sp;
7662                 exparg.lastp = &sp->next;
7663         }
7664         *exparg.lastp = NULL;
7665         if (exparg.list) {
7666                 *arglist->lastp = exparg.list;
7667                 arglist->lastp = exparg.lastp;
7668         }
7669
7670  out:
7671         ifsfree();
7672 }
7673
7674 /*
7675  * Expand shell variables and backquotes inside a here document.
7676  */
7677 static void
7678 expandhere(union node *arg, int fd)
7679 {
7680         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7681         full_write(fd, stackblock(), expdest - (char *)stackblock());
7682 }
7683
7684 /*
7685  * Returns true if the pattern matches the string.
7686  */
7687 static int
7688 patmatch(char *pattern, const char *string)
7689 {
7690         char *p = preglob(pattern, 0);
7691         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7692         return pmatch(p, string);
7693 }
7694
7695 /*
7696  * See if a pattern matches in a case statement.
7697  */
7698 static int
7699 casematch(union node *pattern, char *val)
7700 {
7701         struct stackmark smark;
7702         int result;
7703
7704         setstackmark(&smark);
7705         argbackq = pattern->narg.backquote;
7706         STARTSTACKSTR(expdest);
7707         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7708         STACKSTRNUL(expdest);
7709         ifsfree();
7710         result = patmatch(stackblock(), val);
7711         popstackmark(&smark);
7712         return result;
7713 }
7714
7715
7716 /* ============ find_command */
7717
7718 struct builtincmd {
7719         const char *name;
7720         int (*builtin)(int, char **) FAST_FUNC;
7721         /* unsigned flags; */
7722 };
7723 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7724 /* "regular" builtins always take precedence over commands,
7725  * regardless of PATH=....%builtin... position */
7726 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7727 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7728
7729 struct cmdentry {
7730         smallint cmdtype;       /* CMDxxx */
7731         union param {
7732                 int index;
7733                 /* index >= 0 for commands without path (slashes) */
7734                 /* (TODO: what exactly does the value mean? PATH position?) */
7735                 /* index == -1 for commands with slashes */
7736                 /* index == (-2 - applet_no) for NOFORK applets */
7737                 const struct builtincmd *cmd;
7738                 struct funcnode *func;
7739         } u;
7740 };
7741 /* values of cmdtype */
7742 #define CMDUNKNOWN      -1      /* no entry in table for command */
7743 #define CMDNORMAL       0       /* command is an executable program */
7744 #define CMDFUNCTION     1       /* command is a shell function */
7745 #define CMDBUILTIN      2       /* command is a shell builtin */
7746
7747 /* action to find_command() */
7748 #define DO_ERR          0x01    /* prints errors */
7749 #define DO_ABS          0x02    /* checks absolute paths */
7750 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7751 #define DO_ALTPATH      0x08    /* using alternate path */
7752 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7753
7754 static void find_command(char *, struct cmdentry *, int, const char *);
7755
7756
7757 /* ============ Hashing commands */
7758
7759 /*
7760  * When commands are first encountered, they are entered in a hash table.
7761  * This ensures that a full path search will not have to be done for them
7762  * on each invocation.
7763  *
7764  * We should investigate converting to a linear search, even though that
7765  * would make the command name "hash" a misnomer.
7766  */
7767
7768 struct tblentry {
7769         struct tblentry *next;  /* next entry in hash chain */
7770         union param param;      /* definition of builtin function */
7771         smallint cmdtype;       /* CMDxxx */
7772         char rehash;            /* if set, cd done since entry created */
7773         char cmdname[1];        /* name of command */
7774 };
7775
7776 static struct tblentry **cmdtable;
7777 #define INIT_G_cmdtable() do { \
7778         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7779 } while (0)
7780
7781 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7782
7783
7784 static void
7785 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7786 {
7787 #if ENABLE_FEATURE_SH_STANDALONE
7788         if (applet_no >= 0) {
7789                 if (APPLET_IS_NOEXEC(applet_no)) {
7790                         clearenv();
7791                         while (*envp)
7792                                 putenv(*envp++);
7793                         popredir(/*drop:*/ 1);
7794                         run_applet_no_and_exit(applet_no, cmd, argv);
7795                 }
7796                 /* re-exec ourselves with the new arguments */
7797                 execve(bb_busybox_exec_path, argv, envp);
7798                 /* If they called chroot or otherwise made the binary no longer
7799                  * executable, fall through */
7800         }
7801 #endif
7802
7803  repeat:
7804 #ifdef SYSV
7805         do {
7806                 execve(cmd, argv, envp);
7807         } while (errno == EINTR);
7808 #else
7809         execve(cmd, argv, envp);
7810 #endif
7811         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7812                 /* Run "cmd" as a shell script:
7813                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7814                  * "If the execve() function fails with ENOEXEC, the shell
7815                  * shall execute a command equivalent to having a shell invoked
7816                  * with the command name as its first operand,
7817                  * with any remaining arguments passed to the new shell"
7818                  *
7819                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7820                  * just call ourselves.
7821                  *
7822                  * Note that bash reads ~80 chars of the file, and if it sees
7823                  * a zero byte before it sees newline, it doesn't try to
7824                  * interpret it, but fails with "cannot execute binary file"
7825                  * message and exit code 126. For one, this prevents attempts
7826                  * to interpret foreign ELF binaries as shell scripts.
7827                  */
7828                 argv[0] = (char*) cmd;
7829                 cmd = bb_busybox_exec_path;
7830                 /* NB: this is only possible because all callers of shellexec()
7831                  * ensure that the argv[-1] slot exists!
7832                  */
7833                 argv--;
7834                 argv[0] = (char*) "ash";
7835                 goto repeat;
7836         }
7837 }
7838
7839 /*
7840  * Exec a program.  Never returns.  If you change this routine, you may
7841  * have to change the find_command routine as well.
7842  * argv[-1] must exist and be writable! See tryexec() for why.
7843  */
7844 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7845 static void shellexec(char *prog, char **argv, const char *path, int idx)
7846 {
7847         char *cmdname;
7848         int e;
7849         char **envp;
7850         int exerrno;
7851         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7852
7853         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7854         if (strchr(prog, '/') != NULL
7855 #if ENABLE_FEATURE_SH_STANDALONE
7856          || (applet_no = find_applet_by_name(prog)) >= 0
7857 #endif
7858         ) {
7859                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7860                 if (applet_no >= 0) {
7861                         /* We tried execing ourself, but it didn't work.
7862                          * Maybe /proc/self/exe doesn't exist?
7863                          * Try $PATH search.
7864                          */
7865                         goto try_PATH;
7866                 }
7867                 e = errno;
7868         } else {
7869  try_PATH:
7870                 e = ENOENT;
7871                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7872                         if (--idx < 0 && pathopt == NULL) {
7873                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7874                                 if (errno != ENOENT && errno != ENOTDIR)
7875                                         e = errno;
7876                         }
7877                         stunalloc(cmdname);
7878                 }
7879         }
7880
7881         /* Map to POSIX errors */
7882         switch (e) {
7883         case EACCES:
7884                 exerrno = 126;
7885                 break;
7886         case ENOENT:
7887                 exerrno = 127;
7888                 break;
7889         default:
7890                 exerrno = 2;
7891                 break;
7892         }
7893         exitstatus = exerrno;
7894         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7895                 prog, e, suppress_int));
7896         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7897         /* NOTREACHED */
7898 }
7899
7900 static void
7901 printentry(struct tblentry *cmdp)
7902 {
7903         int idx;
7904         const char *path;
7905         char *name;
7906
7907         idx = cmdp->param.index;
7908         path = pathval();
7909         do {
7910                 name = path_advance(&path, cmdp->cmdname);
7911                 stunalloc(name);
7912         } while (--idx >= 0);
7913         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7914 }
7915
7916 /*
7917  * Clear out command entries.  The argument specifies the first entry in
7918  * PATH which has changed.
7919  */
7920 static void
7921 clearcmdentry(int firstchange)
7922 {
7923         struct tblentry **tblp;
7924         struct tblentry **pp;
7925         struct tblentry *cmdp;
7926
7927         INT_OFF;
7928         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7929                 pp = tblp;
7930                 while ((cmdp = *pp) != NULL) {
7931                         if ((cmdp->cmdtype == CMDNORMAL &&
7932                              cmdp->param.index >= firstchange)
7933                          || (cmdp->cmdtype == CMDBUILTIN &&
7934                              builtinloc >= firstchange)
7935                         ) {
7936                                 *pp = cmdp->next;
7937                                 free(cmdp);
7938                         } else {
7939                                 pp = &cmdp->next;
7940                         }
7941                 }
7942         }
7943         INT_ON;
7944 }
7945
7946 /*
7947  * Locate a command in the command hash table.  If "add" is nonzero,
7948  * add the command to the table if it is not already present.  The
7949  * variable "lastcmdentry" is set to point to the address of the link
7950  * pointing to the entry, so that delete_cmd_entry can delete the
7951  * entry.
7952  *
7953  * Interrupts must be off if called with add != 0.
7954  */
7955 static struct tblentry **lastcmdentry;
7956
7957 static struct tblentry *
7958 cmdlookup(const char *name, int add)
7959 {
7960         unsigned int hashval;
7961         const char *p;
7962         struct tblentry *cmdp;
7963         struct tblentry **pp;
7964
7965         p = name;
7966         hashval = (unsigned char)*p << 4;
7967         while (*p)
7968                 hashval += (unsigned char)*p++;
7969         hashval &= 0x7FFF;
7970         pp = &cmdtable[hashval % CMDTABLESIZE];
7971         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7972                 if (strcmp(cmdp->cmdname, name) == 0)
7973                         break;
7974                 pp = &cmdp->next;
7975         }
7976         if (add && cmdp == NULL) {
7977                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7978                                 + strlen(name)
7979                                 /* + 1 - already done because
7980                                  * tblentry::cmdname is char[1] */);
7981                 /*cmdp->next = NULL; - ckzalloc did it */
7982                 cmdp->cmdtype = CMDUNKNOWN;
7983                 strcpy(cmdp->cmdname, name);
7984         }
7985         lastcmdentry = pp;
7986         return cmdp;
7987 }
7988
7989 /*
7990  * Delete the command entry returned on the last lookup.
7991  */
7992 static void
7993 delete_cmd_entry(void)
7994 {
7995         struct tblentry *cmdp;
7996
7997         INT_OFF;
7998         cmdp = *lastcmdentry;
7999         *lastcmdentry = cmdp->next;
8000         if (cmdp->cmdtype == CMDFUNCTION)
8001                 freefunc(cmdp->param.func);
8002         free(cmdp);
8003         INT_ON;
8004 }
8005
8006 /*
8007  * Add a new command entry, replacing any existing command entry for
8008  * the same name - except special builtins.
8009  */
8010 static void
8011 addcmdentry(char *name, struct cmdentry *entry)
8012 {
8013         struct tblentry *cmdp;
8014
8015         cmdp = cmdlookup(name, 1);
8016         if (cmdp->cmdtype == CMDFUNCTION) {
8017                 freefunc(cmdp->param.func);
8018         }
8019         cmdp->cmdtype = entry->cmdtype;
8020         cmdp->param = entry->u;
8021         cmdp->rehash = 0;
8022 }
8023
8024 static int FAST_FUNC
8025 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8026 {
8027         struct tblentry **pp;
8028         struct tblentry *cmdp;
8029         int c;
8030         struct cmdentry entry;
8031         char *name;
8032
8033         if (nextopt("r") != '\0') {
8034                 clearcmdentry(0);
8035                 return 0;
8036         }
8037
8038         if (*argptr == NULL) {
8039                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8040                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8041                                 if (cmdp->cmdtype == CMDNORMAL)
8042                                         printentry(cmdp);
8043                         }
8044                 }
8045                 return 0;
8046         }
8047
8048         c = 0;
8049         while ((name = *argptr) != NULL) {
8050                 cmdp = cmdlookup(name, 0);
8051                 if (cmdp != NULL
8052                  && (cmdp->cmdtype == CMDNORMAL
8053                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8054                 ) {
8055                         delete_cmd_entry();
8056                 }
8057                 find_command(name, &entry, DO_ERR, pathval());
8058                 if (entry.cmdtype == CMDUNKNOWN)
8059                         c = 1;
8060                 argptr++;
8061         }
8062         return c;
8063 }
8064
8065 /*
8066  * Called when a cd is done.  Marks all commands so the next time they
8067  * are executed they will be rehashed.
8068  */
8069 static void
8070 hashcd(void)
8071 {
8072         struct tblentry **pp;
8073         struct tblentry *cmdp;
8074
8075         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8076                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8077                         if (cmdp->cmdtype == CMDNORMAL
8078                          || (cmdp->cmdtype == CMDBUILTIN
8079                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8080                              && builtinloc > 0)
8081                         ) {
8082                                 cmdp->rehash = 1;
8083                         }
8084                 }
8085         }
8086 }
8087
8088 /*
8089  * Fix command hash table when PATH changed.
8090  * Called before PATH is changed.  The argument is the new value of PATH;
8091  * pathval() still returns the old value at this point.
8092  * Called with interrupts off.
8093  */
8094 static void FAST_FUNC
8095 changepath(const char *new)
8096 {
8097         const char *old;
8098         int firstchange;
8099         int idx;
8100         int idx_bltin;
8101
8102         old = pathval();
8103         firstchange = 9999;     /* assume no change */
8104         idx = 0;
8105         idx_bltin = -1;
8106         for (;;) {
8107                 if (*old != *new) {
8108                         firstchange = idx;
8109                         if ((*old == '\0' && *new == ':')
8110                          || (*old == ':' && *new == '\0')
8111                         ) {
8112                                 firstchange++;
8113                         }
8114                         old = new;      /* ignore subsequent differences */
8115                 }
8116                 if (*new == '\0')
8117                         break;
8118                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8119                         idx_bltin = idx;
8120                 if (*new == ':')
8121                         idx++;
8122                 new++;
8123                 old++;
8124         }
8125         if (builtinloc < 0 && idx_bltin >= 0)
8126                 builtinloc = idx_bltin;             /* zap builtins */
8127         if (builtinloc >= 0 && idx_bltin < 0)
8128                 firstchange = 0;
8129         clearcmdentry(firstchange);
8130         builtinloc = idx_bltin;
8131 }
8132 enum {
8133         TEOF,
8134         TNL,
8135         TREDIR,
8136         TWORD,
8137         TSEMI,
8138         TBACKGND,
8139         TAND,
8140         TOR,
8141         TPIPE,
8142         TLP,
8143         TRP,
8144         TENDCASE,
8145         TENDBQUOTE,
8146         TNOT,
8147         TCASE,
8148         TDO,
8149         TDONE,
8150         TELIF,
8151         TELSE,
8152         TESAC,
8153         TFI,
8154         TFOR,
8155 #if BASH_FUNCTION
8156         TFUNCTION,
8157 #endif
8158         TIF,
8159         TIN,
8160         TTHEN,
8161         TUNTIL,
8162         TWHILE,
8163         TBEGIN,
8164         TEND
8165 };
8166 typedef smallint token_id_t;
8167
8168 /* Nth bit indicates if token marks the end of a list */
8169 enum {
8170         tokendlist = 0
8171         /*  0 */ | (1u << TEOF)
8172         /*  1 */ | (0u << TNL)
8173         /*  2 */ | (0u << TREDIR)
8174         /*  3 */ | (0u << TWORD)
8175         /*  4 */ | (0u << TSEMI)
8176         /*  5 */ | (0u << TBACKGND)
8177         /*  6 */ | (0u << TAND)
8178         /*  7 */ | (0u << TOR)
8179         /*  8 */ | (0u << TPIPE)
8180         /*  9 */ | (0u << TLP)
8181         /* 10 */ | (1u << TRP)
8182         /* 11 */ | (1u << TENDCASE)
8183         /* 12 */ | (1u << TENDBQUOTE)
8184         /* 13 */ | (0u << TNOT)
8185         /* 14 */ | (0u << TCASE)
8186         /* 15 */ | (1u << TDO)
8187         /* 16 */ | (1u << TDONE)
8188         /* 17 */ | (1u << TELIF)
8189         /* 18 */ | (1u << TELSE)
8190         /* 19 */ | (1u << TESAC)
8191         /* 20 */ | (1u << TFI)
8192         /* 21 */ | (0u << TFOR)
8193 #if BASH_FUNCTION
8194         /* 22 */ | (0u << TFUNCTION)
8195 #endif
8196         /* 23 */ | (0u << TIF)
8197         /* 24 */ | (0u << TIN)
8198         /* 25 */ | (1u << TTHEN)
8199         /* 26 */ | (0u << TUNTIL)
8200         /* 27 */ | (0u << TWHILE)
8201         /* 28 */ | (0u << TBEGIN)
8202         /* 29 */ | (1u << TEND)
8203         , /* thus far 29 bits used */
8204 };
8205
8206 static const char *const tokname_array[] = {
8207         "end of file",
8208         "newline",
8209         "redirection",
8210         "word",
8211         ";",
8212         "&",
8213         "&&",
8214         "||",
8215         "|",
8216         "(",
8217         ")",
8218         ";;",
8219         "`",
8220 #define KWDOFFSET 13
8221         /* the following are keywords */
8222         "!",
8223         "case",
8224         "do",
8225         "done",
8226         "elif",
8227         "else",
8228         "esac",
8229         "fi",
8230         "for",
8231 #if BASH_FUNCTION
8232         "function",
8233 #endif
8234         "if",
8235         "in",
8236         "then",
8237         "until",
8238         "while",
8239         "{",
8240         "}",
8241 };
8242
8243 /* Wrapper around strcmp for qsort/bsearch/... */
8244 static int
8245 pstrcmp(const void *a, const void *b)
8246 {
8247         return strcmp((char*)a, *(char**)b);
8248 }
8249
8250 static const char *const *
8251 findkwd(const char *s)
8252 {
8253         return bsearch(s, tokname_array + KWDOFFSET,
8254                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8255                         sizeof(tokname_array[0]), pstrcmp);
8256 }
8257
8258 /*
8259  * Locate and print what a word is...
8260  */
8261 static int
8262 describe_command(char *command, const char *path, int describe_command_verbose)
8263 {
8264         struct cmdentry entry;
8265 #if ENABLE_ASH_ALIAS
8266         const struct alias *ap;
8267 #endif
8268
8269         path = path ? path : pathval();
8270
8271         if (describe_command_verbose) {
8272                 out1str(command);
8273         }
8274
8275         /* First look at the keywords */
8276         if (findkwd(command)) {
8277                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8278                 goto out;
8279         }
8280
8281 #if ENABLE_ASH_ALIAS
8282         /* Then look at the aliases */
8283         ap = lookupalias(command, 0);
8284         if (ap != NULL) {
8285                 if (!describe_command_verbose) {
8286                         out1str("alias ");
8287                         printalias(ap);
8288                         return 0;
8289                 }
8290                 out1fmt(" is an alias for %s", ap->val);
8291                 goto out;
8292         }
8293 #endif
8294         /* Brute force */
8295         find_command(command, &entry, DO_ABS, path);
8296
8297         switch (entry.cmdtype) {
8298         case CMDNORMAL: {
8299                 int j = entry.u.index;
8300                 char *p;
8301                 if (j < 0) {
8302                         p = command;
8303                 } else {
8304                         do {
8305                                 p = path_advance(&path, command);
8306                                 stunalloc(p);
8307                         } while (--j >= 0);
8308                 }
8309                 if (describe_command_verbose) {
8310                         out1fmt(" is %s", p);
8311                 } else {
8312                         out1str(p);
8313                 }
8314                 break;
8315         }
8316
8317         case CMDFUNCTION:
8318                 if (describe_command_verbose) {
8319                         out1str(" is a shell function");
8320                 } else {
8321                         out1str(command);
8322                 }
8323                 break;
8324
8325         case CMDBUILTIN:
8326                 if (describe_command_verbose) {
8327                         out1fmt(" is a %sshell builtin",
8328                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8329                                         "special " : nullstr
8330                         );
8331                 } else {
8332                         out1str(command);
8333                 }
8334                 break;
8335
8336         default:
8337                 if (describe_command_verbose) {
8338                         out1str(": not found\n");
8339                 }
8340                 return 127;
8341         }
8342  out:
8343         out1str("\n");
8344         return 0;
8345 }
8346
8347 static int FAST_FUNC
8348 typecmd(int argc UNUSED_PARAM, char **argv)
8349 {
8350         int i = 1;
8351         int err = 0;
8352         int verbose = 1;
8353
8354         /* type -p ... ? (we don't bother checking for 'p') */
8355         if (argv[1] && argv[1][0] == '-') {
8356                 i++;
8357                 verbose = 0;
8358         }
8359         while (argv[i]) {
8360                 err |= describe_command(argv[i++], NULL, verbose);
8361         }
8362         return err;
8363 }
8364
8365 #if ENABLE_ASH_CMDCMD
8366 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8367 static char **
8368 parse_command_args(char **argv, const char **path)
8369 {
8370         char *cp, c;
8371
8372         for (;;) {
8373                 cp = *++argv;
8374                 if (!cp)
8375                         return NULL;
8376                 if (*cp++ != '-')
8377                         break;
8378                 c = *cp++;
8379                 if (!c)
8380                         break;
8381                 if (c == '-' && !*cp) {
8382                         if (!*++argv)
8383                                 return NULL;
8384                         break;
8385                 }
8386                 do {
8387                         switch (c) {
8388                         case 'p':
8389                                 *path = bb_default_path;
8390                                 break;
8391                         default:
8392                                 /* run 'typecmd' for other options */
8393                                 return NULL;
8394                         }
8395                         c = *cp++;
8396                 } while (c);
8397         }
8398         return argv;
8399 }
8400
8401 static int FAST_FUNC
8402 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8403 {
8404         char *cmd;
8405         int c;
8406         enum {
8407                 VERIFY_BRIEF = 1,
8408                 VERIFY_VERBOSE = 2,
8409         } verify = 0;
8410         const char *path = NULL;
8411
8412         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8413          * never reaches this function.
8414          */
8415
8416         while ((c = nextopt("pvV")) != '\0')
8417                 if (c == 'V')
8418                         verify |= VERIFY_VERBOSE;
8419                 else if (c == 'v')
8420                         /*verify |= VERIFY_BRIEF*/;
8421 #if DEBUG
8422                 else if (c != 'p')
8423                         abort();
8424 #endif
8425                 else
8426                         path = bb_default_path;
8427
8428         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8429         cmd = *argptr;
8430         if (/*verify && */ cmd)
8431                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8432
8433         return 0;
8434 }
8435 #endif
8436
8437
8438 /*static int funcblocksize;     // size of structures in function */
8439 /*static int funcstringsize;    // size of strings in node */
8440 static void *funcblock;         /* block to allocate function from */
8441 static char *funcstring_end;    /* end of block to allocate strings from */
8442
8443 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8444         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8445         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8446         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8447         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8448         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8449         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8450         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8451         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8452         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8453         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8454         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8455         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8456         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8457         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8458         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8459         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8460         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8461 #if BASH_REDIR_OUTPUT
8462         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8463 #endif
8464         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8465         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8466         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8467         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8468         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8469         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8470         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8471         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8472         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8473 };
8474
8475 static int calcsize(int funcblocksize, union node *n);
8476
8477 static int
8478 sizenodelist(int funcblocksize, struct nodelist *lp)
8479 {
8480         while (lp) {
8481                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8482                 funcblocksize = calcsize(funcblocksize, lp->n);
8483                 lp = lp->next;
8484         }
8485         return funcblocksize;
8486 }
8487
8488 static int
8489 calcsize(int funcblocksize, union node *n)
8490 {
8491         if (n == NULL)
8492                 return funcblocksize;
8493         funcblocksize += nodesize[n->type];
8494         switch (n->type) {
8495         case NCMD:
8496                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8497                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8498                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8499                 break;
8500         case NPIPE:
8501                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8502                 break;
8503         case NREDIR:
8504         case NBACKGND:
8505         case NSUBSHELL:
8506                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8507                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8508                 break;
8509         case NAND:
8510         case NOR:
8511         case NSEMI:
8512         case NWHILE:
8513         case NUNTIL:
8514                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8515                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8516                 break;
8517         case NIF:
8518                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8519                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8520                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8521                 break;
8522         case NFOR:
8523                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8524                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8525                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8526                 break;
8527         case NCASE:
8528                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8529                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8530                 break;
8531         case NCLIST:
8532                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8533                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8534                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8535                 break;
8536         case NDEFUN:
8537         case NARG:
8538                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8539                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8540                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8541                 break;
8542         case NTO:
8543 #if BASH_REDIR_OUTPUT
8544         case NTO2:
8545 #endif
8546         case NCLOBBER:
8547         case NFROM:
8548         case NFROMTO:
8549         case NAPPEND:
8550                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8551                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8552                 break;
8553         case NTOFD:
8554         case NFROMFD:
8555                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8556                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8557         break;
8558         case NHERE:
8559         case NXHERE:
8560                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8561                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8562                 break;
8563         case NNOT:
8564                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8565                 break;
8566         };
8567         return funcblocksize;
8568 }
8569
8570 static char *
8571 nodeckstrdup(char *s)
8572 {
8573         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8574         return strcpy(funcstring_end, s);
8575 }
8576
8577 static union node *copynode(union node *);
8578
8579 static struct nodelist *
8580 copynodelist(struct nodelist *lp)
8581 {
8582         struct nodelist *start;
8583         struct nodelist **lpp;
8584
8585         lpp = &start;
8586         while (lp) {
8587                 *lpp = funcblock;
8588                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8589                 (*lpp)->n = copynode(lp->n);
8590                 lp = lp->next;
8591                 lpp = &(*lpp)->next;
8592         }
8593         *lpp = NULL;
8594         return start;
8595 }
8596
8597 static union node *
8598 copynode(union node *n)
8599 {
8600         union node *new;
8601
8602         if (n == NULL)
8603                 return NULL;
8604         new = funcblock;
8605         funcblock = (char *) funcblock + nodesize[n->type];
8606
8607         switch (n->type) {
8608         case NCMD:
8609                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8610                 new->ncmd.args = copynode(n->ncmd.args);
8611                 new->ncmd.assign = copynode(n->ncmd.assign);
8612                 break;
8613         case NPIPE:
8614                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8615                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8616                 break;
8617         case NREDIR:
8618         case NBACKGND:
8619         case NSUBSHELL:
8620                 new->nredir.redirect = copynode(n->nredir.redirect);
8621                 new->nredir.n = copynode(n->nredir.n);
8622                 break;
8623         case NAND:
8624         case NOR:
8625         case NSEMI:
8626         case NWHILE:
8627         case NUNTIL:
8628                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8629                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8630                 break;
8631         case NIF:
8632                 new->nif.elsepart = copynode(n->nif.elsepart);
8633                 new->nif.ifpart = copynode(n->nif.ifpart);
8634                 new->nif.test = copynode(n->nif.test);
8635                 break;
8636         case NFOR:
8637                 new->nfor.var = nodeckstrdup(n->nfor.var);
8638                 new->nfor.body = copynode(n->nfor.body);
8639                 new->nfor.args = copynode(n->nfor.args);
8640                 break;
8641         case NCASE:
8642                 new->ncase.cases = copynode(n->ncase.cases);
8643                 new->ncase.expr = copynode(n->ncase.expr);
8644                 break;
8645         case NCLIST:
8646                 new->nclist.body = copynode(n->nclist.body);
8647                 new->nclist.pattern = copynode(n->nclist.pattern);
8648                 new->nclist.next = copynode(n->nclist.next);
8649                 break;
8650         case NDEFUN:
8651         case NARG:
8652                 new->narg.backquote = copynodelist(n->narg.backquote);
8653                 new->narg.text = nodeckstrdup(n->narg.text);
8654                 new->narg.next = copynode(n->narg.next);
8655                 break;
8656         case NTO:
8657 #if BASH_REDIR_OUTPUT
8658         case NTO2:
8659 #endif
8660         case NCLOBBER:
8661         case NFROM:
8662         case NFROMTO:
8663         case NAPPEND:
8664                 new->nfile.fname = copynode(n->nfile.fname);
8665                 new->nfile.fd = n->nfile.fd;
8666                 new->nfile.next = copynode(n->nfile.next);
8667                 break;
8668         case NTOFD:
8669         case NFROMFD:
8670                 new->ndup.vname = copynode(n->ndup.vname);
8671                 new->ndup.dupfd = n->ndup.dupfd;
8672                 new->ndup.fd = n->ndup.fd;
8673                 new->ndup.next = copynode(n->ndup.next);
8674                 break;
8675         case NHERE:
8676         case NXHERE:
8677                 new->nhere.doc = copynode(n->nhere.doc);
8678                 new->nhere.fd = n->nhere.fd;
8679                 new->nhere.next = copynode(n->nhere.next);
8680                 break;
8681         case NNOT:
8682                 new->nnot.com = copynode(n->nnot.com);
8683                 break;
8684         };
8685         new->type = n->type;
8686         return new;
8687 }
8688
8689 /*
8690  * Make a copy of a parse tree.
8691  */
8692 static struct funcnode *
8693 copyfunc(union node *n)
8694 {
8695         struct funcnode *f;
8696         size_t blocksize;
8697
8698         /*funcstringsize = 0;*/
8699         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8700         f = ckzalloc(blocksize /* + funcstringsize */);
8701         funcblock = (char *) f + offsetof(struct funcnode, n);
8702         funcstring_end = (char *) f + blocksize;
8703         copynode(n);
8704         /* f->count = 0; - ckzalloc did it */
8705         return f;
8706 }
8707
8708 /*
8709  * Define a shell function.
8710  */
8711 static void
8712 defun(union node *func)
8713 {
8714         struct cmdentry entry;
8715
8716         INT_OFF;
8717         entry.cmdtype = CMDFUNCTION;
8718         entry.u.func = copyfunc(func);
8719         addcmdentry(func->narg.text, &entry);
8720         INT_ON;
8721 }
8722
8723 /* Reasons for skipping commands (see comment on breakcmd routine) */
8724 #define SKIPBREAK      (1 << 0)
8725 #define SKIPCONT       (1 << 1)
8726 #define SKIPFUNC       (1 << 2)
8727 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8728 static int skipcount;           /* number of levels to skip */
8729 static int funcnest;            /* depth of function calls */
8730 static int loopnest;            /* current loop nesting level */
8731
8732 /* Forward decl way out to parsing code - dotrap needs it */
8733 static int evalstring(char *s, int flags);
8734
8735 /* Called to execute a trap.
8736  * Single callsite - at the end of evaltree().
8737  * If we return non-zero, evaltree raises EXEXIT exception.
8738  *
8739  * Perhaps we should avoid entering new trap handlers
8740  * while we are executing a trap handler. [is it a TODO?]
8741  */
8742 static void
8743 dotrap(void)
8744 {
8745         uint8_t *g;
8746         int sig;
8747         uint8_t last_status;
8748
8749         if (!pending_sig)
8750                 return;
8751
8752         last_status = exitstatus;
8753         pending_sig = 0;
8754         barrier();
8755
8756         TRACE(("dotrap entered\n"));
8757         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8758                 char *p;
8759
8760                 if (!*g)
8761                         continue;
8762
8763                 if (evalskip) {
8764                         pending_sig = sig;
8765                         break;
8766                 }
8767
8768                 p = trap[sig];
8769                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8770                  * don't upset it by resetting gotsig[SIGINT-1] */
8771                 if (sig == SIGINT && !p)
8772                         continue;
8773
8774                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8775                 *g = 0;
8776                 if (!p)
8777                         continue;
8778                 evalstring(p, 0);
8779         }
8780         exitstatus = last_status;
8781         TRACE(("dotrap returns\n"));
8782 }
8783
8784 /* forward declarations - evaluation is fairly recursive business... */
8785 static int evalloop(union node *, int);
8786 static int evalfor(union node *, int);
8787 static int evalcase(union node *, int);
8788 static int evalsubshell(union node *, int);
8789 static void expredir(union node *);
8790 static int evalpipe(union node *, int);
8791 static int evalcommand(union node *, int);
8792 static int evalbltin(const struct builtincmd *, int, char **, int);
8793 static void prehash(union node *);
8794
8795 /*
8796  * Evaluate a parse tree.  The value is left in the global variable
8797  * exitstatus.
8798  */
8799 static int
8800 evaltree(union node *n, int flags)
8801 {
8802         int checkexit = 0;
8803         int (*evalfn)(union node *, int);
8804         int status = 0;
8805
8806         if (n == NULL) {
8807                 TRACE(("evaltree(NULL) called\n"));
8808                 goto out;
8809         }
8810         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8811
8812         dotrap();
8813
8814         switch (n->type) {
8815         default:
8816 #if DEBUG
8817                 out1fmt("Node type = %d\n", n->type);
8818                 fflush_all();
8819                 break;
8820 #endif
8821         case NNOT:
8822                 status = !evaltree(n->nnot.com, EV_TESTED);
8823                 goto setstatus;
8824         case NREDIR:
8825                 expredir(n->nredir.redirect);
8826                 pushredir(n->nredir.redirect);
8827                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8828                 if (!status) {
8829                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8830                 }
8831                 if (n->nredir.redirect)
8832                         popredir(/*drop:*/ 0);
8833                 goto setstatus;
8834         case NCMD:
8835                 evalfn = evalcommand;
8836  checkexit:
8837                 if (eflag && !(flags & EV_TESTED))
8838                         checkexit = ~0;
8839                 goto calleval;
8840         case NFOR:
8841                 evalfn = evalfor;
8842                 goto calleval;
8843         case NWHILE:
8844         case NUNTIL:
8845                 evalfn = evalloop;
8846                 goto calleval;
8847         case NSUBSHELL:
8848         case NBACKGND:
8849                 evalfn = evalsubshell;
8850                 goto checkexit;
8851         case NPIPE:
8852                 evalfn = evalpipe;
8853                 goto checkexit;
8854         case NCASE:
8855                 evalfn = evalcase;
8856                 goto calleval;
8857         case NAND:
8858         case NOR:
8859         case NSEMI: {
8860
8861 #if NAND + 1 != NOR
8862 #error NAND + 1 != NOR
8863 #endif
8864 #if NOR + 1 != NSEMI
8865 #error NOR + 1 != NSEMI
8866 #endif
8867                 unsigned is_or = n->type - NAND;
8868                 status = evaltree(
8869                         n->nbinary.ch1,
8870                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8871                 );
8872                 if ((!status) == is_or || evalskip)
8873                         break;
8874                 n = n->nbinary.ch2;
8875  evaln:
8876                 evalfn = evaltree;
8877  calleval:
8878                 status = evalfn(n, flags);
8879                 goto setstatus;
8880         }
8881         case NIF:
8882                 status = evaltree(n->nif.test, EV_TESTED);
8883                 if (evalskip)
8884                         break;
8885                 if (!status) {
8886                         n = n->nif.ifpart;
8887                         goto evaln;
8888                 }
8889                 if (n->nif.elsepart) {
8890                         n = n->nif.elsepart;
8891                         goto evaln;
8892                 }
8893                 status = 0;
8894                 goto setstatus;
8895         case NDEFUN:
8896                 defun(n);
8897                 /* Not necessary. To test it:
8898                  * "false; f() { qwerty; }; echo $?" should print 0.
8899                  */
8900                 /* status = 0; */
8901  setstatus:
8902                 exitstatus = status;
8903                 break;
8904         }
8905  out:
8906         /* Order of checks below is important:
8907          * signal handlers trigger before exit caused by "set -e".
8908          */
8909         dotrap();
8910
8911         if (checkexit & status)
8912                 raise_exception(EXEXIT);
8913         if (flags & EV_EXIT)
8914                 raise_exception(EXEXIT);
8915
8916         TRACE(("leaving evaltree (no interrupts)\n"));
8917         return exitstatus;
8918 }
8919
8920 static int
8921 skiploop(void)
8922 {
8923         int skip = evalskip;
8924
8925         switch (skip) {
8926         case 0:
8927                 break;
8928         case SKIPBREAK:
8929         case SKIPCONT:
8930                 if (--skipcount <= 0) {
8931                         evalskip = 0;
8932                         break;
8933                 }
8934                 skip = SKIPBREAK;
8935                 break;
8936         }
8937         return skip;
8938 }
8939
8940 static int
8941 evalloop(union node *n, int flags)
8942 {
8943         int skip;
8944         int status;
8945
8946         loopnest++;
8947         status = 0;
8948         flags &= EV_TESTED;
8949         do {
8950                 int i;
8951
8952                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8953                 skip = skiploop();
8954                 if (skip == SKIPFUNC)
8955                         status = i;
8956                 if (skip)
8957                         continue;
8958                 if (n->type != NWHILE)
8959                         i = !i;
8960                 if (i != 0)
8961                         break;
8962                 status = evaltree(n->nbinary.ch2, flags);
8963                 skip = skiploop();
8964         } while (!(skip & ~SKIPCONT));
8965         loopnest--;
8966
8967         return status;
8968 }
8969
8970 static int
8971 evalfor(union node *n, int flags)
8972 {
8973         struct arglist arglist;
8974         union node *argp;
8975         struct strlist *sp;
8976         struct stackmark smark;
8977         int status = 0;
8978
8979         setstackmark(&smark);
8980         arglist.list = NULL;
8981         arglist.lastp = &arglist.list;
8982         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8983                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8984         }
8985         *arglist.lastp = NULL;
8986
8987         loopnest++;
8988         flags &= EV_TESTED;
8989         for (sp = arglist.list; sp; sp = sp->next) {
8990                 setvar0(n->nfor.var, sp->text);
8991                 status = evaltree(n->nfor.body, flags);
8992                 if (skiploop() & ~SKIPCONT)
8993                         break;
8994         }
8995         loopnest--;
8996         popstackmark(&smark);
8997
8998         return status;
8999 }
9000
9001 static int
9002 evalcase(union node *n, int flags)
9003 {
9004         union node *cp;
9005         union node *patp;
9006         struct arglist arglist;
9007         struct stackmark smark;
9008         int status = 0;
9009
9010         setstackmark(&smark);
9011         arglist.list = NULL;
9012         arglist.lastp = &arglist.list;
9013         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9014         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9015                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9016                         if (casematch(patp, arglist.list->text)) {
9017                                 /* Ensure body is non-empty as otherwise
9018                                  * EV_EXIT may prevent us from setting the
9019                                  * exit status.
9020                                  */
9021                                 if (evalskip == 0 && cp->nclist.body) {
9022                                         status = evaltree(cp->nclist.body, flags);
9023                                 }
9024                                 goto out;
9025                         }
9026                 }
9027         }
9028  out:
9029         popstackmark(&smark);
9030
9031         return status;
9032 }
9033
9034 /*
9035  * Kick off a subshell to evaluate a tree.
9036  */
9037 static int
9038 evalsubshell(union node *n, int flags)
9039 {
9040         struct job *jp;
9041         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9042         int status;
9043
9044         expredir(n->nredir.redirect);
9045         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9046                 goto nofork;
9047         INT_OFF;
9048         if (backgnd == FORK_FG)
9049                 get_tty_state();
9050         jp = makejob(/*n,*/ 1);
9051         if (forkshell(jp, n, backgnd) == 0) {
9052                 /* child */
9053                 INT_ON;
9054                 flags |= EV_EXIT;
9055                 if (backgnd)
9056                         flags &= ~EV_TESTED;
9057  nofork:
9058                 redirect(n->nredir.redirect, 0);
9059                 evaltreenr(n->nredir.n, flags);
9060                 /* never returns */
9061         }
9062         /* parent */
9063         status = 0;
9064         if (backgnd == FORK_FG)
9065                 status = waitforjob(jp);
9066         INT_ON;
9067         return status;
9068 }
9069
9070 /*
9071  * Compute the names of the files in a redirection list.
9072  */
9073 static void fixredir(union node *, const char *, int);
9074 static void
9075 expredir(union node *n)
9076 {
9077         union node *redir;
9078
9079         for (redir = n; redir; redir = redir->nfile.next) {
9080                 struct arglist fn;
9081
9082                 fn.list = NULL;
9083                 fn.lastp = &fn.list;
9084                 switch (redir->type) {
9085                 case NFROMTO:
9086                 case NFROM:
9087                 case NTO:
9088 #if BASH_REDIR_OUTPUT
9089                 case NTO2:
9090 #endif
9091                 case NCLOBBER:
9092                 case NAPPEND:
9093                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9094                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9095 #if BASH_REDIR_OUTPUT
9096  store_expfname:
9097 #endif
9098 #if 0
9099 // By the design of stack allocator, the loop of this kind:
9100 //      while true; do while true; do break; done </dev/null; done
9101 // will look like a memory leak: ash plans to free expfname's
9102 // of "/dev/null" as soon as it finishes running the loop
9103 // (in this case, never).
9104 // This "fix" is wrong:
9105                         if (redir->nfile.expfname)
9106                                 stunalloc(redir->nfile.expfname);
9107 // It results in corrupted state of stacked allocations.
9108 #endif
9109                         redir->nfile.expfname = fn.list->text;
9110                         break;
9111                 case NFROMFD:
9112                 case NTOFD: /* >& */
9113                         if (redir->ndup.vname) {
9114                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9115                                 if (fn.list == NULL)
9116                                         ash_msg_and_raise_error("redir error");
9117 #if BASH_REDIR_OUTPUT
9118 //FIXME: we used expandarg with different args!
9119                                 if (!isdigit_str9(fn.list->text)) {
9120                                         /* >&file, not >&fd */
9121                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9122                                                 ash_msg_and_raise_error("redir error");
9123                                         redir->type = NTO2;
9124                                         goto store_expfname;
9125                                 }
9126 #endif
9127                                 fixredir(redir, fn.list->text, 1);
9128                         }
9129                         break;
9130                 }
9131         }
9132 }
9133
9134 /*
9135  * Evaluate a pipeline.  All the processes in the pipeline are children
9136  * of the process creating the pipeline.  (This differs from some versions
9137  * of the shell, which make the last process in a pipeline the parent
9138  * of all the rest.)
9139  */
9140 static int
9141 evalpipe(union node *n, int flags)
9142 {
9143         struct job *jp;
9144         struct nodelist *lp;
9145         int pipelen;
9146         int prevfd;
9147         int pip[2];
9148         int status = 0;
9149
9150         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9151         pipelen = 0;
9152         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9153                 pipelen++;
9154         flags |= EV_EXIT;
9155         INT_OFF;
9156         if (n->npipe.pipe_backgnd == 0)
9157                 get_tty_state();
9158         jp = makejob(/*n,*/ pipelen);
9159         prevfd = -1;
9160         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9161                 prehash(lp->n);
9162                 pip[1] = -1;
9163                 if (lp->next) {
9164                         if (pipe(pip) < 0) {
9165                                 close(prevfd);
9166                                 ash_msg_and_raise_error("pipe call failed");
9167                         }
9168                 }
9169                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9170                         /* child */
9171                         INT_ON;
9172                         if (pip[1] >= 0) {
9173                                 close(pip[0]);
9174                         }
9175                         if (prevfd > 0) {
9176                                 dup2(prevfd, 0);
9177                                 close(prevfd);
9178                         }
9179                         if (pip[1] > 1) {
9180                                 dup2(pip[1], 1);
9181                                 close(pip[1]);
9182                         }
9183                         evaltreenr(lp->n, flags);
9184                         /* never returns */
9185                 }
9186                 /* parent */
9187                 if (prevfd >= 0)
9188                         close(prevfd);
9189                 prevfd = pip[0];
9190                 /* Don't want to trigger debugging */
9191                 if (pip[1] != -1)
9192                         close(pip[1]);
9193         }
9194         if (n->npipe.pipe_backgnd == 0) {
9195                 status = waitforjob(jp);
9196                 TRACE(("evalpipe:  job done exit status %d\n", status));
9197         }
9198         INT_ON;
9199
9200         return status;
9201 }
9202
9203 /*
9204  * Controls whether the shell is interactive or not.
9205  */
9206 static void
9207 setinteractive(int on)
9208 {
9209         static smallint is_interactive;
9210
9211         if (++on == is_interactive)
9212                 return;
9213         is_interactive = on;
9214         setsignal(SIGINT);
9215         setsignal(SIGQUIT);
9216         setsignal(SIGTERM);
9217 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9218         if (is_interactive > 1) {
9219                 /* Looks like they want an interactive shell */
9220                 static smallint did_banner;
9221
9222                 if (!did_banner) {
9223                         /* note: ash and hush share this string */
9224                         out1fmt("\n\n%s %s\n"
9225                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9226                                 "\n",
9227                                 bb_banner,
9228                                 "built-in shell (ash)"
9229                         );
9230                         did_banner = 1;
9231                 }
9232         }
9233 #endif
9234 }
9235
9236 static void
9237 optschanged(void)
9238 {
9239 #if DEBUG
9240         opentrace();
9241 #endif
9242         setinteractive(iflag);
9243         setjobctl(mflag);
9244 #if ENABLE_FEATURE_EDITING_VI
9245         if (viflag)
9246                 line_input_state->flags |= VI_MODE;
9247         else
9248                 line_input_state->flags &= ~VI_MODE;
9249 #else
9250         viflag = 0; /* forcibly keep the option off */
9251 #endif
9252 }
9253
9254 struct localvar_list {
9255         struct localvar_list *next;
9256         struct localvar *lv;
9257 };
9258
9259 static struct localvar_list *localvar_stack;
9260
9261 /*
9262  * Called after a function returns.
9263  * Interrupts must be off.
9264  */
9265 static void
9266 poplocalvars(int keep)
9267 {
9268         struct localvar_list *ll;
9269         struct localvar *lvp, *next;
9270         struct var *vp;
9271
9272         INT_OFF;
9273         ll = localvar_stack;
9274         localvar_stack = ll->next;
9275
9276         next = ll->lv;
9277         free(ll);
9278
9279         while ((lvp = next) != NULL) {
9280                 next = lvp->next;
9281                 vp = lvp->vp;
9282                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9283                 if (keep) {
9284                         int bits = VSTRFIXED;
9285
9286                         if (lvp->flags != VUNSET) {
9287                                 if (vp->var_text == lvp->text)
9288                                         bits |= VTEXTFIXED;
9289                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9290                                         free((char*)lvp->text);
9291                         }
9292
9293                         vp->flags &= ~bits;
9294                         vp->flags |= (lvp->flags & bits);
9295
9296                         if ((vp->flags &
9297                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9298                                 unsetvar(vp->var_text);
9299                 } else if (vp == NULL) {        /* $- saved */
9300                         memcpy(optlist, lvp->text, sizeof(optlist));
9301                         free((char*)lvp->text);
9302                         optschanged();
9303                 } else if (lvp->flags == VUNSET) {
9304                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9305                         unsetvar(vp->var_text);
9306                 } else {
9307                         if (vp->var_func)
9308                                 vp->var_func(var_end(lvp->text));
9309                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9310                                 free((char*)vp->var_text);
9311                         vp->flags = lvp->flags;
9312                         vp->var_text = lvp->text;
9313                 }
9314                 free(lvp);
9315         }
9316         INT_ON;
9317 }
9318
9319 /*
9320  * Create a new localvar environment.
9321  */
9322 static struct localvar_list *
9323 pushlocalvars(void)
9324 {
9325         struct localvar_list *ll;
9326
9327         INT_OFF;
9328         ll = ckzalloc(sizeof(*ll));
9329         /*ll->lv = NULL; - zalloc did it */
9330         ll->next = localvar_stack;
9331         localvar_stack = ll;
9332         INT_ON;
9333
9334         return ll->next;
9335 }
9336
9337 static void
9338 unwindlocalvars(struct localvar_list *stop)
9339 {
9340         while (localvar_stack != stop)
9341                 poplocalvars(0);
9342 }
9343
9344 static int
9345 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9346 {
9347         volatile struct shparam saveparam;
9348         struct jmploc *volatile savehandler;
9349         struct jmploc jmploc;
9350         int e;
9351
9352         saveparam = shellparam;
9353         savehandler = exception_handler;
9354         e = setjmp(jmploc.loc);
9355         if (e) {
9356                 goto funcdone;
9357         }
9358         INT_OFF;
9359         exception_handler = &jmploc;
9360         shellparam.malloced = 0;
9361         func->count++;
9362         funcnest++;
9363         INT_ON;
9364         shellparam.nparam = argc - 1;
9365         shellparam.p = argv + 1;
9366 #if ENABLE_ASH_GETOPTS
9367         shellparam.optind = 1;
9368         shellparam.optoff = -1;
9369 #endif
9370         pushlocalvars();
9371         evaltree(func->n.narg.next, flags & EV_TESTED);
9372         poplocalvars(0);
9373  funcdone:
9374         INT_OFF;
9375         funcnest--;
9376         freefunc(func);
9377         freeparam(&shellparam);
9378         shellparam = saveparam;
9379         exception_handler = savehandler;
9380         INT_ON;
9381         evalskip &= ~SKIPFUNC;
9382         return e;
9383 }
9384
9385 /*
9386  * Make a variable a local variable.  When a variable is made local, it's
9387  * value and flags are saved in a localvar structure.  The saved values
9388  * will be restored when the shell function returns.  We handle the name
9389  * "-" as a special case: it makes changes to "set +-options" local
9390  * (options will be restored on return from the function).
9391  */
9392 static void
9393 mklocal(char *name)
9394 {
9395         struct localvar *lvp;
9396         struct var **vpp;
9397         struct var *vp;
9398         char *eq = strchr(name, '=');
9399
9400         INT_OFF;
9401         /* Cater for duplicate "local". Examples:
9402          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9403          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9404          */
9405         lvp = localvar_stack->lv;
9406         while (lvp) {
9407                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9408                         if (eq)
9409                                 setvareq(name, 0);
9410                         /* else:
9411                          * it's a duplicate "local VAR" declaration, do nothing
9412                          */
9413                         goto ret;
9414                 }
9415                 lvp = lvp->next;
9416         }
9417
9418         lvp = ckzalloc(sizeof(*lvp));
9419         if (LONE_DASH(name)) {
9420                 char *p;
9421                 p = ckmalloc(sizeof(optlist));
9422                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9423                 vp = NULL;
9424         } else {
9425                 vpp = hashvar(name);
9426                 vp = *findvar(vpp, name);
9427                 if (vp == NULL) {
9428                         /* variable did not exist yet */
9429                         if (eq)
9430                                 vp = setvareq(name, VSTRFIXED);
9431                         else
9432                                 vp = setvar(name, NULL, VSTRFIXED);
9433                         lvp->flags = VUNSET;
9434                 } else {
9435                         lvp->text = vp->var_text;
9436                         lvp->flags = vp->flags;
9437                         /* make sure neither "struct var" nor string gets freed
9438                          * during (un)setting:
9439                          */
9440                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9441                         if (eq)
9442                                 setvareq(name, 0);
9443                         else
9444                                 /* "local VAR" unsets VAR: */
9445                                 setvar0(name, NULL);
9446                 }
9447         }
9448         lvp->vp = vp;
9449         lvp->next = localvar_stack->lv;
9450         localvar_stack->lv = lvp;
9451  ret:
9452         INT_ON;
9453 }
9454
9455 /*
9456  * The "local" command.
9457  */
9458 static int FAST_FUNC
9459 localcmd(int argc UNUSED_PARAM, char **argv)
9460 {
9461         char *name;
9462
9463         if (!localvar_stack)
9464                 ash_msg_and_raise_error("not in a function");
9465
9466         argv = argptr;
9467         while ((name = *argv++) != NULL) {
9468                 mklocal(name);
9469         }
9470         return 0;
9471 }
9472
9473 static int FAST_FUNC
9474 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9475 {
9476         return 1;
9477 }
9478
9479 static int FAST_FUNC
9480 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9481 {
9482         return 0;
9483 }
9484
9485 static int FAST_FUNC
9486 execcmd(int argc UNUSED_PARAM, char **argv)
9487 {
9488         optionarg = NULL;
9489         while (nextopt("a:") != '\0')
9490                 /* nextopt() sets optionarg to "-a ARGV0" */;
9491
9492         argv = argptr;
9493         if (argv[0]) {
9494                 char *prog;
9495
9496                 iflag = 0;              /* exit on error */
9497                 mflag = 0;
9498                 optschanged();
9499                 /* We should set up signals for "exec CMD"
9500                  * the same way as for "CMD" without "exec".
9501                  * But optschanged->setinteractive->setsignal
9502                  * still thought we are a root shell. Therefore, for example,
9503                  * SIGQUIT is still set to IGN. Fix it:
9504                  */
9505                 shlvl++;
9506                 setsignal(SIGQUIT);
9507                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9508                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9509                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9510
9511                 prog = argv[0];
9512                 if (optionarg)
9513                         argv[0] = optionarg;
9514                 shellexec(prog, argv, pathval(), 0);
9515                 /* NOTREACHED */
9516         }
9517         return 0;
9518 }
9519
9520 /*
9521  * The return command.
9522  */
9523 static int FAST_FUNC
9524 returncmd(int argc UNUSED_PARAM, char **argv)
9525 {
9526         /*
9527          * If called outside a function, do what ksh does;
9528          * skip the rest of the file.
9529          */
9530         evalskip = SKIPFUNC;
9531         return argv[1] ? number(argv[1]) : exitstatus;
9532 }
9533
9534 /* Forward declarations for builtintab[] */
9535 static int breakcmd(int, char **) FAST_FUNC;
9536 static int dotcmd(int, char **) FAST_FUNC;
9537 static int evalcmd(int, char **, int) FAST_FUNC;
9538 static int exitcmd(int, char **) FAST_FUNC;
9539 static int exportcmd(int, char **) FAST_FUNC;
9540 #if ENABLE_ASH_GETOPTS
9541 static int getoptscmd(int, char **) FAST_FUNC;
9542 #endif
9543 #if ENABLE_ASH_HELP
9544 static int helpcmd(int, char **) FAST_FUNC;
9545 #endif
9546 #if MAX_HISTORY
9547 static int historycmd(int, char **) FAST_FUNC;
9548 #endif
9549 #if ENABLE_FEATURE_SH_MATH
9550 static int letcmd(int, char **) FAST_FUNC;
9551 #endif
9552 static int readcmd(int, char **) FAST_FUNC;
9553 static int setcmd(int, char **) FAST_FUNC;
9554 static int shiftcmd(int, char **) FAST_FUNC;
9555 static int timescmd(int, char **) FAST_FUNC;
9556 static int trapcmd(int, char **) FAST_FUNC;
9557 static int umaskcmd(int, char **) FAST_FUNC;
9558 static int unsetcmd(int, char **) FAST_FUNC;
9559 static int ulimitcmd(int, char **) FAST_FUNC;
9560
9561 #define BUILTIN_NOSPEC          "0"
9562 #define BUILTIN_SPECIAL         "1"
9563 #define BUILTIN_REGULAR         "2"
9564 #define BUILTIN_SPEC_REG        "3"
9565 #define BUILTIN_ASSIGN          "4"
9566 #define BUILTIN_SPEC_ASSG       "5"
9567 #define BUILTIN_REG_ASSG        "6"
9568 #define BUILTIN_SPEC_REG_ASSG   "7"
9569
9570 /* Stubs for calling non-FAST_FUNC's */
9571 #if ENABLE_ASH_ECHO
9572 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9573 #endif
9574 #if ENABLE_ASH_PRINTF
9575 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9576 #endif
9577 #if ENABLE_ASH_TEST || BASH_TEST2
9578 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9579 #endif
9580
9581 /* Keep these in proper order since it is searched via bsearch() */
9582 static const struct builtincmd builtintab[] = {
9583         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9584         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9585 #if ENABLE_ASH_TEST
9586         { BUILTIN_REGULAR       "["       , testcmd    },
9587 #endif
9588 #if BASH_TEST2
9589         { BUILTIN_REGULAR       "[["      , testcmd    },
9590 #endif
9591 #if ENABLE_ASH_ALIAS
9592         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9593 #endif
9594 #if JOBS
9595         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9596 #endif
9597         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9598         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9599         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9600 #if ENABLE_ASH_CMDCMD
9601         { BUILTIN_REGULAR       "command" , commandcmd },
9602 #endif
9603         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9604 #if ENABLE_ASH_ECHO
9605         { BUILTIN_REGULAR       "echo"    , echocmd    },
9606 #endif
9607         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9608         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9609         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9610         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9611         { BUILTIN_REGULAR       "false"   , falsecmd   },
9612 #if JOBS
9613         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9614 #endif
9615 #if ENABLE_ASH_GETOPTS
9616         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9617 #endif
9618         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9619 #if ENABLE_ASH_HELP
9620         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9621 #endif
9622 #if MAX_HISTORY
9623         { BUILTIN_NOSPEC        "history" , historycmd },
9624 #endif
9625 #if JOBS
9626         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9627         { BUILTIN_REGULAR       "kill"    , killcmd    },
9628 #endif
9629 #if ENABLE_FEATURE_SH_MATH
9630         { BUILTIN_NOSPEC        "let"     , letcmd     },
9631 #endif
9632         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9633 #if ENABLE_ASH_PRINTF
9634         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9635 #endif
9636         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9637         { BUILTIN_REGULAR       "read"    , readcmd    },
9638         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9639         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9640         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9641         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9642 #if BASH_SOURCE
9643         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9644 #endif
9645 #if ENABLE_ASH_TEST
9646         { BUILTIN_REGULAR       "test"    , testcmd    },
9647 #endif
9648         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9649         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9650         { BUILTIN_REGULAR       "true"    , truecmd    },
9651         { BUILTIN_NOSPEC        "type"    , typecmd    },
9652         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9653         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9654 #if ENABLE_ASH_ALIAS
9655         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9656 #endif
9657         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9658         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9659 };
9660
9661 /* Should match the above table! */
9662 #define COMMANDCMD (builtintab + \
9663         /* . : */       2 + \
9664         /* [ */         1 * ENABLE_ASH_TEST + \
9665         /* [[ */        1 * BASH_TEST2 + \
9666         /* alias */     1 * ENABLE_ASH_ALIAS + \
9667         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9668         /* break cd cddir  */   3)
9669 #define EVALCMD (COMMANDCMD + \
9670         /* command */   1 * ENABLE_ASH_CMDCMD + \
9671         /* continue */  1 + \
9672         /* echo */      1 * ENABLE_ASH_ECHO + \
9673         0)
9674 #define EXECCMD (EVALCMD + \
9675         /* eval */      1)
9676
9677 /*
9678  * Search the table of builtin commands.
9679  */
9680 static int
9681 pstrcmp1(const void *a, const void *b)
9682 {
9683         return strcmp((char*)a, *(char**)b + 1);
9684 }
9685 static struct builtincmd *
9686 find_builtin(const char *name)
9687 {
9688         struct builtincmd *bp;
9689
9690         bp = bsearch(
9691                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9692                 pstrcmp1
9693         );
9694         return bp;
9695 }
9696
9697 /*
9698  * Execute a simple command.
9699  */
9700 static int
9701 isassignment(const char *p)
9702 {
9703         const char *q = endofname(p);
9704         if (p == q)
9705                 return 0;
9706         return *q == '=';
9707 }
9708 static int FAST_FUNC
9709 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9710 {
9711         /* Preserve exitstatus of a previous possible redirection
9712          * as POSIX mandates */
9713         return back_exitstatus;
9714 }
9715 static int
9716 evalcommand(union node *cmd, int flags)
9717 {
9718         static const struct builtincmd null_bltin = {
9719                 "\0\0", bltincmd /* why three NULs? */
9720         };
9721         struct localvar_list *localvar_stop;
9722         struct redirtab *redir_stop;
9723         struct stackmark smark;
9724         union node *argp;
9725         struct arglist arglist;
9726         struct arglist varlist;
9727         char **argv;
9728         int argc;
9729         const struct strlist *sp;
9730         struct cmdentry cmdentry;
9731         struct job *jp;
9732         char *lastarg;
9733         const char *path;
9734         int spclbltin;
9735         int status;
9736         char **nargv;
9737         smallint cmd_is_exec;
9738
9739         /* First expand the arguments. */
9740         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9741         setstackmark(&smark);
9742         localvar_stop = pushlocalvars();
9743         back_exitstatus = 0;
9744
9745         cmdentry.cmdtype = CMDBUILTIN;
9746         cmdentry.u.cmd = &null_bltin;
9747         varlist.lastp = &varlist.list;
9748         *varlist.lastp = NULL;
9749         arglist.lastp = &arglist.list;
9750         *arglist.lastp = NULL;
9751
9752         argc = 0;
9753         if (cmd->ncmd.args) {
9754                 struct builtincmd *bcmd;
9755                 smallint pseudovarflag;
9756
9757                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9758                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9759
9760                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9761                         struct strlist **spp;
9762
9763                         spp = arglist.lastp;
9764                         if (pseudovarflag && isassignment(argp->narg.text))
9765                                 expandarg(argp, &arglist, EXP_VARTILDE);
9766                         else
9767                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9768
9769                         for (sp = *spp; sp; sp = sp->next)
9770                                 argc++;
9771                 }
9772         }
9773
9774         /* Reserve one extra spot at the front for shellexec. */
9775         nargv = stalloc(sizeof(char *) * (argc + 2));
9776         argv = ++nargv;
9777         for (sp = arglist.list; sp; sp = sp->next) {
9778                 TRACE(("evalcommand arg: %s\n", sp->text));
9779                 *nargv++ = sp->text;
9780         }
9781         *nargv = NULL;
9782
9783         lastarg = NULL;
9784         if (iflag && funcnest == 0 && argc > 0)
9785                 lastarg = nargv[-1];
9786
9787         expredir(cmd->ncmd.redirect);
9788         redir_stop = pushredir(cmd->ncmd.redirect);
9789         preverrout_fd = 2;
9790         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9791
9792         path = vpath.var_text;
9793         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9794                 struct strlist **spp;
9795                 char *p;
9796
9797                 spp = varlist.lastp;
9798                 expandarg(argp, &varlist, EXP_VARTILDE);
9799
9800                 mklocal((*spp)->text);
9801
9802                 /*
9803                  * Modify the command lookup path, if a PATH= assignment
9804                  * is present
9805                  */
9806                 p = (*spp)->text;
9807                 if (varcmp(p, path) == 0)
9808                         path = p;
9809         }
9810
9811         /* Print the command if xflag is set. */
9812         if (xflag) {
9813                 const char *pfx = "";
9814
9815                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9816
9817                 sp = varlist.list;
9818                 while (sp) {
9819                         char *varval = sp->text;
9820                         char *eq = strchrnul(varval, '=');
9821                         if (*eq)
9822                                 eq++;
9823                         fdprintf(preverrout_fd, "%s%.*s%s",
9824                                 pfx,
9825                                 (int)(eq - varval), varval,
9826                                 maybe_single_quote(eq)
9827                         );
9828                         sp = sp->next;
9829                         pfx = " ";
9830                 }
9831
9832                 sp = arglist.list;
9833                 while (sp) {
9834                         fdprintf(preverrout_fd, "%s%s",
9835                                 pfx,
9836                                 /* always quote if matches reserved word: */
9837                                 findkwd(sp->text)
9838                                 ? single_quote(sp->text)
9839                                 : maybe_single_quote(sp->text)
9840                         );
9841                         sp = sp->next;
9842                         pfx = " ";
9843                 }
9844                 safe_write(preverrout_fd, "\n", 1);
9845         }
9846
9847         cmd_is_exec = 0;
9848         spclbltin = -1;
9849
9850         /* Now locate the command. */
9851         if (argc) {
9852                 int cmd_flag = DO_ERR;
9853 #if ENABLE_ASH_CMDCMD
9854                 const char *oldpath = path + 5;
9855 #endif
9856                 path += 5;
9857                 for (;;) {
9858                         find_command(argv[0], &cmdentry, cmd_flag, path);
9859                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9860                                 flush_stdout_stderr();
9861                                 status = 127;
9862                                 goto bail;
9863                         }
9864
9865                         /* implement bltin and command here */
9866                         if (cmdentry.cmdtype != CMDBUILTIN)
9867                                 break;
9868                         if (spclbltin < 0)
9869                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9870                         if (cmdentry.u.cmd == EXECCMD)
9871                                 cmd_is_exec = 1;
9872 #if ENABLE_ASH_CMDCMD
9873                         if (cmdentry.u.cmd == COMMANDCMD) {
9874                                 path = oldpath;
9875                                 nargv = parse_command_args(argv, &path);
9876                                 if (!nargv)
9877                                         break;
9878                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9879                                  * nargv => "PROG". path is updated if -p.
9880                                  */
9881                                 argc -= nargv - argv;
9882                                 argv = nargv;
9883                                 cmd_flag |= DO_NOFUNC;
9884                         } else
9885 #endif
9886                                 break;
9887                 }
9888         }
9889
9890         if (status) {
9891  bail:
9892                 exitstatus = status;
9893
9894                 /* We have a redirection error. */
9895                 if (spclbltin > 0)
9896                         raise_exception(EXERROR);
9897
9898                 goto out;
9899         }
9900
9901         /* Execute the command. */
9902         switch (cmdentry.cmdtype) {
9903         default: {
9904
9905 #if ENABLE_FEATURE_SH_NOFORK
9906 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9907  *     around run_nofork_applet() call.
9908  * (2) Should this check also be done in forkshell()?
9909  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9910  */
9911                 /* find_command() encodes applet_no as (-2 - applet_no) */
9912                 int applet_no = (- cmdentry.u.index - 2);
9913                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9914                         listsetvar(varlist.list, VEXPORT|VSTACK);
9915                         /* run <applet>_main() */
9916                         status = run_nofork_applet(applet_no, argv);
9917                         break;
9918                 }
9919 #endif
9920                 /* Can we avoid forking off? For example, very last command
9921                  * in a script or a subshell does not need forking,
9922                  * we can just exec it.
9923                  */
9924                 if (!(flags & EV_EXIT) || may_have_traps) {
9925                         /* No, forking off a child is necessary */
9926                         INT_OFF;
9927                         get_tty_state();
9928                         jp = makejob(/*cmd,*/ 1);
9929                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9930                                 /* parent */
9931                                 status = waitforjob(jp);
9932                                 INT_ON;
9933                                 TRACE(("forked child exited with %d\n", status));
9934                                 break;
9935                         }
9936                         /* child */
9937                         FORCE_INT_ON;
9938                         /* fall through to exec'ing external program */
9939                 }
9940                 listsetvar(varlist.list, VEXPORT|VSTACK);
9941                 shellexec(argv[0], argv, path, cmdentry.u.index);
9942                 /* NOTREACHED */
9943         } /* default */
9944         case CMDBUILTIN:
9945                 if (spclbltin > 0 || argc == 0) {
9946                         poplocalvars(1);
9947                         if (cmd_is_exec && argc > 1)
9948                                 listsetvar(varlist.list, VEXPORT);
9949                 }
9950
9951                 /* Tight loop with builtins only:
9952                  * "while kill -0 $child; do true; done"
9953                  * will never exit even if $child died, unless we do this
9954                  * to reap the zombie and make kill detect that it's gone: */
9955                 dowait(DOWAIT_NONBLOCK, NULL);
9956
9957                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9958                         if (exception_type == EXERROR && spclbltin <= 0) {
9959                                 FORCE_INT_ON;
9960                                 goto readstatus;
9961                         }
9962  raise:
9963                         longjmp(exception_handler->loc, 1);
9964                 }
9965                 goto readstatus;
9966
9967         case CMDFUNCTION:
9968                 poplocalvars(1);
9969                 /* See above for the rationale */
9970                 dowait(DOWAIT_NONBLOCK, NULL);
9971                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9972                         goto raise;
9973  readstatus:
9974                 status = exitstatus;
9975                 break;
9976         } /* switch */
9977
9978  out:
9979         if (cmd->ncmd.redirect)
9980                 popredir(/*drop:*/ cmd_is_exec);
9981         unwindredir(redir_stop);
9982         unwindlocalvars(localvar_stop);
9983         if (lastarg) {
9984                 /* dsl: I think this is intended to be used to support
9985                  * '_' in 'vi' command mode during line editing...
9986                  * However I implemented that within libedit itself.
9987                  */
9988                 setvar0("_", lastarg);
9989         }
9990         popstackmark(&smark);
9991
9992         return status;
9993 }
9994
9995 static int
9996 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9997 {
9998         char *volatile savecmdname;
9999         struct jmploc *volatile savehandler;
10000         struct jmploc jmploc;
10001         int status;
10002         int i;
10003
10004         savecmdname = commandname;
10005         savehandler = exception_handler;
10006         i = setjmp(jmploc.loc);
10007         if (i)
10008                 goto cmddone;
10009         exception_handler = &jmploc;
10010         commandname = argv[0];
10011         argptr = argv + 1;
10012         optptr = NULL;                  /* initialize nextopt */
10013         if (cmd == EVALCMD)
10014                 status = evalcmd(argc, argv, flags);
10015         else
10016                 status = (*cmd->builtin)(argc, argv);
10017         flush_stdout_stderr();
10018         status |= ferror(stdout);
10019         exitstatus = status;
10020  cmddone:
10021         clearerr(stdout);
10022         commandname = savecmdname;
10023         exception_handler = savehandler;
10024
10025         return i;
10026 }
10027
10028 static int
10029 goodname(const char *p)
10030 {
10031         return endofname(p)[0] == '\0';
10032 }
10033
10034
10035 /*
10036  * Search for a command.  This is called before we fork so that the
10037  * location of the command will be available in the parent as well as
10038  * the child.  The check for "goodname" is an overly conservative
10039  * check that the name will not be subject to expansion.
10040  */
10041 static void
10042 prehash(union node *n)
10043 {
10044         struct cmdentry entry;
10045
10046         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10047                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10048 }
10049
10050
10051 /* ============ Builtin commands
10052  *
10053  * Builtin commands whose functions are closely tied to evaluation
10054  * are implemented here.
10055  */
10056
10057 /*
10058  * Handle break and continue commands.  Break, continue, and return are
10059  * all handled by setting the evalskip flag.  The evaluation routines
10060  * above all check this flag, and if it is set they start skipping
10061  * commands rather than executing them.  The variable skipcount is
10062  * the number of loops to break/continue, or the number of function
10063  * levels to return.  (The latter is always 1.)  It should probably
10064  * be an error to break out of more loops than exist, but it isn't
10065  * in the standard shell so we don't make it one here.
10066  */
10067 static int FAST_FUNC
10068 breakcmd(int argc UNUSED_PARAM, char **argv)
10069 {
10070         int n = argv[1] ? number(argv[1]) : 1;
10071
10072         if (n <= 0)
10073                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10074         if (n > loopnest)
10075                 n = loopnest;
10076         if (n > 0) {
10077                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10078                 skipcount = n;
10079         }
10080         return 0;
10081 }
10082
10083
10084 /*
10085  * This implements the input routines used by the parser.
10086  */
10087
10088 enum {
10089         INPUT_PUSH_FILE = 1,
10090         INPUT_NOFILE_OK = 2,
10091 };
10092
10093 static smallint checkkwd;
10094 /* values of checkkwd variable */
10095 #define CHKALIAS        0x1
10096 #define CHKKWD          0x2
10097 #define CHKNL           0x4
10098 #define CHKEOFMARK      0x8
10099
10100 /*
10101  * Push a string back onto the input at this current parsefile level.
10102  * We handle aliases this way.
10103  */
10104 #if !ENABLE_ASH_ALIAS
10105 #define pushstring(s, ap) pushstring(s)
10106 #endif
10107 static void
10108 pushstring(char *s, struct alias *ap)
10109 {
10110         struct strpush *sp;
10111         int len;
10112
10113         len = strlen(s);
10114         INT_OFF;
10115         if (g_parsefile->strpush) {
10116                 sp = ckzalloc(sizeof(*sp));
10117                 sp->prev = g_parsefile->strpush;
10118         } else {
10119                 sp = &(g_parsefile->basestrpush);
10120         }
10121         g_parsefile->strpush = sp;
10122         sp->prev_string = g_parsefile->next_to_pgetc;
10123         sp->prev_left_in_line = g_parsefile->left_in_line;
10124         sp->unget = g_parsefile->unget;
10125         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10126 #if ENABLE_ASH_ALIAS
10127         sp->ap = ap;
10128         if (ap) {
10129                 ap->flag |= ALIASINUSE;
10130                 sp->string = s;
10131         }
10132 #endif
10133         g_parsefile->next_to_pgetc = s;
10134         g_parsefile->left_in_line = len;
10135         g_parsefile->unget = 0;
10136         INT_ON;
10137 }
10138
10139 static void
10140 popstring(void)
10141 {
10142         struct strpush *sp = g_parsefile->strpush;
10143
10144         INT_OFF;
10145 #if ENABLE_ASH_ALIAS
10146         if (sp->ap) {
10147                 if (g_parsefile->next_to_pgetc[-1] == ' '
10148                  || g_parsefile->next_to_pgetc[-1] == '\t'
10149                 ) {
10150                         checkkwd |= CHKALIAS;
10151                 }
10152                 if (sp->string != sp->ap->val) {
10153                         free(sp->string);
10154                 }
10155                 sp->ap->flag &= ~ALIASINUSE;
10156                 if (sp->ap->flag & ALIASDEAD) {
10157                         unalias(sp->ap->name);
10158                 }
10159         }
10160 #endif
10161         g_parsefile->next_to_pgetc = sp->prev_string;
10162         g_parsefile->left_in_line = sp->prev_left_in_line;
10163         g_parsefile->unget = sp->unget;
10164         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10165         g_parsefile->strpush = sp->prev;
10166         if (sp != &(g_parsefile->basestrpush))
10167                 free(sp);
10168         INT_ON;
10169 }
10170
10171 static int
10172 preadfd(void)
10173 {
10174         int nr;
10175         char *buf = g_parsefile->buf;
10176
10177         g_parsefile->next_to_pgetc = buf;
10178 #if ENABLE_FEATURE_EDITING
10179  retry:
10180         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10181                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10182         else {
10183                 int timeout = -1;
10184 # if ENABLE_ASH_IDLE_TIMEOUT
10185                 if (iflag) {
10186                         const char *tmout_var = lookupvar("TMOUT");
10187                         if (tmout_var) {
10188                                 timeout = atoi(tmout_var) * 1000;
10189                                 if (timeout <= 0)
10190                                         timeout = -1;
10191                         }
10192                 }
10193 # endif
10194 # if ENABLE_FEATURE_TAB_COMPLETION
10195                 line_input_state->path_lookup = pathval();
10196 # endif
10197                 reinit_unicode_for_ash();
10198                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10199                 if (nr == 0) {
10200                         /* ^C pressed, "convert" to SIGINT */
10201                         write(STDOUT_FILENO, "^C", 2);
10202                         if (trap[SIGINT]) {
10203                                 buf[0] = '\n';
10204                                 buf[1] = '\0';
10205                                 raise(SIGINT);
10206                                 return 1;
10207                         }
10208                         exitstatus = 128 + SIGINT;
10209                         bb_putchar('\n');
10210                         goto retry;
10211                 }
10212                 if (nr < 0) {
10213                         if (errno == 0) {
10214                                 /* Ctrl+D pressed */
10215                                 nr = 0;
10216                         }
10217 # if ENABLE_ASH_IDLE_TIMEOUT
10218                         else if (errno == EAGAIN && timeout > 0) {
10219                                 puts("\007timed out waiting for input: auto-logout");
10220                                 exitshell();
10221                         }
10222 # endif
10223                 }
10224         }
10225 #else
10226         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10227 #endif
10228
10229 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10230         if (nr < 0) {
10231                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10232                         int flags = fcntl(0, F_GETFL);
10233                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10234                                 flags &= ~O_NONBLOCK;
10235                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10236                                         out2str("sh: turning off NDELAY mode\n");
10237                                         goto retry;
10238                                 }
10239                         }
10240                 }
10241         }
10242 #endif
10243         return nr;
10244 }
10245
10246 /*
10247  * Refill the input buffer and return the next input character:
10248  *
10249  * 1) If a string was pushed back on the input, pop it;
10250  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10251  *    or we are reading from a string so we can't refill the buffer,
10252  *    return EOF.
10253  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10254  * 4) Process input up to the next newline, deleting nul characters.
10255  */
10256 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10257 #define pgetc_debug(...) ((void)0)
10258 static int pgetc(void);
10259 static int
10260 preadbuffer(void)
10261 {
10262         char *q;
10263         int more;
10264
10265         if (g_parsefile->strpush) {
10266 #if ENABLE_ASH_ALIAS
10267                 if (g_parsefile->left_in_line == -1
10268                  && g_parsefile->strpush->ap
10269                  && g_parsefile->next_to_pgetc[-1] != ' '
10270                  && g_parsefile->next_to_pgetc[-1] != '\t'
10271                 ) {
10272                         pgetc_debug("preadbuffer PEOA");
10273                         return PEOA;
10274                 }
10275 #endif
10276                 popstring();
10277                 return pgetc();
10278         }
10279         /* on both branches above g_parsefile->left_in_line < 0.
10280          * "pgetc" needs refilling.
10281          */
10282
10283         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10284          * pungetc() may increment it a few times.
10285          * Assuming it won't increment it to less than -90.
10286          */
10287         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10288                 pgetc_debug("preadbuffer PEOF1");
10289                 /* even in failure keep left_in_line and next_to_pgetc
10290                  * in lock step, for correct multi-layer pungetc.
10291                  * left_in_line was decremented before preadbuffer(),
10292                  * must inc next_to_pgetc: */
10293                 g_parsefile->next_to_pgetc++;
10294                 return PEOF;
10295         }
10296
10297         more = g_parsefile->left_in_buffer;
10298         if (more <= 0) {
10299                 flush_stdout_stderr();
10300  again:
10301                 more = preadfd();
10302                 if (more <= 0) {
10303                         /* don't try reading again */
10304                         g_parsefile->left_in_line = -99;
10305                         pgetc_debug("preadbuffer PEOF2");
10306                         g_parsefile->next_to_pgetc++;
10307                         return PEOF;
10308                 }
10309         }
10310
10311         /* Find out where's the end of line.
10312          * Set g_parsefile->left_in_line
10313          * and g_parsefile->left_in_buffer acordingly.
10314          * NUL chars are deleted.
10315          */
10316         q = g_parsefile->next_to_pgetc;
10317         for (;;) {
10318                 char c;
10319
10320                 more--;
10321
10322                 c = *q;
10323                 if (c == '\0') {
10324                         memmove(q, q + 1, more);
10325                 } else {
10326                         q++;
10327                         if (c == '\n') {
10328                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10329                                 break;
10330                         }
10331                 }
10332
10333                 if (more <= 0) {
10334                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10335                         if (g_parsefile->left_in_line < 0)
10336                                 goto again;
10337                         break;
10338                 }
10339         }
10340         g_parsefile->left_in_buffer = more;
10341
10342         if (vflag) {
10343                 char save = *q;
10344                 *q = '\0';
10345                 out2str(g_parsefile->next_to_pgetc);
10346                 *q = save;
10347         }
10348
10349         pgetc_debug("preadbuffer at %d:%p'%s'",
10350                         g_parsefile->left_in_line,
10351                         g_parsefile->next_to_pgetc,
10352                         g_parsefile->next_to_pgetc);
10353         return (unsigned char)*g_parsefile->next_to_pgetc++;
10354 }
10355
10356 static void
10357 nlprompt(void)
10358 {
10359         g_parsefile->linno++;
10360         setprompt_if(doprompt, 2);
10361 }
10362 static void
10363 nlnoprompt(void)
10364 {
10365         g_parsefile->linno++;
10366         needprompt = doprompt;
10367 }
10368
10369 static int
10370 pgetc(void)
10371 {
10372         int c;
10373
10374         pgetc_debug("pgetc at %d:%p'%s'",
10375                         g_parsefile->left_in_line,
10376                         g_parsefile->next_to_pgetc,
10377                         g_parsefile->next_to_pgetc);
10378         if (g_parsefile->unget)
10379                 return g_parsefile->lastc[--g_parsefile->unget];
10380
10381         if (--g_parsefile->left_in_line >= 0)
10382                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10383         else
10384                 c = preadbuffer();
10385
10386         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10387         g_parsefile->lastc[0] = c;
10388
10389         return c;
10390 }
10391
10392 #if ENABLE_ASH_ALIAS
10393 static int
10394 pgetc_without_PEOA(void)
10395 {
10396         int c;
10397         do {
10398                 pgetc_debug("pgetc at %d:%p'%s'",
10399                                 g_parsefile->left_in_line,
10400                                 g_parsefile->next_to_pgetc,
10401                                 g_parsefile->next_to_pgetc);
10402                 c = pgetc();
10403         } while (c == PEOA);
10404         return c;
10405 }
10406 #else
10407 # define pgetc_without_PEOA() pgetc()
10408 #endif
10409
10410 /*
10411  * Undo a call to pgetc.  Only two characters may be pushed back.
10412  * PEOF may be pushed back.
10413  */
10414 static void
10415 pungetc(void)
10416 {
10417         g_parsefile->unget++;
10418 }
10419
10420 /* This one eats backslash+newline */
10421 static int
10422 pgetc_eatbnl(void)
10423 {
10424         int c;
10425
10426         while ((c = pgetc()) == '\\') {
10427                 if (pgetc() != '\n') {
10428                         pungetc();
10429                         break;
10430                 }
10431
10432                 nlprompt();
10433         }
10434
10435         return c;
10436 }
10437
10438 /*
10439  * To handle the "." command, a stack of input files is used.  Pushfile
10440  * adds a new entry to the stack and popfile restores the previous level.
10441  */
10442 static void
10443 pushfile(void)
10444 {
10445         struct parsefile *pf;
10446
10447         pf = ckzalloc(sizeof(*pf));
10448         pf->prev = g_parsefile;
10449         pf->pf_fd = -1;
10450         /*pf->strpush = NULL; - ckzalloc did it */
10451         /*pf->basestrpush.prev = NULL;*/
10452         /*pf->unget = 0;*/
10453         g_parsefile = pf;
10454 }
10455
10456 static void
10457 popfile(void)
10458 {
10459         struct parsefile *pf = g_parsefile;
10460
10461         if (pf == &basepf)
10462                 return;
10463
10464         INT_OFF;
10465         if (pf->pf_fd >= 0)
10466                 close(pf->pf_fd);
10467         free(pf->buf);
10468         while (pf->strpush)
10469                 popstring();
10470         g_parsefile = pf->prev;
10471         free(pf);
10472         INT_ON;
10473 }
10474
10475 /*
10476  * Return to top level.
10477  */
10478 static void
10479 popallfiles(void)
10480 {
10481         while (g_parsefile != &basepf)
10482                 popfile();
10483 }
10484
10485 /*
10486  * Close the file(s) that the shell is reading commands from.  Called
10487  * after a fork is done.
10488  */
10489 static void
10490 closescript(void)
10491 {
10492         popallfiles();
10493         if (g_parsefile->pf_fd > 0) {
10494                 close(g_parsefile->pf_fd);
10495                 g_parsefile->pf_fd = 0;
10496         }
10497 }
10498
10499 /*
10500  * Like setinputfile, but takes an open file descriptor.  Call this with
10501  * interrupts off.
10502  */
10503 static void
10504 setinputfd(int fd, int push)
10505 {
10506         if (push) {
10507                 pushfile();
10508                 g_parsefile->buf = NULL;
10509         }
10510         g_parsefile->pf_fd = fd;
10511         if (g_parsefile->buf == NULL)
10512                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10513         g_parsefile->left_in_buffer = 0;
10514         g_parsefile->left_in_line = 0;
10515         g_parsefile->linno = 1;
10516 }
10517
10518 /*
10519  * Set the input to take input from a file.  If push is set, push the
10520  * old input onto the stack first.
10521  */
10522 static int
10523 setinputfile(const char *fname, int flags)
10524 {
10525         int fd;
10526
10527         INT_OFF;
10528         fd = open(fname, O_RDONLY);
10529         if (fd < 0) {
10530                 if (flags & INPUT_NOFILE_OK)
10531                         goto out;
10532                 exitstatus = 127;
10533                 ash_msg_and_raise_error("can't open '%s'", fname);
10534         }
10535         if (fd < 10)
10536                 fd = savefd(fd);
10537         else
10538                 close_on_exec_on(fd);
10539         setinputfd(fd, flags & INPUT_PUSH_FILE);
10540  out:
10541         INT_ON;
10542         return fd;
10543 }
10544
10545 /*
10546  * Like setinputfile, but takes input from a string.
10547  */
10548 static void
10549 setinputstring(char *string)
10550 {
10551         INT_OFF;
10552         pushfile();
10553         g_parsefile->next_to_pgetc = string;
10554         g_parsefile->left_in_line = strlen(string);
10555         g_parsefile->buf = NULL;
10556         g_parsefile->linno = 1;
10557         INT_ON;
10558 }
10559
10560
10561 /*
10562  * Routines to check for mail.
10563  */
10564
10565 #if ENABLE_ASH_MAIL
10566
10567 /* Hash of mtimes of mailboxes */
10568 static unsigned mailtime_hash;
10569 /* Set if MAIL or MAILPATH is changed. */
10570 static smallint mail_var_path_changed;
10571
10572 /*
10573  * Print appropriate message(s) if mail has arrived.
10574  * If mail_var_path_changed is set,
10575  * then the value of MAIL has mail_var_path_changed,
10576  * so we just update the values.
10577  */
10578 static void
10579 chkmail(void)
10580 {
10581         const char *mpath;
10582         char *p;
10583         char *q;
10584         unsigned new_hash;
10585         struct stackmark smark;
10586         struct stat statb;
10587
10588         setstackmark(&smark);
10589         mpath = mpathset() ? mpathval() : mailval();
10590         new_hash = 0;
10591         for (;;) {
10592                 p = path_advance(&mpath, nullstr);
10593                 if (p == NULL)
10594                         break;
10595                 if (*p == '\0')
10596                         continue;
10597                 for (q = p; *q; q++)
10598                         continue;
10599 #if DEBUG
10600                 if (q[-1] != '/')
10601                         abort();
10602 #endif
10603                 q[-1] = '\0';                   /* delete trailing '/' */
10604                 if (stat(p, &statb) < 0) {
10605                         continue;
10606                 }
10607                 /* Very simplistic "hash": just a sum of all mtimes */
10608                 new_hash += (unsigned)statb.st_mtime;
10609         }
10610         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10611                 if (mailtime_hash != 0)
10612                         out2str("you have mail\n");
10613                 mailtime_hash = new_hash;
10614         }
10615         mail_var_path_changed = 0;
10616         popstackmark(&smark);
10617 }
10618
10619 static void FAST_FUNC
10620 changemail(const char *val UNUSED_PARAM)
10621 {
10622         mail_var_path_changed = 1;
10623 }
10624
10625 #endif /* ASH_MAIL */
10626
10627
10628 /* ============ ??? */
10629
10630 /*
10631  * Set the shell parameters.
10632  */
10633 static void
10634 setparam(char **argv)
10635 {
10636         char **newparam;
10637         char **ap;
10638         int nparam;
10639
10640         for (nparam = 0; argv[nparam]; nparam++)
10641                 continue;
10642         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10643         while (*argv) {
10644                 *ap++ = ckstrdup(*argv++);
10645         }
10646         *ap = NULL;
10647         freeparam(&shellparam);
10648         shellparam.malloced = 1;
10649         shellparam.nparam = nparam;
10650         shellparam.p = newparam;
10651 #if ENABLE_ASH_GETOPTS
10652         shellparam.optind = 1;
10653         shellparam.optoff = -1;
10654 #endif
10655 }
10656
10657 /*
10658  * Process shell options.  The global variable argptr contains a pointer
10659  * to the argument list; we advance it past the options.
10660  *
10661  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10662  * For a non-interactive shell, an error condition encountered
10663  * by a special built-in ... shall cause the shell to write a diagnostic message
10664  * to standard error and exit as shown in the following table:
10665  * Error                                           Special Built-In
10666  * ...
10667  * Utility syntax error (option or operand error)  Shall exit
10668  * ...
10669  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10670  * we see that bash does not do that (set "finishes" with error code 1 instead,
10671  * and shell continues), and people rely on this behavior!
10672  * Testcase:
10673  * set -o barfoo 2>/dev/null
10674  * echo $?
10675  *
10676  * Oh well. Let's mimic that.
10677  */
10678 static int
10679 plus_minus_o(char *name, int val)
10680 {
10681         int i;
10682
10683         if (name) {
10684                 for (i = 0; i < NOPTS; i++) {
10685                         if (strcmp(name, optnames(i)) == 0) {
10686                                 optlist[i] = val;
10687                                 return 0;
10688                         }
10689                 }
10690                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10691                 return 1;
10692         }
10693         for (i = 0; i < NOPTS; i++) {
10694                 if (val) {
10695                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10696                 } else {
10697                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10698                 }
10699         }
10700         return 0;
10701 }
10702 static void
10703 setoption(int flag, int val)
10704 {
10705         int i;
10706
10707         for (i = 0; i < NOPTS; i++) {
10708                 if (optletters(i) == flag) {
10709                         optlist[i] = val;
10710                         return;
10711                 }
10712         }
10713         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10714         /* NOTREACHED */
10715 }
10716 static int
10717 options(int cmdline)
10718 {
10719         char *p;
10720         int val;
10721         int c;
10722
10723         if (cmdline)
10724                 minusc = NULL;
10725         while ((p = *argptr) != NULL) {
10726                 c = *p++;
10727                 if (c != '-' && c != '+')
10728                         break;
10729                 argptr++;
10730                 val = 0; /* val = 0 if c == '+' */
10731                 if (c == '-') {
10732                         val = 1;
10733                         if (p[0] == '\0' || LONE_DASH(p)) {
10734                                 if (!cmdline) {
10735                                         /* "-" means turn off -x and -v */
10736                                         if (p[0] == '\0')
10737                                                 xflag = vflag = 0;
10738                                         /* "--" means reset params */
10739                                         else if (*argptr == NULL)
10740                                                 setparam(argptr);
10741                                 }
10742                                 break;    /* "-" or "--" terminates options */
10743                         }
10744                 }
10745                 /* first char was + or - */
10746                 while ((c = *p++) != '\0') {
10747                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10748                         if (c == 'c' && cmdline) {
10749                                 minusc = p;     /* command is after shell args */
10750                         } else if (c == 'o') {
10751                                 if (plus_minus_o(*argptr, val)) {
10752                                         /* it already printed err message */
10753                                         return 1; /* error */
10754                                 }
10755                                 if (*argptr)
10756                                         argptr++;
10757                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10758                                 isloginsh = 1;
10759                         /* bash does not accept +-login, we also won't */
10760                         } else if (cmdline && val && (c == '-')) { /* long options */
10761                                 if (strcmp(p, "login") == 0)
10762                                         isloginsh = 1;
10763                                 break;
10764                         } else {
10765                                 setoption(c, val);
10766                         }
10767                 }
10768         }
10769         return 0;
10770 }
10771
10772 /*
10773  * The shift builtin command.
10774  */
10775 static int FAST_FUNC
10776 shiftcmd(int argc UNUSED_PARAM, char **argv)
10777 {
10778         int n;
10779         char **ap1, **ap2;
10780
10781         n = 1;
10782         if (argv[1])
10783                 n = number(argv[1]);
10784         if (n > shellparam.nparam)
10785                 n = 0; /* bash compat, was = shellparam.nparam; */
10786         INT_OFF;
10787         shellparam.nparam -= n;
10788         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10789                 if (shellparam.malloced)
10790                         free(*ap1);
10791         }
10792         ap2 = shellparam.p;
10793         while ((*ap2++ = *ap1++) != NULL)
10794                 continue;
10795 #if ENABLE_ASH_GETOPTS
10796         shellparam.optind = 1;
10797         shellparam.optoff = -1;
10798 #endif
10799         INT_ON;
10800         return 0;
10801 }
10802
10803 /*
10804  * POSIX requires that 'set' (but not export or readonly) output the
10805  * variables in lexicographic order - by the locale's collating order (sigh).
10806  * Maybe we could keep them in an ordered balanced binary tree
10807  * instead of hashed lists.
10808  * For now just roll 'em through qsort for printing...
10809  */
10810 static int
10811 showvars(const char *sep_prefix, int on, int off)
10812 {
10813         const char *sep;
10814         char **ep, **epend;
10815
10816         ep = listvars(on, off, &epend);
10817         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10818
10819         sep = *sep_prefix ? " " : sep_prefix;
10820
10821         for (; ep < epend; ep++) {
10822                 const char *p;
10823                 const char *q;
10824
10825                 p = strchrnul(*ep, '=');
10826                 q = nullstr;
10827                 if (*p)
10828                         q = single_quote(++p);
10829                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10830         }
10831         return 0;
10832 }
10833
10834 /*
10835  * The set command builtin.
10836  */
10837 static int FAST_FUNC
10838 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10839 {
10840         int retval;
10841
10842         if (!argv[1])
10843                 return showvars(nullstr, 0, VUNSET);
10844
10845         INT_OFF;
10846         retval = options(/*cmdline:*/ 0);
10847         if (retval == 0) { /* if no parse error... */
10848                 optschanged();
10849                 if (*argptr != NULL) {
10850                         setparam(argptr);
10851                 }
10852         }
10853         INT_ON;
10854         return retval;
10855 }
10856
10857 #if ENABLE_ASH_RANDOM_SUPPORT
10858 static void FAST_FUNC
10859 change_random(const char *value)
10860 {
10861         uint32_t t;
10862
10863         if (value == NULL) {
10864                 /* "get", generate */
10865                 t = next_random(&random_gen);
10866                 /* set without recursion */
10867                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10868                 vrandom.flags &= ~VNOFUNC;
10869         } else {
10870                 /* set/reset */
10871                 t = strtoul(value, NULL, 10);
10872                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10873         }
10874 }
10875 #endif
10876
10877 #if ENABLE_ASH_GETOPTS
10878 static int
10879 getopts(char *optstr, char *optvar, char **optfirst)
10880 {
10881         char *p, *q;
10882         char c = '?';
10883         int done = 0;
10884         char sbuf[2];
10885         char **optnext;
10886         int ind = shellparam.optind;
10887         int off = shellparam.optoff;
10888
10889         sbuf[1] = '\0';
10890
10891         shellparam.optind = -1;
10892         optnext = optfirst + ind - 1;
10893
10894         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10895                 p = NULL;
10896         else
10897                 p = optnext[-1] + off;
10898         if (p == NULL || *p == '\0') {
10899                 /* Current word is done, advance */
10900                 p = *optnext;
10901                 if (p == NULL || *p != '-' || *++p == '\0') {
10902  atend:
10903                         p = NULL;
10904                         done = 1;
10905                         goto out;
10906                 }
10907                 optnext++;
10908                 if (LONE_DASH(p))        /* check for "--" */
10909                         goto atend;
10910         }
10911
10912         c = *p++;
10913         for (q = optstr; *q != c;) {
10914                 if (*q == '\0') {
10915                         if (optstr[0] == ':') {
10916                                 sbuf[0] = c;
10917                                 /*sbuf[1] = '\0'; - already is */
10918                                 setvar0("OPTARG", sbuf);
10919                         } else {
10920                                 fprintf(stderr, "Illegal option -%c\n", c);
10921                                 unsetvar("OPTARG");
10922                         }
10923                         c = '?';
10924                         goto out;
10925                 }
10926                 if (*++q == ':')
10927                         q++;
10928         }
10929
10930         if (*++q == ':') {
10931                 if (*p == '\0' && (p = *optnext) == NULL) {
10932                         if (optstr[0] == ':') {
10933                                 sbuf[0] = c;
10934                                 /*sbuf[1] = '\0'; - already is */
10935                                 setvar0("OPTARG", sbuf);
10936                                 c = ':';
10937                         } else {
10938                                 fprintf(stderr, "No arg for -%c option\n", c);
10939                                 unsetvar("OPTARG");
10940                                 c = '?';
10941                         }
10942                         goto out;
10943                 }
10944
10945                 if (p == *optnext)
10946                         optnext++;
10947                 setvar0("OPTARG", p);
10948                 p = NULL;
10949         } else
10950                 setvar0("OPTARG", nullstr);
10951  out:
10952         ind = optnext - optfirst + 1;
10953         setvar("OPTIND", itoa(ind), VNOFUNC);
10954         sbuf[0] = c;
10955         /*sbuf[1] = '\0'; - already is */
10956         setvar0(optvar, sbuf);
10957
10958         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10959         shellparam.optind = ind;
10960
10961         return done;
10962 }
10963
10964 /*
10965  * The getopts builtin.  Shellparam.optnext points to the next argument
10966  * to be processed.  Shellparam.optptr points to the next character to
10967  * be processed in the current argument.  If shellparam.optnext is NULL,
10968  * then it's the first time getopts has been called.
10969  */
10970 static int FAST_FUNC
10971 getoptscmd(int argc, char **argv)
10972 {
10973         char **optbase;
10974
10975         if (argc < 3)
10976                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10977         if (argc == 3) {
10978                 optbase = shellparam.p;
10979                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10980                         shellparam.optind = 1;
10981                         shellparam.optoff = -1;
10982                 }
10983         } else {
10984                 optbase = &argv[3];
10985                 if ((unsigned)shellparam.optind > argc - 2) {
10986                         shellparam.optind = 1;
10987                         shellparam.optoff = -1;
10988                 }
10989         }
10990
10991         return getopts(argv[1], argv[2], optbase);
10992 }
10993 #endif /* ASH_GETOPTS */
10994
10995
10996 /* ============ Shell parser */
10997
10998 struct heredoc {
10999         struct heredoc *next;   /* next here document in list */
11000         union node *here;       /* redirection node */
11001         char *eofmark;          /* string indicating end of input */
11002         smallint striptabs;     /* if set, strip leading tabs */
11003 };
11004
11005 static smallint tokpushback;           /* last token pushed back */
11006 static smallint quoteflag;             /* set if (part of) last token was quoted */
11007 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11008 static struct heredoc *heredoclist;    /* list of here documents to read */
11009 static char *wordtext;                 /* text of last word returned by readtoken */
11010 static struct nodelist *backquotelist;
11011 static union node *redirnode;
11012 static struct heredoc *heredoc;
11013
11014 static const char *
11015 tokname(char *buf, int tok)
11016 {
11017         if (tok < TSEMI)
11018                 return tokname_array[tok];
11019         sprintf(buf, "\"%s\"", tokname_array[tok]);
11020         return buf;
11021 }
11022
11023 /* raise_error_unexpected_syntax:
11024  * Called when an unexpected token is read during the parse.  The argument
11025  * is the token that is expected, or -1 if more than one type of token can
11026  * occur at this point.
11027  */
11028 static void raise_error_unexpected_syntax(int) NORETURN;
11029 static void
11030 raise_error_unexpected_syntax(int token)
11031 {
11032         char msg[64];
11033         char buf[16];
11034         int l;
11035
11036         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11037         if (token >= 0)
11038                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11039         raise_error_syntax(msg);
11040         /* NOTREACHED */
11041 }
11042
11043 /* parsing is heavily cross-recursive, need these forward decls */
11044 static union node *andor(void);
11045 static union node *pipeline(void);
11046 static union node *parse_command(void);
11047 static void parseheredoc(void);
11048 static int peektoken(void);
11049 static int readtoken(void);
11050
11051 static union node *
11052 list(int nlflag)
11053 {
11054         union node *n1, *n2, *n3;
11055         int tok;
11056
11057         n1 = NULL;
11058         for (;;) {
11059                 switch (peektoken()) {
11060                 case TNL:
11061                         if (!(nlflag & 1))
11062                                 break;
11063                         parseheredoc();
11064                         return n1;
11065
11066                 case TEOF:
11067                         if (!n1 && (nlflag & 1))
11068                                 n1 = NODE_EOF;
11069                         parseheredoc();
11070                         return n1;
11071                 }
11072
11073                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11074                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11075                         return n1;
11076                 nlflag |= 2;
11077
11078                 n2 = andor();
11079                 tok = readtoken();
11080                 if (tok == TBACKGND) {
11081                         if (n2->type == NPIPE) {
11082                                 n2->npipe.pipe_backgnd = 1;
11083                         } else {
11084                                 if (n2->type != NREDIR) {
11085                                         n3 = stzalloc(sizeof(struct nredir));
11086                                         n3->nredir.n = n2;
11087                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11088                                         n2 = n3;
11089                                 }
11090                                 n2->type = NBACKGND;
11091                         }
11092                 }
11093                 if (n1 == NULL) {
11094                         n1 = n2;
11095                 } else {
11096                         n3 = stzalloc(sizeof(struct nbinary));
11097                         n3->type = NSEMI;
11098                         n3->nbinary.ch1 = n1;
11099                         n3->nbinary.ch2 = n2;
11100                         n1 = n3;
11101                 }
11102                 switch (tok) {
11103                 case TNL:
11104                 case TEOF:
11105                         tokpushback = 1;
11106                         /* fall through */
11107                 case TBACKGND:
11108                 case TSEMI:
11109                         break;
11110                 default:
11111                         if ((nlflag & 1))
11112                                 raise_error_unexpected_syntax(-1);
11113                         tokpushback = 1;
11114                         return n1;
11115                 }
11116         }
11117 }
11118
11119 static union node *
11120 andor(void)
11121 {
11122         union node *n1, *n2, *n3;
11123         int t;
11124
11125         n1 = pipeline();
11126         for (;;) {
11127                 t = readtoken();
11128                 if (t == TAND) {
11129                         t = NAND;
11130                 } else if (t == TOR) {
11131                         t = NOR;
11132                 } else {
11133                         tokpushback = 1;
11134                         return n1;
11135                 }
11136                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11137                 n2 = pipeline();
11138                 n3 = stzalloc(sizeof(struct nbinary));
11139                 n3->type = t;
11140                 n3->nbinary.ch1 = n1;
11141                 n3->nbinary.ch2 = n2;
11142                 n1 = n3;
11143         }
11144 }
11145
11146 static union node *
11147 pipeline(void)
11148 {
11149         union node *n1, *n2, *pipenode;
11150         struct nodelist *lp, *prev;
11151         int negate;
11152
11153         negate = 0;
11154         TRACE(("pipeline: entered\n"));
11155         if (readtoken() == TNOT) {
11156                 negate = !negate;
11157                 checkkwd = CHKKWD | CHKALIAS;
11158         } else
11159                 tokpushback = 1;
11160         n1 = parse_command();
11161         if (readtoken() == TPIPE) {
11162                 pipenode = stzalloc(sizeof(struct npipe));
11163                 pipenode->type = NPIPE;
11164                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11165                 lp = stzalloc(sizeof(struct nodelist));
11166                 pipenode->npipe.cmdlist = lp;
11167                 lp->n = n1;
11168                 do {
11169                         prev = lp;
11170                         lp = stzalloc(sizeof(struct nodelist));
11171                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11172                         lp->n = parse_command();
11173                         prev->next = lp;
11174                 } while (readtoken() == TPIPE);
11175                 lp->next = NULL;
11176                 n1 = pipenode;
11177         }
11178         tokpushback = 1;
11179         if (negate) {
11180                 n2 = stzalloc(sizeof(struct nnot));
11181                 n2->type = NNOT;
11182                 n2->nnot.com = n1;
11183                 return n2;
11184         }
11185         return n1;
11186 }
11187
11188 static union node *
11189 makename(void)
11190 {
11191         union node *n;
11192
11193         n = stzalloc(sizeof(struct narg));
11194         n->type = NARG;
11195         /*n->narg.next = NULL; - stzalloc did it */
11196         n->narg.text = wordtext;
11197         n->narg.backquote = backquotelist;
11198         return n;
11199 }
11200
11201 static void
11202 fixredir(union node *n, const char *text, int err)
11203 {
11204         int fd;
11205
11206         TRACE(("Fix redir %s %d\n", text, err));
11207         if (!err)
11208                 n->ndup.vname = NULL;
11209
11210         fd = bb_strtou(text, NULL, 10);
11211         if (!errno && fd >= 0)
11212                 n->ndup.dupfd = fd;
11213         else if (LONE_DASH(text))
11214                 n->ndup.dupfd = -1;
11215         else {
11216                 if (err)
11217                         raise_error_syntax("bad fd number");
11218                 n->ndup.vname = makename();
11219         }
11220 }
11221
11222 static void
11223 parsefname(void)
11224 {
11225         union node *n = redirnode;
11226
11227         if (n->type == NHERE)
11228                 checkkwd = CHKEOFMARK;
11229         if (readtoken() != TWORD)
11230                 raise_error_unexpected_syntax(-1);
11231         if (n->type == NHERE) {
11232                 struct heredoc *here = heredoc;
11233                 struct heredoc *p;
11234
11235                 if (quoteflag == 0)
11236                         n->type = NXHERE;
11237                 TRACE(("Here document %d\n", n->type));
11238                 rmescapes(wordtext, 0);
11239                 here->eofmark = wordtext;
11240                 here->next = NULL;
11241                 if (heredoclist == NULL)
11242                         heredoclist = here;
11243                 else {
11244                         for (p = heredoclist; p->next; p = p->next)
11245                                 continue;
11246                         p->next = here;
11247                 }
11248         } else if (n->type == NTOFD || n->type == NFROMFD) {
11249                 fixredir(n, wordtext, 0);
11250         } else {
11251                 n->nfile.fname = makename();
11252         }
11253 }
11254
11255 static union node *
11256 simplecmd(void)
11257 {
11258         union node *args, **app;
11259         union node *n = NULL;
11260         union node *vars, **vpp;
11261         union node **rpp, *redir;
11262         int savecheckkwd;
11263 #if BASH_TEST2
11264         smallint double_brackets_flag = 0;
11265 #endif
11266         IF_BASH_FUNCTION(smallint function_flag = 0;)
11267
11268         args = NULL;
11269         app = &args;
11270         vars = NULL;
11271         vpp = &vars;
11272         redir = NULL;
11273         rpp = &redir;
11274
11275         savecheckkwd = CHKALIAS;
11276         for (;;) {
11277                 int t;
11278                 checkkwd = savecheckkwd;
11279                 t = readtoken();
11280                 switch (t) {
11281 #if BASH_FUNCTION
11282                 case TFUNCTION:
11283                         if (peektoken() != TWORD)
11284                                 raise_error_unexpected_syntax(TWORD);
11285                         function_flag = 1;
11286                         break;
11287 #endif
11288 #if BASH_TEST2
11289                 case TAND: /* "&&" */
11290                 case TOR: /* "||" */
11291                         if (!double_brackets_flag) {
11292                                 tokpushback = 1;
11293                                 goto out;
11294                         }
11295                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11296 #endif
11297                 case TWORD:
11298                         n = stzalloc(sizeof(struct narg));
11299                         n->type = NARG;
11300                         /*n->narg.next = NULL; - stzalloc did it */
11301                         n->narg.text = wordtext;
11302 #if BASH_TEST2
11303                         if (strcmp("[[", wordtext) == 0)
11304                                 double_brackets_flag = 1;
11305                         else if (strcmp("]]", wordtext) == 0)
11306                                 double_brackets_flag = 0;
11307 #endif
11308                         n->narg.backquote = backquotelist;
11309                         if (savecheckkwd && isassignment(wordtext)) {
11310                                 *vpp = n;
11311                                 vpp = &n->narg.next;
11312                         } else {
11313                                 *app = n;
11314                                 app = &n->narg.next;
11315                                 savecheckkwd = 0;
11316                         }
11317 #if BASH_FUNCTION
11318                         if (function_flag) {
11319                                 checkkwd = CHKNL | CHKKWD;
11320                                 switch (peektoken()) {
11321                                 case TBEGIN:
11322                                 case TIF:
11323                                 case TCASE:
11324                                 case TUNTIL:
11325                                 case TWHILE:
11326                                 case TFOR:
11327                                         goto do_func;
11328                                 case TLP:
11329                                         function_flag = 0;
11330                                         break;
11331                                 case TWORD:
11332                                         if (strcmp("[[", wordtext) == 0)
11333                                                 goto do_func;
11334                                         /* fall through */
11335                                 default:
11336                                         raise_error_unexpected_syntax(-1);
11337                                 }
11338                         }
11339 #endif
11340                         break;
11341                 case TREDIR:
11342                         *rpp = n = redirnode;
11343                         rpp = &n->nfile.next;
11344                         parsefname();   /* read name of redirection file */
11345                         break;
11346                 case TLP:
11347  IF_BASH_FUNCTION(do_func:)
11348                         if (args && app == &args->narg.next
11349                          && !vars && !redir
11350                         ) {
11351                                 struct builtincmd *bcmd;
11352                                 const char *name;
11353
11354                                 /* We have a function */
11355                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11356                                         raise_error_unexpected_syntax(TRP);
11357                                 name = n->narg.text;
11358                                 if (!goodname(name)
11359                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11360                                 ) {
11361                                         raise_error_syntax("bad function name");
11362                                 }
11363                                 n->type = NDEFUN;
11364                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11365                                 n->narg.next = parse_command();
11366                                 return n;
11367                         }
11368                         IF_BASH_FUNCTION(function_flag = 0;)
11369                         /* fall through */
11370                 default:
11371                         tokpushback = 1;
11372                         goto out;
11373                 }
11374         }
11375  out:
11376         *app = NULL;
11377         *vpp = NULL;
11378         *rpp = NULL;
11379         n = stzalloc(sizeof(struct ncmd));
11380         n->type = NCMD;
11381         n->ncmd.args = args;
11382         n->ncmd.assign = vars;
11383         n->ncmd.redirect = redir;
11384         return n;
11385 }
11386
11387 static union node *
11388 parse_command(void)
11389 {
11390         union node *n1, *n2;
11391         union node *ap, **app;
11392         union node *cp, **cpp;
11393         union node *redir, **rpp;
11394         union node **rpp2;
11395         int t;
11396
11397         redir = NULL;
11398         rpp2 = &redir;
11399
11400         switch (readtoken()) {
11401         default:
11402                 raise_error_unexpected_syntax(-1);
11403                 /* NOTREACHED */
11404         case TIF:
11405                 n1 = stzalloc(sizeof(struct nif));
11406                 n1->type = NIF;
11407                 n1->nif.test = list(0);
11408                 if (readtoken() != TTHEN)
11409                         raise_error_unexpected_syntax(TTHEN);
11410                 n1->nif.ifpart = list(0);
11411                 n2 = n1;
11412                 while (readtoken() == TELIF) {
11413                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11414                         n2 = n2->nif.elsepart;
11415                         n2->type = NIF;
11416                         n2->nif.test = list(0);
11417                         if (readtoken() != TTHEN)
11418                                 raise_error_unexpected_syntax(TTHEN);
11419                         n2->nif.ifpart = list(0);
11420                 }
11421                 if (lasttoken == TELSE)
11422                         n2->nif.elsepart = list(0);
11423                 else {
11424                         n2->nif.elsepart = NULL;
11425                         tokpushback = 1;
11426                 }
11427                 t = TFI;
11428                 break;
11429         case TWHILE:
11430         case TUNTIL: {
11431                 int got;
11432                 n1 = stzalloc(sizeof(struct nbinary));
11433                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11434                 n1->nbinary.ch1 = list(0);
11435                 got = readtoken();
11436                 if (got != TDO) {
11437                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11438                                         got == TWORD ? wordtext : ""));
11439                         raise_error_unexpected_syntax(TDO);
11440                 }
11441                 n1->nbinary.ch2 = list(0);
11442                 t = TDONE;
11443                 break;
11444         }
11445         case TFOR:
11446                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11447                         raise_error_syntax("bad for loop variable");
11448                 n1 = stzalloc(sizeof(struct nfor));
11449                 n1->type = NFOR;
11450                 n1->nfor.var = wordtext;
11451                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11452                 if (readtoken() == TIN) {
11453                         app = &ap;
11454                         while (readtoken() == TWORD) {
11455                                 n2 = stzalloc(sizeof(struct narg));
11456                                 n2->type = NARG;
11457                                 /*n2->narg.next = NULL; - stzalloc did it */
11458                                 n2->narg.text = wordtext;
11459                                 n2->narg.backquote = backquotelist;
11460                                 *app = n2;
11461                                 app = &n2->narg.next;
11462                         }
11463                         *app = NULL;
11464                         n1->nfor.args = ap;
11465                         if (lasttoken != TNL && lasttoken != TSEMI)
11466                                 raise_error_unexpected_syntax(-1);
11467                 } else {
11468                         n2 = stzalloc(sizeof(struct narg));
11469                         n2->type = NARG;
11470                         /*n2->narg.next = NULL; - stzalloc did it */
11471                         n2->narg.text = (char *)dolatstr;
11472                         /*n2->narg.backquote = NULL;*/
11473                         n1->nfor.args = n2;
11474                         /*
11475                          * Newline or semicolon here is optional (but note
11476                          * that the original Bourne shell only allowed NL).
11477                          */
11478                         if (lasttoken != TSEMI)
11479                                 tokpushback = 1;
11480                 }
11481                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11482                 if (readtoken() != TDO)
11483                         raise_error_unexpected_syntax(TDO);
11484                 n1->nfor.body = list(0);
11485                 t = TDONE;
11486                 break;
11487         case TCASE:
11488                 n1 = stzalloc(sizeof(struct ncase));
11489                 n1->type = NCASE;
11490                 if (readtoken() != TWORD)
11491                         raise_error_unexpected_syntax(TWORD);
11492                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11493                 n2->type = NARG;
11494                 /*n2->narg.next = NULL; - stzalloc did it */
11495                 n2->narg.text = wordtext;
11496                 n2->narg.backquote = backquotelist;
11497                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11498                 if (readtoken() != TIN)
11499                         raise_error_unexpected_syntax(TIN);
11500                 cpp = &n1->ncase.cases;
11501  next_case:
11502                 checkkwd = CHKNL | CHKKWD;
11503                 t = readtoken();
11504                 while (t != TESAC) {
11505                         if (lasttoken == TLP)
11506                                 readtoken();
11507                         *cpp = cp = stzalloc(sizeof(struct nclist));
11508                         cp->type = NCLIST;
11509                         app = &cp->nclist.pattern;
11510                         for (;;) {
11511                                 *app = ap = stzalloc(sizeof(struct narg));
11512                                 ap->type = NARG;
11513                                 /*ap->narg.next = NULL; - stzalloc did it */
11514                                 ap->narg.text = wordtext;
11515                                 ap->narg.backquote = backquotelist;
11516                                 if (readtoken() != TPIPE)
11517                                         break;
11518                                 app = &ap->narg.next;
11519                                 readtoken();
11520                         }
11521                         //ap->narg.next = NULL;
11522                         if (lasttoken != TRP)
11523                                 raise_error_unexpected_syntax(TRP);
11524                         cp->nclist.body = list(2);
11525
11526                         cpp = &cp->nclist.next;
11527
11528                         checkkwd = CHKNL | CHKKWD;
11529                         t = readtoken();
11530                         if (t != TESAC) {
11531                                 if (t != TENDCASE)
11532                                         raise_error_unexpected_syntax(TENDCASE);
11533                                 goto next_case;
11534                         }
11535                 }
11536                 *cpp = NULL;
11537                 goto redir;
11538         case TLP:
11539                 n1 = stzalloc(sizeof(struct nredir));
11540                 n1->type = NSUBSHELL;
11541                 n1->nredir.n = list(0);
11542                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11543                 t = TRP;
11544                 break;
11545         case TBEGIN:
11546                 n1 = list(0);
11547                 t = TEND;
11548                 break;
11549         IF_BASH_FUNCTION(case TFUNCTION:)
11550         case TWORD:
11551         case TREDIR:
11552                 tokpushback = 1;
11553                 return simplecmd();
11554         }
11555
11556         if (readtoken() != t)
11557                 raise_error_unexpected_syntax(t);
11558
11559  redir:
11560         /* Now check for redirection which may follow command */
11561         checkkwd = CHKKWD | CHKALIAS;
11562         rpp = rpp2;
11563         while (readtoken() == TREDIR) {
11564                 *rpp = n2 = redirnode;
11565                 rpp = &n2->nfile.next;
11566                 parsefname();
11567         }
11568         tokpushback = 1;
11569         *rpp = NULL;
11570         if (redir) {
11571                 if (n1->type != NSUBSHELL) {
11572                         n2 = stzalloc(sizeof(struct nredir));
11573                         n2->type = NREDIR;
11574                         n2->nredir.n = n1;
11575                         n1 = n2;
11576                 }
11577                 n1->nredir.redirect = redir;
11578         }
11579         return n1;
11580 }
11581
11582 #if BASH_DOLLAR_SQUOTE
11583 static int
11584 decode_dollar_squote(void)
11585 {
11586         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11587         int c, cnt;
11588         char *p;
11589         char buf[4];
11590
11591         c = pgetc();
11592         p = strchr(C_escapes, c);
11593         if (p) {
11594                 buf[0] = c;
11595                 p = buf;
11596                 cnt = 3;
11597                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11598                         do {
11599                                 c = pgetc();
11600                                 *++p = c;
11601                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11602                         pungetc();
11603                 } else if (c == 'x') { /* \xHH */
11604                         do {
11605                                 c = pgetc();
11606                                 *++p = c;
11607                         } while (isxdigit(c) && --cnt);
11608                         pungetc();
11609                         if (cnt == 3) { /* \x but next char is "bad" */
11610                                 c = 'x';
11611                                 goto unrecognized;
11612                         }
11613                 } else { /* simple seq like \\ or \t */
11614                         p++;
11615                 }
11616                 *p = '\0';
11617                 p = buf;
11618                 c = bb_process_escape_sequence((void*)&p);
11619         } else { /* unrecognized "\z": print both chars unless ' or " */
11620                 if (c != '\'' && c != '"') {
11621  unrecognized:
11622                         c |= 0x100; /* "please encode \, then me" */
11623                 }
11624         }
11625         return c;
11626 }
11627 #endif
11628
11629 /* Used by expandstr to get here-doc like behaviour. */
11630 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11631
11632 static ALWAYS_INLINE int
11633 realeofmark(const char *eofmark)
11634 {
11635         return eofmark && eofmark != FAKEEOFMARK;
11636 }
11637
11638 /*
11639  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11640  * is not NULL, read a here document.  In the latter case, eofmark is the
11641  * word which marks the end of the document and striptabs is true if
11642  * leading tabs should be stripped from the document.  The argument c
11643  * is the first character of the input token or document.
11644  *
11645  * Because C does not have internal subroutines, I have simulated them
11646  * using goto's to implement the subroutine linkage.  The following macros
11647  * will run code that appears at the end of readtoken1.
11648  */
11649 #define CHECKEND()      {goto checkend; checkend_return:;}
11650 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11651 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11652 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11653 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11654 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11655 static int
11656 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11657 {
11658         /* NB: syntax parameter fits into smallint */
11659         /* c parameter is an unsigned char or PEOF or PEOA */
11660         char *out;
11661         size_t len;
11662         struct nodelist *bqlist;
11663         smallint quotef;
11664         smallint dblquote;
11665         smallint oldstyle;
11666         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11667         smallint pssyntax;   /* we are expanding a prompt string */
11668         int varnest;         /* levels of variables expansion */
11669         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11670         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11671         int dqvarnest;       /* levels of variables expansion within double quotes */
11672
11673         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11674
11675         startlinno = g_parsefile->linno;
11676         bqlist = NULL;
11677         quotef = 0;
11678         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11679 #if ENABLE_ASH_EXPAND_PRMT
11680         pssyntax = (syntax == PSSYNTAX);
11681         if (pssyntax)
11682                 syntax = DQSYNTAX;
11683 #else
11684         pssyntax = 0; /* constant */
11685 #endif
11686         dblquote = (syntax == DQSYNTAX);
11687         varnest = 0;
11688         IF_FEATURE_SH_MATH(arinest = 0;)
11689         IF_FEATURE_SH_MATH(parenlevel = 0;)
11690         dqvarnest = 0;
11691
11692         STARTSTACKSTR(out);
11693  loop:
11694         /* For each line, until end of word */
11695         CHECKEND();     /* set c to PEOF if at end of here document */
11696         for (;;) {      /* until end of line or end of word */
11697                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11698                 switch (SIT(c, syntax)) {
11699                 case CNL:       /* '\n' */
11700                         if (syntax == BASESYNTAX)
11701                                 goto endword;   /* exit outer loop */
11702                         USTPUTC(c, out);
11703                         nlprompt();
11704                         c = pgetc();
11705                         goto loop;              /* continue outer loop */
11706                 case CWORD:
11707                         USTPUTC(c, out);
11708                         break;
11709                 case CCTL:
11710 #if BASH_DOLLAR_SQUOTE
11711                         if (c == '\\' && bash_dollar_squote) {
11712                                 c = decode_dollar_squote();
11713                                 if (c == '\0') {
11714                                         /* skip $'\000', $'\x00' (like bash) */
11715                                         break;
11716                                 }
11717                                 if (c & 0x100) {
11718                                         /* Unknown escape. Encode as '\z' */
11719                                         c = (unsigned char)c;
11720                                         if (eofmark == NULL || dblquote)
11721                                                 USTPUTC(CTLESC, out);
11722                                         USTPUTC('\\', out);
11723                                 }
11724                         }
11725 #endif
11726                         if (eofmark == NULL || dblquote)
11727                                 USTPUTC(CTLESC, out);
11728                         USTPUTC(c, out);
11729                         break;
11730                 case CBACK:     /* backslash */
11731                         c = pgetc_without_PEOA();
11732                         if (c == PEOF) {
11733                                 USTPUTC(CTLESC, out);
11734                                 USTPUTC('\\', out);
11735                                 pungetc();
11736                         } else if (c == '\n') {
11737                                 nlprompt();
11738                         } else {
11739                                 if (pssyntax && c == '$') {
11740                                         USTPUTC(CTLESC, out);
11741                                         USTPUTC('\\', out);
11742                                 }
11743                                 /* Backslash is retained if we are in "str" and next char isn't special */
11744                                 if (dblquote
11745                                  && c != '\\'
11746                                  && c != '`'
11747                                  && c != '$'
11748                                  && (c != '"' || eofmark != NULL)
11749                                 ) {
11750                                         USTPUTC('\\', out);
11751                                 }
11752                                 USTPUTC(CTLESC, out);
11753                                 USTPUTC(c, out);
11754                                 quotef = 1;
11755                         }
11756                         break;
11757                 case CSQUOTE:
11758                         syntax = SQSYNTAX;
11759  quotemark:
11760                         if (eofmark == NULL) {
11761                                 USTPUTC(CTLQUOTEMARK, out);
11762                         }
11763                         break;
11764                 case CDQUOTE:
11765                         syntax = DQSYNTAX;
11766                         dblquote = 1;
11767                         goto quotemark;
11768                 case CENDQUOTE:
11769                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11770                         if (eofmark != NULL && varnest == 0) {
11771                                 USTPUTC(c, out);
11772                         } else {
11773                                 if (dqvarnest == 0) {
11774                                         syntax = BASESYNTAX;
11775                                         dblquote = 0;
11776                                 }
11777                                 quotef = 1;
11778                                 goto quotemark;
11779                         }
11780                         break;
11781                 case CVAR:      /* '$' */
11782                         PARSESUB();             /* parse substitution */
11783                         break;
11784                 case CENDVAR:   /* '}' */
11785                         if (varnest > 0) {
11786                                 varnest--;
11787                                 if (dqvarnest > 0) {
11788                                         dqvarnest--;
11789                                 }
11790                                 c = CTLENDVAR;
11791                         }
11792                         USTPUTC(c, out);
11793                         break;
11794 #if ENABLE_FEATURE_SH_MATH
11795                 case CLP:       /* '(' in arithmetic */
11796                         parenlevel++;
11797                         USTPUTC(c, out);
11798                         break;
11799                 case CRP:       /* ')' in arithmetic */
11800                         if (parenlevel > 0) {
11801                                 parenlevel--;
11802                         } else {
11803                                 if (pgetc_eatbnl() == ')') {
11804                                         c = CTLENDARI;
11805                                         if (--arinest == 0) {
11806                                                 syntax = prevsyntax;
11807                                         }
11808                                 } else {
11809                                         /*
11810                                          * unbalanced parens
11811                                          * (don't 2nd guess - no error)
11812                                          */
11813                                         pungetc();
11814                                 }
11815                         }
11816                         USTPUTC(c, out);
11817                         break;
11818 #endif
11819                 case CBQUOTE:   /* '`' */
11820                         PARSEBACKQOLD();
11821                         break;
11822                 case CENDFILE:
11823                         goto endword;           /* exit outer loop */
11824                 case CIGN:
11825                         break;
11826                 default:
11827                         if (varnest == 0) {
11828 #if BASH_REDIR_OUTPUT
11829                                 if (c == '&') {
11830 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11831                                         if (pgetc() == '>')
11832                                                 c = 0x100 + '>'; /* flag &> */
11833                                         pungetc();
11834                                 }
11835 #endif
11836                                 goto endword;   /* exit outer loop */
11837                         }
11838                         IF_ASH_ALIAS(if (c != PEOA))
11839                                 USTPUTC(c, out);
11840                 }
11841                 c = pgetc();
11842         } /* for (;;) */
11843  endword:
11844
11845 #if ENABLE_FEATURE_SH_MATH
11846         if (syntax == ARISYNTAX)
11847                 raise_error_syntax("missing '))'");
11848 #endif
11849         if (syntax != BASESYNTAX && eofmark == NULL)
11850                 raise_error_syntax("unterminated quoted string");
11851         if (varnest != 0) {
11852                 startlinno = g_parsefile->linno;
11853                 /* { */
11854                 raise_error_syntax("missing '}'");
11855         }
11856         USTPUTC('\0', out);
11857         len = out - (char *)stackblock();
11858         out = stackblock();
11859         if (eofmark == NULL) {
11860                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11861                  && quotef == 0
11862                 ) {
11863                         if (isdigit_str9(out)) {
11864                                 PARSEREDIR(); /* passed as params: out, c */
11865                                 lasttoken = TREDIR;
11866                                 return lasttoken;
11867                         }
11868                         /* else: non-number X seen, interpret it
11869                          * as "NNNX>file" = "NNNX >file" */
11870                 }
11871                 pungetc();
11872         }
11873         quoteflag = quotef;
11874         backquotelist = bqlist;
11875         grabstackblock(len);
11876         wordtext = out;
11877         lasttoken = TWORD;
11878         return lasttoken;
11879 /* end of readtoken routine */
11880
11881 /*
11882  * Check to see whether we are at the end of the here document.  When this
11883  * is called, c is set to the first character of the next input line.  If
11884  * we are at the end of the here document, this routine sets the c to PEOF.
11885  */
11886 checkend: {
11887         if (realeofmark(eofmark)) {
11888                 int markloc;
11889                 char *p;
11890
11891 #if ENABLE_ASH_ALIAS
11892                 if (c == PEOA)
11893                         c = pgetc_without_PEOA();
11894 #endif
11895                 if (striptabs) {
11896                         while (c == '\t') {
11897                                 c = pgetc_without_PEOA();
11898                         }
11899                 }
11900
11901                 markloc = out - (char *)stackblock();
11902                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11903                         if (c != *p)
11904                                 goto more_heredoc;
11905
11906                         c = pgetc_without_PEOA();
11907                 }
11908
11909                 if (c == '\n' || c == PEOF) {
11910                         c = PEOF;
11911                         g_parsefile->linno++;
11912                         needprompt = doprompt;
11913                 } else {
11914                         int len_here;
11915
11916  more_heredoc:
11917                         p = (char *)stackblock() + markloc + 1;
11918                         len_here = out - p;
11919
11920                         if (len_here) {
11921                                 len_here -= (c >= PEOF);
11922                                 c = p[-1];
11923
11924                                 if (len_here) {
11925                                         char *str;
11926
11927                                         str = alloca(len_here + 1);
11928                                         *(char *)mempcpy(str, p, len_here) = '\0';
11929
11930                                         pushstring(str, NULL);
11931                                 }
11932                         }
11933                 }
11934
11935                 STADJUST((char *)stackblock() + markloc - out, out);
11936         }
11937         goto checkend_return;
11938 }
11939
11940 /*
11941  * Parse a redirection operator.  The variable "out" points to a string
11942  * specifying the fd to be redirected.  The variable "c" contains the
11943  * first character of the redirection operator.
11944  */
11945 parseredir: {
11946         /* out is already checked to be a valid number or "" */
11947         int fd = (*out == '\0' ? -1 : atoi(out));
11948         union node *np;
11949
11950         np = stzalloc(sizeof(struct nfile));
11951         if (c == '>') {
11952                 np->nfile.fd = 1;
11953                 c = pgetc();
11954                 if (c == '>')
11955                         np->type = NAPPEND;
11956                 else if (c == '|')
11957                         np->type = NCLOBBER;
11958                 else if (c == '&')
11959                         np->type = NTOFD;
11960                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11961                 else {
11962                         np->type = NTO;
11963                         pungetc();
11964                 }
11965         }
11966 #if BASH_REDIR_OUTPUT
11967         else if (c == 0x100 + '>') { /* this flags &> redirection */
11968                 np->nfile.fd = 1;
11969                 pgetc(); /* this is '>', no need to check */
11970                 np->type = NTO2;
11971         }
11972 #endif
11973         else { /* c == '<' */
11974                 /*np->nfile.fd = 0; - stzalloc did it */
11975                 c = pgetc();
11976                 switch (c) {
11977                 case '<':
11978                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11979                                 np = stzalloc(sizeof(struct nhere));
11980                                 /*np->nfile.fd = 0; - stzalloc did it */
11981                         }
11982                         np->type = NHERE;
11983                         heredoc = stzalloc(sizeof(struct heredoc));
11984                         heredoc->here = np;
11985                         c = pgetc();
11986                         if (c == '-') {
11987                                 heredoc->striptabs = 1;
11988                         } else {
11989                                 /*heredoc->striptabs = 0; - stzalloc did it */
11990                                 pungetc();
11991                         }
11992                         break;
11993
11994                 case '&':
11995                         np->type = NFROMFD;
11996                         break;
11997
11998                 case '>':
11999                         np->type = NFROMTO;
12000                         break;
12001
12002                 default:
12003                         np->type = NFROM;
12004                         pungetc();
12005                         break;
12006                 }
12007         }
12008         if (fd >= 0)
12009                 np->nfile.fd = fd;
12010         redirnode = np;
12011         goto parseredir_return;
12012 }
12013
12014 /*
12015  * Parse a substitution.  At this point, we have read the dollar sign
12016  * and nothing else.
12017  */
12018
12019 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12020  * (assuming ascii char codes, as the original implementation did) */
12021 #define is_special(c) \
12022         (((unsigned)(c) - 33 < 32) \
12023                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12024 parsesub: {
12025         unsigned char subtype;
12026         int typeloc;
12027
12028         c = pgetc_eatbnl();
12029         if ((checkkwd & CHKEOFMARK)
12030          || c > 255 /* PEOA or PEOF */
12031          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12032         ) {
12033 #if BASH_DOLLAR_SQUOTE
12034                 if (syntax != DQSYNTAX && c == '\'')
12035                         bash_dollar_squote = 1;
12036                 else
12037 #endif
12038                         USTPUTC('$', out);
12039                 pungetc();
12040         } else if (c == '(') {
12041                 /* $(command) or $((arith)) */
12042                 if (pgetc_eatbnl() == '(') {
12043 #if ENABLE_FEATURE_SH_MATH
12044                         PARSEARITH();
12045 #else
12046                         raise_error_syntax("support for $((arith)) is disabled");
12047 #endif
12048                 } else {
12049                         pungetc();
12050                         PARSEBACKQNEW();
12051                 }
12052         } else {
12053                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12054                 USTPUTC(CTLVAR, out);
12055                 typeloc = out - (char *)stackblock();
12056                 STADJUST(1, out);
12057                 subtype = VSNORMAL;
12058                 if (c == '{') {
12059                         c = pgetc_eatbnl();
12060                         subtype = 0;
12061                 }
12062  varname:
12063                 if (is_name(c)) {
12064                         /* $[{[#]]NAME[}] */
12065                         do {
12066                                 STPUTC(c, out);
12067                                 c = pgetc_eatbnl();
12068                         } while (is_in_name(c));
12069                 } else if (isdigit(c)) {
12070                         /* $[{[#]]NUM[}] */
12071                         do {
12072                                 STPUTC(c, out);
12073                                 c = pgetc_eatbnl();
12074                         } while (isdigit(c));
12075                 } else if (is_special(c)) {
12076                         /* $[{[#]]<specialchar>[}] */
12077                         int cc = c;
12078
12079                         c = pgetc_eatbnl();
12080                         if (!subtype && cc == '#') {
12081                                 subtype = VSLENGTH;
12082                                 if (c == '_' || isalnum(c))
12083                                         goto varname;
12084                                 cc = c;
12085                                 c = pgetc_eatbnl();
12086                                 if (cc == '}' || c != '}') {
12087                                         pungetc();
12088                                         subtype = 0;
12089                                         c = cc;
12090                                         cc = '#';
12091                                 }
12092                         }
12093                         USTPUTC(cc, out);
12094                 } else {
12095                         goto badsub;
12096                 }
12097                 if (c != '}' && subtype == VSLENGTH) {
12098                         /* ${#VAR didn't end with } */
12099                         goto badsub;
12100                 }
12101
12102                 if (subtype == 0) {
12103                         static const char types[] ALIGN1 = "}-+?=";
12104                         /* ${VAR...} but not $VAR or ${#VAR} */
12105                         /* c == first char after VAR */
12106                         switch (c) {
12107                         case ':':
12108                                 c = pgetc_eatbnl();
12109 #if BASH_SUBSTR
12110                                 /* This check is only needed to not misinterpret
12111                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12112                                  * constructs.
12113                                  */
12114                                 if (!strchr(types, c)) {
12115                                         subtype = VSSUBSTR;
12116                                         pungetc();
12117                                         break; /* "goto badsub" is bigger (!) */
12118                                 }
12119 #endif
12120                                 subtype = VSNUL;
12121                                 /*FALLTHROUGH*/
12122                         default: {
12123                                 const char *p = strchr(types, c);
12124                                 if (p == NULL)
12125                                         break;
12126                                 subtype |= p - types + VSNORMAL;
12127                                 break;
12128                         }
12129                         case '%':
12130                         case '#': {
12131                                 int cc = c;
12132                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12133                                 c = pgetc_eatbnl();
12134                                 if (c != cc)
12135                                         goto badsub;
12136                                 subtype++;
12137                                 break;
12138                         }
12139 #if BASH_PATTERN_SUBST
12140                         case '/':
12141                                 /* ${v/[/]pattern/repl} */
12142 //TODO: encode pattern and repl separately.
12143 // Currently ${v/$var_with_slash/repl} is horribly broken
12144                                 subtype = VSREPLACE;
12145                                 c = pgetc_eatbnl();
12146                                 if (c != '/')
12147                                         goto badsub;
12148                                 subtype++; /* VSREPLACEALL */
12149                                 break;
12150 #endif
12151                         }
12152                 } else {
12153  badsub:
12154                         pungetc();
12155                 }
12156                 ((unsigned char *)stackblock())[typeloc] = subtype;
12157                 if (subtype != VSNORMAL) {
12158                         varnest++;
12159                         if (dblquote)
12160                                 dqvarnest++;
12161                 }
12162                 STPUTC('=', out);
12163         }
12164         goto parsesub_return;
12165 }
12166
12167 /*
12168  * Called to parse command substitutions.  Newstyle is set if the command
12169  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12170  * list of commands (passed by reference), and savelen is the number of
12171  * characters on the top of the stack which must be preserved.
12172  */
12173 parsebackq: {
12174         struct nodelist **nlpp;
12175         union node *n;
12176         char *str;
12177         size_t savelen;
12178         smallint saveprompt = 0;
12179
12180         str = NULL;
12181         savelen = out - (char *)stackblock();
12182         if (savelen > 0) {
12183                 /*
12184                  * FIXME: this can allocate very large block on stack and SEGV.
12185                  * Example:
12186                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12187                  * allocates 100kb for every command subst. With about
12188                  * a hundred command substitutions stack overflows.
12189                  * With larger prepended string, SEGV happens sooner.
12190                  */
12191                 str = alloca(savelen);
12192                 memcpy(str, stackblock(), savelen);
12193         }
12194
12195         if (oldstyle) {
12196                 /* We must read until the closing backquote, giving special
12197                  * treatment to some slashes, and then push the string and
12198                  * reread it as input, interpreting it normally.
12199                  */
12200                 char *pout;
12201                 size_t psavelen;
12202                 char *pstr;
12203
12204                 STARTSTACKSTR(pout);
12205                 for (;;) {
12206                         int pc;
12207
12208                         setprompt_if(needprompt, 2);
12209                         pc = pgetc();
12210                         switch (pc) {
12211                         case '`':
12212                                 goto done;
12213
12214                         case '\\':
12215                                 pc = pgetc();
12216                                 if (pc == '\n') {
12217                                         nlprompt();
12218                                         /*
12219                                          * If eating a newline, avoid putting
12220                                          * the newline into the new character
12221                                          * stream (via the STPUTC after the
12222                                          * switch).
12223                                          */
12224                                         continue;
12225                                 }
12226                                 if (pc != '\\' && pc != '`' && pc != '$'
12227                                  && (!dblquote || pc != '"')
12228                                 ) {
12229                                         STPUTC('\\', pout);
12230                                 }
12231                                 if (pc <= 255 /* not PEOA or PEOF */) {
12232                                         break;
12233                                 }
12234                                 /* fall through */
12235
12236                         case PEOF:
12237                         IF_ASH_ALIAS(case PEOA:)
12238                                 startlinno = g_parsefile->linno;
12239                                 raise_error_syntax("EOF in backquote substitution");
12240
12241                         case '\n':
12242                                 nlnoprompt();
12243                                 break;
12244
12245                         default:
12246                                 break;
12247                         }
12248                         STPUTC(pc, pout);
12249                 }
12250  done:
12251                 STPUTC('\0', pout);
12252                 psavelen = pout - (char *)stackblock();
12253                 if (psavelen > 0) {
12254                         pstr = grabstackstr(pout);
12255                         setinputstring(pstr);
12256                 }
12257         }
12258         nlpp = &bqlist;
12259         while (*nlpp)
12260                 nlpp = &(*nlpp)->next;
12261         *nlpp = stzalloc(sizeof(**nlpp));
12262         /* (*nlpp)->next = NULL; - stzalloc did it */
12263
12264         if (oldstyle) {
12265                 saveprompt = doprompt;
12266                 doprompt = 0;
12267         }
12268
12269         n = list(2);
12270
12271         if (oldstyle)
12272                 doprompt = saveprompt;
12273         else if (readtoken() != TRP)
12274                 raise_error_unexpected_syntax(TRP);
12275
12276         (*nlpp)->n = n;
12277         if (oldstyle) {
12278                 /*
12279                  * Start reading from old file again, ignoring any pushed back
12280                  * tokens left from the backquote parsing
12281                  */
12282                 popfile();
12283                 tokpushback = 0;
12284         }
12285         while (stackblocksize() <= savelen)
12286                 growstackblock();
12287         STARTSTACKSTR(out);
12288         if (str) {
12289                 memcpy(out, str, savelen);
12290                 STADJUST(savelen, out);
12291         }
12292         USTPUTC(CTLBACKQ, out);
12293         if (oldstyle)
12294                 goto parsebackq_oldreturn;
12295         goto parsebackq_newreturn;
12296 }
12297
12298 #if ENABLE_FEATURE_SH_MATH
12299 /*
12300  * Parse an arithmetic expansion (indicate start of one and set state)
12301  */
12302 parsearith: {
12303         if (++arinest == 1) {
12304                 prevsyntax = syntax;
12305                 syntax = ARISYNTAX;
12306         }
12307         USTPUTC(CTLARI, out);
12308         goto parsearith_return;
12309 }
12310 #endif
12311 } /* end of readtoken */
12312
12313 /*
12314  * Read the next input token.
12315  * If the token is a word, we set backquotelist to the list of cmds in
12316  *      backquotes.  We set quoteflag to true if any part of the word was
12317  *      quoted.
12318  * If the token is TREDIR, then we set redirnode to a structure containing
12319  *      the redirection.
12320  * In all cases, the variable startlinno is set to the number of the line
12321  *      on which the token starts.
12322  *
12323  * [Change comment:  here documents and internal procedures]
12324  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12325  *  word parsing code into a separate routine.  In this case, readtoken
12326  *  doesn't need to have any internal procedures, but parseword does.
12327  *  We could also make parseoperator in essence the main routine, and
12328  *  have parseword (readtoken1?) handle both words and redirection.]
12329  */
12330 #define NEW_xxreadtoken
12331 #ifdef NEW_xxreadtoken
12332 /* singles must be first! */
12333 static const char xxreadtoken_chars[7] ALIGN1 = {
12334         '\n', '(', ')', /* singles */
12335         '&', '|', ';',  /* doubles */
12336         0
12337 };
12338
12339 #define xxreadtoken_singles 3
12340 #define xxreadtoken_doubles 3
12341
12342 static const char xxreadtoken_tokens[] ALIGN1 = {
12343         TNL, TLP, TRP,          /* only single occurrence allowed */
12344         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12345         TEOF,                   /* corresponds to trailing nul */
12346         TAND, TOR, TENDCASE     /* if double occurrence */
12347 };
12348
12349 static int
12350 xxreadtoken(void)
12351 {
12352         int c;
12353
12354         if (tokpushback) {
12355                 tokpushback = 0;
12356                 return lasttoken;
12357         }
12358         setprompt_if(needprompt, 2);
12359         startlinno = g_parsefile->linno;
12360         for (;;) {                      /* until token or start of word found */
12361                 c = pgetc();
12362                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12363                         continue;
12364
12365                 if (c == '#') {
12366                         while ((c = pgetc()) != '\n' && c != PEOF)
12367                                 continue;
12368                         pungetc();
12369                 } else if (c == '\\') {
12370                         if (pgetc() != '\n') {
12371                                 pungetc();
12372                                 break; /* return readtoken1(...) */
12373                         }
12374                         nlprompt();
12375                 } else {
12376                         const char *p;
12377
12378                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12379                         if (c != PEOF) {
12380                                 if (c == '\n') {
12381                                         nlnoprompt();
12382                                 }
12383
12384                                 p = strchr(xxreadtoken_chars, c);
12385                                 if (p == NULL)
12386                                         break; /* return readtoken1(...) */
12387
12388                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12389                                         int cc = pgetc();
12390                                         if (cc == c) {    /* double occurrence? */
12391                                                 p += xxreadtoken_doubles + 1;
12392                                         } else {
12393                                                 pungetc();
12394 #if BASH_REDIR_OUTPUT
12395                                                 if (c == '&' && cc == '>') /* &> */
12396                                                         break; /* return readtoken1(...) */
12397 #endif
12398                                         }
12399                                 }
12400                         }
12401                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12402                         return lasttoken;
12403                 }
12404         } /* for (;;) */
12405
12406         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12407 }
12408 #else /* old xxreadtoken */
12409 #define RETURN(token)   return lasttoken = token
12410 static int
12411 xxreadtoken(void)
12412 {
12413         int c;
12414
12415         if (tokpushback) {
12416                 tokpushback = 0;
12417                 return lasttoken;
12418         }
12419         setprompt_if(needprompt, 2);
12420         startlinno = g_parsefile->linno;
12421         for (;;) {      /* until token or start of word found */
12422                 c = pgetc();
12423                 switch (c) {
12424                 case ' ': case '\t':
12425                 IF_ASH_ALIAS(case PEOA:)
12426                         continue;
12427                 case '#':
12428                         while ((c = pgetc()) != '\n' && c != PEOF)
12429                                 continue;
12430                         pungetc();
12431                         continue;
12432                 case '\\':
12433                         if (pgetc() == '\n') {
12434                                 nlprompt();
12435                                 continue;
12436                         }
12437                         pungetc();
12438                         goto breakloop;
12439                 case '\n':
12440                         nlnoprompt();
12441                         RETURN(TNL);
12442                 case PEOF:
12443                         RETURN(TEOF);
12444                 case '&':
12445                         if (pgetc() == '&')
12446                                 RETURN(TAND);
12447                         pungetc();
12448                         RETURN(TBACKGND);
12449                 case '|':
12450                         if (pgetc() == '|')
12451                                 RETURN(TOR);
12452                         pungetc();
12453                         RETURN(TPIPE);
12454                 case ';':
12455                         if (pgetc() == ';')
12456                                 RETURN(TENDCASE);
12457                         pungetc();
12458                         RETURN(TSEMI);
12459                 case '(':
12460                         RETURN(TLP);
12461                 case ')':
12462                         RETURN(TRP);
12463                 default:
12464                         goto breakloop;
12465                 }
12466         }
12467  breakloop:
12468         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12469 #undef RETURN
12470 }
12471 #endif /* old xxreadtoken */
12472
12473 static int
12474 readtoken(void)
12475 {
12476         int t;
12477         int kwd = checkkwd;
12478 #if DEBUG
12479         smallint alreadyseen = tokpushback;
12480 #endif
12481
12482 #if ENABLE_ASH_ALIAS
12483  top:
12484 #endif
12485
12486         t = xxreadtoken();
12487
12488         /*
12489          * eat newlines
12490          */
12491         if (kwd & CHKNL) {
12492                 while (t == TNL) {
12493                         parseheredoc();
12494                         t = xxreadtoken();
12495                 }
12496         }
12497
12498         if (t != TWORD || quoteflag) {
12499                 goto out;
12500         }
12501
12502         /*
12503          * check for keywords
12504          */
12505         if (kwd & CHKKWD) {
12506                 const char *const *pp;
12507
12508                 pp = findkwd(wordtext);
12509                 if (pp) {
12510                         lasttoken = t = pp - tokname_array;
12511                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12512                         goto out;
12513                 }
12514         }
12515
12516         if (checkkwd & CHKALIAS) {
12517 #if ENABLE_ASH_ALIAS
12518                 struct alias *ap;
12519                 ap = lookupalias(wordtext, 1);
12520                 if (ap != NULL) {
12521                         if (*ap->val) {
12522                                 pushstring(ap->val, ap);
12523                         }
12524                         goto top;
12525                 }
12526 #endif
12527         }
12528  out:
12529         checkkwd = 0;
12530 #if DEBUG
12531         if (!alreadyseen)
12532                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12533         else
12534                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12535 #endif
12536         return t;
12537 }
12538
12539 static int
12540 peektoken(void)
12541 {
12542         int t;
12543
12544         t = readtoken();
12545         tokpushback = 1;
12546         return t;
12547 }
12548
12549 /*
12550  * Read and parse a command.  Returns NODE_EOF on end of file.
12551  * (NULL is a valid parse tree indicating a blank line.)
12552  */
12553 static union node *
12554 parsecmd(int interact)
12555 {
12556         tokpushback = 0;
12557         checkkwd = 0;
12558         heredoclist = 0;
12559         doprompt = interact;
12560         setprompt_if(doprompt, doprompt);
12561         needprompt = 0;
12562         return list(1);
12563 }
12564
12565 /*
12566  * Input any here documents.
12567  */
12568 static void
12569 parseheredoc(void)
12570 {
12571         struct heredoc *here;
12572         union node *n;
12573
12574         here = heredoclist;
12575         heredoclist = NULL;
12576
12577         while (here) {
12578                 setprompt_if(needprompt, 2);
12579                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12580                                 here->eofmark, here->striptabs);
12581                 n = stzalloc(sizeof(struct narg));
12582                 n->narg.type = NARG;
12583                 /*n->narg.next = NULL; - stzalloc did it */
12584                 n->narg.text = wordtext;
12585                 n->narg.backquote = backquotelist;
12586                 here->here->nhere.doc = n;
12587                 here = here->next;
12588         }
12589 }
12590
12591
12592 static const char *
12593 expandstr(const char *ps, int syntax_type)
12594 {
12595         union node n;
12596         int saveprompt;
12597
12598         /* XXX Fix (char *) cast. */
12599         setinputstring((char *)ps);
12600
12601         saveprompt = doprompt;
12602         doprompt = 0;
12603         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12604         doprompt = saveprompt;
12605
12606         popfile();
12607
12608         n.narg.type = NARG;
12609         n.narg.next = NULL;
12610         n.narg.text = wordtext;
12611         n.narg.backquote = backquotelist;
12612
12613         expandarg(&n, NULL, EXP_QUOTED);
12614         return stackblock();
12615 }
12616
12617 static inline int
12618 parser_eof(void)
12619 {
12620         return tokpushback && lasttoken == TEOF;
12621 }
12622
12623 /*
12624  * Execute a command or commands contained in a string.
12625  */
12626 static int
12627 evalstring(char *s, int flags)
12628 {
12629         struct jmploc *volatile savehandler;
12630         struct jmploc jmploc;
12631         int ex;
12632
12633         union node *n;
12634         struct stackmark smark;
12635         int status;
12636
12637         s = sstrdup(s);
12638         setinputstring(s);
12639         setstackmark(&smark);
12640
12641         status = 0;
12642         /* On exception inside execution loop, we must popfile().
12643          * Try interactively:
12644          *      readonly a=a
12645          *      command eval "a=b"  # throws "is read only" error
12646          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12647          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12648          */
12649         savehandler = exception_handler;
12650         ex = setjmp(jmploc.loc);
12651         if (ex)
12652                 goto out;
12653         exception_handler = &jmploc;
12654
12655         while ((n = parsecmd(0)) != NODE_EOF) {
12656                 int i;
12657
12658                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12659                 if (n)
12660                         status = i;
12661                 popstackmark(&smark);
12662                 if (evalskip)
12663                         break;
12664         }
12665  out:
12666         popstackmark(&smark);
12667         popfile();
12668         stunalloc(s);
12669
12670         exception_handler = savehandler;
12671         if (ex)
12672                 longjmp(exception_handler->loc, ex);
12673
12674         return status;
12675 }
12676
12677 /*
12678  * The eval command.
12679  */
12680 static int FAST_FUNC
12681 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12682 {
12683         char *p;
12684         char *concat;
12685
12686         if (argv[1]) {
12687                 p = argv[1];
12688                 argv += 2;
12689                 if (argv[0]) {
12690                         STARTSTACKSTR(concat);
12691                         for (;;) {
12692                                 concat = stack_putstr(p, concat);
12693                                 p = *argv++;
12694                                 if (p == NULL)
12695                                         break;
12696                                 STPUTC(' ', concat);
12697                         }
12698                         STPUTC('\0', concat);
12699                         p = grabstackstr(concat);
12700                 }
12701                 return evalstring(p, flags & EV_TESTED);
12702         }
12703         return 0;
12704 }
12705
12706 /*
12707  * Read and execute commands.
12708  * "Top" is nonzero for the top level command loop;
12709  * it turns on prompting if the shell is interactive.
12710  */
12711 static int
12712 cmdloop(int top)
12713 {
12714         union node *n;
12715         struct stackmark smark;
12716         int inter;
12717         int status = 0;
12718         int numeof = 0;
12719
12720         TRACE(("cmdloop(%d) called\n", top));
12721         for (;;) {
12722                 int skip;
12723
12724                 setstackmark(&smark);
12725 #if JOBS
12726                 if (doing_jobctl)
12727                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12728 #endif
12729                 inter = 0;
12730                 if (iflag && top) {
12731                         inter++;
12732                         chkmail();
12733                 }
12734                 n = parsecmd(inter);
12735 #if DEBUG
12736                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12737                         showtree(n);
12738 #endif
12739                 if (n == NODE_EOF) {
12740                         if (!top || numeof >= 50)
12741                                 break;
12742                         if (!stoppedjobs()) {
12743                                 if (!Iflag)
12744                                         break;
12745                                 out2str("\nUse \"exit\" to leave shell.\n");
12746                         }
12747                         numeof++;
12748                 } else if (nflag == 0) {
12749                         int i;
12750
12751                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12752                         job_warning >>= 1;
12753                         numeof = 0;
12754                         i = evaltree(n, 0);
12755                         if (n)
12756                                 status = i;
12757                 }
12758                 popstackmark(&smark);
12759                 skip = evalskip;
12760
12761                 if (skip) {
12762                         evalskip &= ~SKIPFUNC;
12763                         break;
12764                 }
12765         }
12766         return status;
12767 }
12768
12769 /*
12770  * Take commands from a file.  To be compatible we should do a path
12771  * search for the file, which is necessary to find sub-commands.
12772  */
12773 static char *
12774 find_dot_file(char *name)
12775 {
12776         char *fullname;
12777         const char *path = pathval();
12778         struct stat statb;
12779
12780         /* don't try this for absolute or relative paths */
12781         if (strchr(name, '/'))
12782                 return name;
12783
12784         while ((fullname = path_advance(&path, name)) != NULL) {
12785                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12786                         /*
12787                          * Don't bother freeing here, since it will
12788                          * be freed by the caller.
12789                          */
12790                         return fullname;
12791                 }
12792                 if (fullname != name)
12793                         stunalloc(fullname);
12794         }
12795
12796         /* not found in the PATH */
12797         ash_msg_and_raise_error("%s: not found", name);
12798         /* NOTREACHED */
12799 }
12800
12801 static int FAST_FUNC
12802 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12803 {
12804         /* "false; . empty_file; echo $?" should print 0, not 1: */
12805         int status = 0;
12806         char *fullname;
12807         char **argv;
12808         char *args_need_save;
12809         volatile struct shparam saveparam;
12810
12811 //???
12812 //      struct strlist *sp;
12813 //      for (sp = cmdenviron; sp; sp = sp->next)
12814 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12815
12816         nextopt(nullstr); /* handle possible "--" */
12817         argv = argptr;
12818
12819         if (!argv[0]) {
12820                 /* bash says: "bash: .: filename argument required" */
12821                 return 2; /* bash compat */
12822         }
12823
12824         /* This aborts if file isn't found, which is POSIXly correct.
12825          * bash returns exitcode 1 instead.
12826          */
12827         fullname = find_dot_file(argv[0]);
12828         argv++;
12829         args_need_save = argv[0];
12830         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12831                 int argc;
12832                 saveparam = shellparam;
12833                 shellparam.malloced = 0;
12834                 argc = 1;
12835                 while (argv[argc])
12836                         argc++;
12837                 shellparam.nparam = argc;
12838                 shellparam.p = argv;
12839         };
12840
12841         /* This aborts if file can't be opened, which is POSIXly correct.
12842          * bash returns exitcode 1 instead.
12843          */
12844         setinputfile(fullname, INPUT_PUSH_FILE);
12845         commandname = fullname;
12846         status = cmdloop(0);
12847         popfile();
12848
12849         if (args_need_save) {
12850                 freeparam(&shellparam);
12851                 shellparam = saveparam;
12852         };
12853
12854         return status;
12855 }
12856
12857 static int FAST_FUNC
12858 exitcmd(int argc UNUSED_PARAM, char **argv)
12859 {
12860         if (stoppedjobs())
12861                 return 0;
12862         if (argv[1])
12863                 exitstatus = number(argv[1]);
12864         raise_exception(EXEXIT);
12865         /* NOTREACHED */
12866 }
12867
12868 /*
12869  * Read a file containing shell functions.
12870  */
12871 static void
12872 readcmdfile(char *name)
12873 {
12874         setinputfile(name, INPUT_PUSH_FILE);
12875         cmdloop(0);
12876         popfile();
12877 }
12878
12879
12880 /* ============ find_command inplementation */
12881
12882 /*
12883  * Resolve a command name.  If you change this routine, you may have to
12884  * change the shellexec routine as well.
12885  */
12886 static void
12887 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12888 {
12889         struct tblentry *cmdp;
12890         int idx;
12891         int prev;
12892         char *fullname;
12893         struct stat statb;
12894         int e;
12895         int updatetbl;
12896         struct builtincmd *bcmd;
12897
12898         /* If name contains a slash, don't use PATH or hash table */
12899         if (strchr(name, '/') != NULL) {
12900                 entry->u.index = -1;
12901                 if (act & DO_ABS) {
12902                         while (stat(name, &statb) < 0) {
12903 #ifdef SYSV
12904                                 if (errno == EINTR)
12905                                         continue;
12906 #endif
12907                                 entry->cmdtype = CMDUNKNOWN;
12908                                 return;
12909                         }
12910                 }
12911                 entry->cmdtype = CMDNORMAL;
12912                 return;
12913         }
12914
12915 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12916
12917         updatetbl = (path == pathval());
12918         if (!updatetbl) {
12919                 act |= DO_ALTPATH;
12920                 if (strstr(path, "%builtin") != NULL)
12921                         act |= DO_ALTBLTIN;
12922         }
12923
12924         /* If name is in the table, check answer will be ok */
12925         cmdp = cmdlookup(name, 0);
12926         if (cmdp != NULL) {
12927                 int bit;
12928
12929                 switch (cmdp->cmdtype) {
12930                 default:
12931 #if DEBUG
12932                         abort();
12933 #endif
12934                 case CMDNORMAL:
12935                         bit = DO_ALTPATH;
12936                         break;
12937                 case CMDFUNCTION:
12938                         bit = DO_NOFUNC;
12939                         break;
12940                 case CMDBUILTIN:
12941                         bit = DO_ALTBLTIN;
12942                         break;
12943                 }
12944                 if (act & bit) {
12945                         updatetbl = 0;
12946                         cmdp = NULL;
12947                 } else if (cmdp->rehash == 0)
12948                         /* if not invalidated by cd, we're done */
12949                         goto success;
12950         }
12951
12952         /* If %builtin not in path, check for builtin next */
12953         bcmd = find_builtin(name);
12954         if (bcmd) {
12955                 if (IS_BUILTIN_REGULAR(bcmd))
12956                         goto builtin_success;
12957                 if (act & DO_ALTPATH) {
12958                         if (!(act & DO_ALTBLTIN))
12959                                 goto builtin_success;
12960                 } else if (builtinloc <= 0) {
12961                         goto builtin_success;
12962                 }
12963         }
12964
12965 #if ENABLE_FEATURE_SH_STANDALONE
12966         {
12967                 int applet_no = find_applet_by_name(name);
12968                 if (applet_no >= 0) {
12969                         entry->cmdtype = CMDNORMAL;
12970                         entry->u.index = -2 - applet_no;
12971                         return;
12972                 }
12973         }
12974 #endif
12975
12976         /* We have to search path. */
12977         prev = -1;              /* where to start */
12978         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12979                 if (cmdp->cmdtype == CMDBUILTIN)
12980                         prev = builtinloc;
12981                 else
12982                         prev = cmdp->param.index;
12983         }
12984
12985         e = ENOENT;
12986         idx = -1;
12987  loop:
12988         while ((fullname = path_advance(&path, name)) != NULL) {
12989                 stunalloc(fullname);
12990                 /* NB: code below will still use fullname
12991                  * despite it being "unallocated" */
12992                 idx++;
12993                 if (pathopt) {
12994                         if (prefix(pathopt, "builtin")) {
12995                                 if (bcmd)
12996                                         goto builtin_success;
12997                                 continue;
12998                         }
12999                         if ((act & DO_NOFUNC)
13000                          || !prefix(pathopt, "func")
13001                         ) {     /* ignore unimplemented options */
13002                                 continue;
13003                         }
13004                 }
13005                 /* if rehash, don't redo absolute path names */
13006                 if (fullname[0] == '/' && idx <= prev) {
13007                         if (idx < prev)
13008                                 continue;
13009                         TRACE(("searchexec \"%s\": no change\n", name));
13010                         goto success;
13011                 }
13012                 while (stat(fullname, &statb) < 0) {
13013 #ifdef SYSV
13014                         if (errno == EINTR)
13015                                 continue;
13016 #endif
13017                         if (errno != ENOENT && errno != ENOTDIR)
13018                                 e = errno;
13019                         goto loop;
13020                 }
13021                 e = EACCES;     /* if we fail, this will be the error */
13022                 if (!S_ISREG(statb.st_mode))
13023                         continue;
13024                 if (pathopt) {          /* this is a %func directory */
13025                         stalloc(strlen(fullname) + 1);
13026                         /* NB: stalloc will return space pointed by fullname
13027                          * (because we don't have any intervening allocations
13028                          * between stunalloc above and this stalloc) */
13029                         readcmdfile(fullname);
13030                         cmdp = cmdlookup(name, 0);
13031                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13032                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13033                         stunalloc(fullname);
13034                         goto success;
13035                 }
13036                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13037                 if (!updatetbl) {
13038                         entry->cmdtype = CMDNORMAL;
13039                         entry->u.index = idx;
13040                         return;
13041                 }
13042                 INT_OFF;
13043                 cmdp = cmdlookup(name, 1);
13044                 cmdp->cmdtype = CMDNORMAL;
13045                 cmdp->param.index = idx;
13046                 INT_ON;
13047                 goto success;
13048         }
13049
13050         /* We failed.  If there was an entry for this command, delete it */
13051         if (cmdp && updatetbl)
13052                 delete_cmd_entry();
13053         if (act & DO_ERR)
13054                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13055         entry->cmdtype = CMDUNKNOWN;
13056         return;
13057
13058  builtin_success:
13059         if (!updatetbl) {
13060                 entry->cmdtype = CMDBUILTIN;
13061                 entry->u.cmd = bcmd;
13062                 return;
13063         }
13064         INT_OFF;
13065         cmdp = cmdlookup(name, 1);
13066         cmdp->cmdtype = CMDBUILTIN;
13067         cmdp->param.cmd = bcmd;
13068         INT_ON;
13069  success:
13070         cmdp->rehash = 0;
13071         entry->cmdtype = cmdp->cmdtype;
13072         entry->u = cmdp->param;
13073 }
13074
13075
13076 /*
13077  * The trap builtin.
13078  */
13079 static int FAST_FUNC
13080 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13081 {
13082         char *action;
13083         char **ap;
13084         int signo, exitcode;
13085
13086         nextopt(nullstr);
13087         ap = argptr;
13088         if (!*ap) {
13089                 for (signo = 0; signo < NSIG; signo++) {
13090                         char *tr = trap_ptr[signo];
13091                         if (tr) {
13092                                 /* note: bash adds "SIG", but only if invoked
13093                                  * as "bash". If called as "sh", or if set -o posix,
13094                                  * then it prints short signal names.
13095                                  * We are printing short names: */
13096                                 out1fmt("trap -- %s %s\n",
13097                                                 single_quote(tr),
13098                                                 get_signame(signo));
13099                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13100                  * In this case, we will exit very soon, no need to free(). */
13101                                 /* if (trap_ptr != trap && tp[0]) */
13102                                 /*      free(tr); */
13103                         }
13104                 }
13105                 /*
13106                 if (trap_ptr != trap) {
13107                         free(trap_ptr);
13108                         trap_ptr = trap;
13109                 }
13110                 */
13111                 return 0;
13112         }
13113
13114         /* Why the second check?
13115          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13116          * In this case, NUM is signal no, not an action.
13117          */
13118         action = NULL;
13119         if (ap[1] && !is_number(ap[0]))
13120                 action = *ap++;
13121
13122         exitcode = 0;
13123         while (*ap) {
13124                 signo = get_signum(*ap);
13125                 if (signo < 0) {
13126                         /* Mimic bash message exactly */
13127                         ash_msg("%s: invalid signal specification", *ap);
13128                         exitcode = 1;
13129                         goto next;
13130                 }
13131                 INT_OFF;
13132                 if (action) {
13133                         if (LONE_DASH(action))
13134                                 action = NULL;
13135                         else {
13136                                 if (action[0]) /* not NULL and not "" and not "-" */
13137                                         may_have_traps = 1;
13138                                 action = ckstrdup(action);
13139                         }
13140                 }
13141                 free(trap[signo]);
13142                 trap[signo] = action;
13143                 if (signo != 0)
13144                         setsignal(signo);
13145                 INT_ON;
13146  next:
13147                 ap++;
13148         }
13149         return exitcode;
13150 }
13151
13152
13153 /* ============ Builtins */
13154
13155 #if ENABLE_ASH_HELP
13156 static int FAST_FUNC
13157 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13158 {
13159         unsigned col;
13160         unsigned i;
13161
13162         out1fmt(
13163                 "Built-in commands:\n"
13164                 "------------------\n");
13165         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13166                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13167                                         builtintab[i].name + 1);
13168                 if (col > 60) {
13169                         out1fmt("\n");
13170                         col = 0;
13171                 }
13172         }
13173 # if ENABLE_FEATURE_SH_STANDALONE
13174         {
13175                 const char *a = applet_names;
13176                 while (*a) {
13177                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13178                         if (col > 60) {
13179                                 out1fmt("\n");
13180                                 col = 0;
13181                         }
13182                         while (*a++ != '\0')
13183                                 continue;
13184                 }
13185         }
13186 # endif
13187         newline_and_flush(stdout);
13188         return EXIT_SUCCESS;
13189 }
13190 #endif
13191
13192 #if MAX_HISTORY
13193 static int FAST_FUNC
13194 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13195 {
13196         show_history(line_input_state);
13197         return EXIT_SUCCESS;
13198 }
13199 #endif
13200
13201 /*
13202  * The export and readonly commands.
13203  */
13204 static int FAST_FUNC
13205 exportcmd(int argc UNUSED_PARAM, char **argv)
13206 {
13207         struct var *vp;
13208         char *name;
13209         const char *p;
13210         char **aptr;
13211         char opt;
13212         int flag;
13213         int flag_off;
13214
13215         /* "readonly" in bash accepts, but ignores -n.
13216          * We do the same: it saves a conditional in nextopt's param.
13217          */
13218         flag_off = 0;
13219         while ((opt = nextopt("np")) != '\0') {
13220                 if (opt == 'n')
13221                         flag_off = VEXPORT;
13222         }
13223         flag = VEXPORT;
13224         if (argv[0][0] == 'r') {
13225                 flag = VREADONLY;
13226                 flag_off = 0; /* readonly ignores -n */
13227         }
13228         flag_off = ~flag_off;
13229
13230         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13231         {
13232                 aptr = argptr;
13233                 name = *aptr;
13234                 if (name) {
13235                         do {
13236                                 p = strchr(name, '=');
13237                                 if (p != NULL) {
13238                                         p++;
13239                                 } else {
13240                                         vp = *findvar(hashvar(name), name);
13241                                         if (vp) {
13242                                                 vp->flags = ((vp->flags | flag) & flag_off);
13243                                                 continue;
13244                                         }
13245                                 }
13246                                 setvar(name, p, (flag & flag_off));
13247                         } while ((name = *++aptr) != NULL);
13248                         return 0;
13249                 }
13250         }
13251
13252         /* No arguments. Show the list of exported or readonly vars.
13253          * -n is ignored.
13254          */
13255         showvars(argv[0], flag, 0);
13256         return 0;
13257 }
13258
13259 /*
13260  * Delete a function if it exists.
13261  */
13262 static void
13263 unsetfunc(const char *name)
13264 {
13265         struct tblentry *cmdp;
13266
13267         cmdp = cmdlookup(name, 0);
13268         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13269                 delete_cmd_entry();
13270 }
13271
13272 /*
13273  * The unset builtin command.  We unset the function before we unset the
13274  * variable to allow a function to be unset when there is a readonly variable
13275  * with the same name.
13276  */
13277 static int FAST_FUNC
13278 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13279 {
13280         char **ap;
13281         int i;
13282         int flag = 0;
13283
13284         while ((i = nextopt("vf")) != 0) {
13285                 flag = i;
13286         }
13287
13288         for (ap = argptr; *ap; ap++) {
13289                 if (flag != 'f') {
13290                         unsetvar(*ap);
13291                         continue;
13292                 }
13293                 if (flag != 'v')
13294                         unsetfunc(*ap);
13295         }
13296         return 0;
13297 }
13298
13299 static const unsigned char timescmd_str[] ALIGN1 = {
13300         ' ',  offsetof(struct tms, tms_utime),
13301         '\n', offsetof(struct tms, tms_stime),
13302         ' ',  offsetof(struct tms, tms_cutime),
13303         '\n', offsetof(struct tms, tms_cstime),
13304         0
13305 };
13306 static int FAST_FUNC
13307 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13308 {
13309         unsigned long clk_tck, s, t;
13310         const unsigned char *p;
13311         struct tms buf;
13312
13313         clk_tck = bb_clk_tck();
13314         times(&buf);
13315
13316         p = timescmd_str;
13317         do {
13318                 t = *(clock_t *)(((char *) &buf) + p[1]);
13319                 s = t / clk_tck;
13320                 t = t % clk_tck;
13321                 out1fmt("%lum%lu.%03lus%c",
13322                         s / 60, s % 60,
13323                         (t * 1000) / clk_tck,
13324                         p[0]);
13325                 p += 2;
13326         } while (*p);
13327
13328         return 0;
13329 }
13330
13331 #if ENABLE_FEATURE_SH_MATH
13332 /*
13333  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13334  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13335  *
13336  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13337  */
13338 static int FAST_FUNC
13339 letcmd(int argc UNUSED_PARAM, char **argv)
13340 {
13341         arith_t i;
13342
13343         argv++;
13344         if (!*argv)
13345                 ash_msg_and_raise_error("expression expected");
13346         do {
13347                 i = ash_arith(*argv);
13348         } while (*++argv);
13349
13350         return !i;
13351 }
13352 #endif
13353
13354 /*
13355  * The read builtin. Options:
13356  *      -r              Do not interpret '\' specially
13357  *      -s              Turn off echo (tty only)
13358  *      -n NCHARS       Read NCHARS max
13359  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13360  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13361  *      -u FD           Read from given FD instead of fd 0
13362  * This uses unbuffered input, which may be avoidable in some cases.
13363  * TODO: bash also has:
13364  *      -a ARRAY        Read into array[0],[1],etc
13365  *      -d DELIM        End on DELIM char, not newline
13366  *      -e              Use line editing (tty only)
13367  */
13368 static int FAST_FUNC
13369 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13370 {
13371         char *opt_n = NULL;
13372         char *opt_p = NULL;
13373         char *opt_t = NULL;
13374         char *opt_u = NULL;
13375         int read_flags = 0;
13376         const char *r;
13377         int i;
13378
13379         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13380                 switch (i) {
13381                 case 'p':
13382                         opt_p = optionarg;
13383                         break;
13384                 case 'n':
13385                         opt_n = optionarg;
13386                         break;
13387                 case 's':
13388                         read_flags |= BUILTIN_READ_SILENT;
13389                         break;
13390                 case 't':
13391                         opt_t = optionarg;
13392                         break;
13393                 case 'r':
13394                         read_flags |= BUILTIN_READ_RAW;
13395                         break;
13396                 case 'u':
13397                         opt_u = optionarg;
13398                         break;
13399                 default:
13400                         break;
13401                 }
13402         }
13403
13404         /* "read -s" needs to save/restore termios, can't allow ^C
13405          * to jump out of it.
13406          */
13407  again:
13408         INT_OFF;
13409         r = shell_builtin_read(setvar0,
13410                 argptr,
13411                 bltinlookup("IFS"), /* can be NULL */
13412                 read_flags,
13413                 opt_n,
13414                 opt_p,
13415                 opt_t,
13416                 opt_u
13417         );
13418         INT_ON;
13419
13420         if ((uintptr_t)r == 1 && errno == EINTR) {
13421                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13422                 if (pending_sig == 0)
13423                         goto again;
13424         }
13425
13426         if ((uintptr_t)r > 1)
13427                 ash_msg_and_raise_error(r);
13428
13429         return (uintptr_t)r;
13430 }
13431
13432 static int FAST_FUNC
13433 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13434 {
13435         static const char permuser[3] ALIGN1 = "ogu";
13436
13437         mode_t mask;
13438         int symbolic_mode = 0;
13439
13440         while (nextopt("S") != '\0') {
13441                 symbolic_mode = 1;
13442         }
13443
13444         INT_OFF;
13445         mask = umask(0);
13446         umask(mask);
13447         INT_ON;
13448
13449         if (*argptr == NULL) {
13450                 if (symbolic_mode) {
13451                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13452                         char *p = buf;
13453                         int i;
13454
13455                         i = 2;
13456                         for (;;) {
13457                                 *p++ = ',';
13458                                 *p++ = permuser[i];
13459                                 *p++ = '=';
13460                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13461                                 if (!(mask & 0400)) *p++ = 'r';
13462                                 if (!(mask & 0200)) *p++ = 'w';
13463                                 if (!(mask & 0100)) *p++ = 'x';
13464                                 mask <<= 3;
13465                                 if (--i < 0)
13466                                         break;
13467                         }
13468                         *p = '\0';
13469                         puts(buf + 1);
13470                 } else {
13471                         out1fmt("%04o\n", mask);
13472                 }
13473         } else {
13474                 char *modestr = *argptr;
13475                 /* numeric umasks are taken as-is */
13476                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13477                 if (!isdigit(modestr[0]))
13478                         mask ^= 0777;
13479                 mask = bb_parse_mode(modestr, mask);
13480                 if ((unsigned)mask > 0777) {
13481                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13482                 }
13483                 if (!isdigit(modestr[0]))
13484                         mask ^= 0777;
13485                 umask(mask);
13486         }
13487         return 0;
13488 }
13489
13490 static int FAST_FUNC
13491 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13492 {
13493         return shell_builtin_ulimit(argv);
13494 }
13495
13496 /* ============ main() and helpers */
13497
13498 /*
13499  * Called to exit the shell.
13500  */
13501 static void
13502 exitshell(void)
13503 {
13504         struct jmploc loc;
13505         char *p;
13506         int status;
13507
13508 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13509         save_history(line_input_state);
13510 #endif
13511         status = exitstatus;
13512         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13513         if (setjmp(loc.loc)) {
13514                 if (exception_type == EXEXIT)
13515                         status = exitstatus;
13516                 goto out;
13517         }
13518         exception_handler = &loc;
13519         p = trap[0];
13520         if (p) {
13521                 trap[0] = NULL;
13522                 evalskip = 0;
13523                 evalstring(p, 0);
13524                 /*free(p); - we'll exit soon */
13525         }
13526  out:
13527         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13528          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13529          */
13530         setjobctl(0);
13531         flush_stdout_stderr();
13532         _exit(status);
13533         /* NOTREACHED */
13534 }
13535
13536 static void
13537 init(void)
13538 {
13539         /* we will never free this */
13540         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13541
13542         sigmode[SIGCHLD - 1] = S_DFL;
13543         setsignal(SIGCHLD);
13544
13545         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13546          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13547          */
13548         signal(SIGHUP, SIG_DFL);
13549
13550         {
13551                 char **envp;
13552                 const char *p;
13553                 struct stat st1, st2;
13554
13555                 initvar();
13556                 for (envp = environ; envp && *envp; envp++) {
13557                         p = endofname(*envp);
13558                         if (p != *envp && *p == '=') {
13559                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13560                         }
13561                 }
13562
13563                 setvareq((char*)defoptindvar, VTEXTFIXED);
13564
13565                 setvar0("PPID", utoa(getppid()));
13566 #if BASH_SHLVL_VAR
13567                 p = lookupvar("SHLVL");
13568                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13569 #endif
13570 #if BASH_HOSTNAME_VAR
13571                 if (!lookupvar("HOSTNAME")) {
13572                         struct utsname uts;
13573                         uname(&uts);
13574                         setvar0("HOSTNAME", uts.nodename);
13575                 }
13576 #endif
13577                 p = lookupvar("PWD");
13578                 if (p) {
13579                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13580                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13581                         ) {
13582                                 p = NULL;
13583                         }
13584                 }
13585                 setpwd(p, 0);
13586         }
13587 }
13588
13589
13590 //usage:#define ash_trivial_usage
13591 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13592 //usage:#define ash_full_usage "\n\n"
13593 //usage:        "Unix shell interpreter"
13594
13595 /*
13596  * Process the shell command line arguments.
13597  */
13598 static void
13599 procargs(char **argv)
13600 {
13601         int i;
13602         const char *xminusc;
13603         char **xargv;
13604
13605         xargv = argv;
13606         arg0 = xargv[0];
13607         /* if (xargv[0]) - mmm, this is always true! */
13608                 xargv++;
13609         for (i = 0; i < NOPTS; i++)
13610                 optlist[i] = 2;
13611         argptr = xargv;
13612         if (options(/*cmdline:*/ 1)) {
13613                 /* it already printed err message */
13614                 raise_exception(EXERROR);
13615         }
13616         xargv = argptr;
13617         xminusc = minusc;
13618         if (*xargv == NULL) {
13619                 if (xminusc)
13620                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13621                 sflag = 1;
13622         }
13623         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13624                 iflag = 1;
13625         if (mflag == 2)
13626                 mflag = iflag;
13627         for (i = 0; i < NOPTS; i++)
13628                 if (optlist[i] == 2)
13629                         optlist[i] = 0;
13630 #if DEBUG == 2
13631         debug = 1;
13632 #endif
13633         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13634         if (xminusc) {
13635                 minusc = *xargv++;
13636                 if (*xargv)
13637                         goto setarg0;
13638         } else if (!sflag) {
13639                 setinputfile(*xargv, 0);
13640  setarg0:
13641                 arg0 = *xargv++;
13642                 commandname = arg0;
13643         }
13644
13645         shellparam.p = xargv;
13646 #if ENABLE_ASH_GETOPTS
13647         shellparam.optind = 1;
13648         shellparam.optoff = -1;
13649 #endif
13650         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13651         while (*xargv) {
13652                 shellparam.nparam++;
13653                 xargv++;
13654         }
13655         optschanged();
13656 }
13657
13658 /*
13659  * Read /etc/profile, ~/.profile, $ENV.
13660  */
13661 static void
13662 read_profile(const char *name)
13663 {
13664         name = expandstr(name, DQSYNTAX);
13665         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13666                 return;
13667         cmdloop(0);
13668         popfile();
13669 }
13670
13671 /*
13672  * This routine is called when an error or an interrupt occurs in an
13673  * interactive shell and control is returned to the main command loop.
13674  * (In dash, this function is auto-generated by build machinery).
13675  */
13676 static void
13677 reset(void)
13678 {
13679         /* from eval.c: */
13680         evalskip = 0;
13681         loopnest = 0;
13682
13683         /* from expand.c: */
13684         ifsfree();
13685
13686         /* from input.c: */
13687         g_parsefile->left_in_buffer = 0;
13688         g_parsefile->left_in_line = 0;      /* clear input buffer */
13689         popallfiles();
13690
13691         /* from redir.c: */
13692         unwindredir(NULL);
13693
13694         /* from var.c: */
13695         unwindlocalvars(NULL);
13696 }
13697
13698 #if PROFILE
13699 static short profile_buf[16384];
13700 extern int etext();
13701 #endif
13702
13703 /*
13704  * Main routine.  We initialize things, parse the arguments, execute
13705  * profiles if we're a login shell, and then call cmdloop to execute
13706  * commands.  The setjmp call sets up the location to jump to when an
13707  * exception occurs.  When an exception occurs the variable "state"
13708  * is used to figure out how far we had gotten.
13709  */
13710 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13711 int ash_main(int argc UNUSED_PARAM, char **argv)
13712 {
13713         volatile smallint state;
13714         struct jmploc jmploc;
13715         struct stackmark smark;
13716
13717         /* Initialize global data */
13718         INIT_G_misc();
13719         INIT_G_memstack();
13720         INIT_G_var();
13721 #if ENABLE_ASH_ALIAS
13722         INIT_G_alias();
13723 #endif
13724         INIT_G_cmdtable();
13725
13726 #if PROFILE
13727         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13728 #endif
13729
13730 #if ENABLE_FEATURE_EDITING
13731         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13732 #endif
13733         state = 0;
13734         if (setjmp(jmploc.loc)) {
13735                 smallint e;
13736                 smallint s;
13737
13738                 reset();
13739
13740                 e = exception_type;
13741                 s = state;
13742                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13743                         exitshell();
13744                 }
13745                 if (e == EXINT) {
13746                         newline_and_flush(stderr);
13747                 }
13748
13749                 popstackmark(&smark);
13750                 FORCE_INT_ON; /* enable interrupts */
13751                 if (s == 1)
13752                         goto state1;
13753                 if (s == 2)
13754                         goto state2;
13755                 if (s == 3)
13756                         goto state3;
13757                 goto state4;
13758         }
13759         exception_handler = &jmploc;
13760         rootpid = getpid();
13761
13762         init();
13763         setstackmark(&smark);
13764         procargs(argv);
13765 #if DEBUG
13766         TRACE(("Shell args: "));
13767         trace_puts_args(argv);
13768 #endif
13769
13770         if (argv[0] && argv[0][0] == '-')
13771                 isloginsh = 1;
13772         if (isloginsh) {
13773                 const char *hp;
13774
13775                 state = 1;
13776                 read_profile("/etc/profile");
13777  state1:
13778                 state = 2;
13779                 hp = lookupvar("HOME");
13780                 if (hp)
13781                         read_profile("$HOME/.profile");
13782         }
13783  state2:
13784         state = 3;
13785         if (
13786 #ifndef linux
13787          getuid() == geteuid() && getgid() == getegid() &&
13788 #endif
13789          iflag
13790         ) {
13791                 const char *shinit = lookupvar("ENV");
13792                 if (shinit != NULL && *shinit != '\0')
13793                         read_profile(shinit);
13794         }
13795         popstackmark(&smark);
13796  state3:
13797         state = 4;
13798         if (minusc) {
13799                 /* evalstring pushes parsefile stack.
13800                  * Ensure we don't falsely claim that 0 (stdin)
13801                  * is one of stacked source fds.
13802                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13803                 // if (!sflag) g_parsefile->pf_fd = -1;
13804                 // ^^ not necessary since now we special-case fd 0
13805                 // in save_fd_on_redirect()
13806                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13807         }
13808
13809         if (sflag || minusc == NULL) {
13810 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13811                 if (iflag) {
13812                         const char *hp = lookupvar("HISTFILE");
13813                         if (!hp) {
13814                                 hp = lookupvar("HOME");
13815                                 if (hp) {
13816                                         INT_OFF;
13817                                         hp = concat_path_file(hp, ".ash_history");
13818                                         setvar0("HISTFILE", hp);
13819                                         free((char*)hp);
13820                                         INT_ON;
13821                                         hp = lookupvar("HISTFILE");
13822                                 }
13823                         }
13824                         if (hp)
13825                                 line_input_state->hist_file = hp;
13826 # if ENABLE_FEATURE_SH_HISTFILESIZE
13827                         hp = lookupvar("HISTFILESIZE");
13828                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13829 # endif
13830                 }
13831 #endif
13832  state4: /* XXX ??? - why isn't this before the "if" statement */
13833                 cmdloop(1);
13834         }
13835 #if PROFILE
13836         monitor(0);
13837 #endif
13838 #ifdef GPROF
13839         {
13840                 extern void _mcleanup(void);
13841                 _mcleanup();
13842         }
13843 #endif
13844         TRACE(("End of main reached\n"));
13845         exitshell();
13846         /* NOTREACHED */
13847 }
13848
13849
13850 /*-
13851  * Copyright (c) 1989, 1991, 1993, 1994
13852  *      The Regents of the University of California.  All rights reserved.
13853  *
13854  * This code is derived from software contributed to Berkeley by
13855  * Kenneth Almquist.
13856  *
13857  * Redistribution and use in source and binary forms, with or without
13858  * modification, are permitted provided that the following conditions
13859  * are met:
13860  * 1. Redistributions of source code must retain the above copyright
13861  *    notice, this list of conditions and the following disclaimer.
13862  * 2. Redistributions in binary form must reproduce the above copyright
13863  *    notice, this list of conditions and the following disclaimer in the
13864  *    documentation and/or other materials provided with the distribution.
13865  * 3. Neither the name of the University nor the names of its contributors
13866  *    may be used to endorse or promote products derived from this software
13867  *    without specific prior written permission.
13868  *
13869  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13870  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13871  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13872  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13873  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13874  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13875  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13876  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13877  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13878  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13879  * SUCH DAMAGE.
13880  */