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