58999fac587918440398515cc7a5e8c74703747a
[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 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
192 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
193 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
194
195 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
196 /* Bionic at least up to version 24 has no glob() */
197 # undef  ENABLE_ASH_INTERNAL_GLOB
198 # define ENABLE_ASH_INTERNAL_GLOB 1
199 #endif
200
201 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
202 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
203 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
204 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
205 # error glob() should unbackslash them and match. uClibc does not unbackslash,
206 # error fails to match dirname, subsequently not expanding <pattern> in it.
207 // Testcase:
208 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
209 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
210 #endif
211
212 #if !ENABLE_ASH_INTERNAL_GLOB
213 # include <glob.h>
214 #endif
215
216 #include "unicode.h"
217 #include "shell_common.h"
218 #if ENABLE_FEATURE_SH_MATH
219 # include "math.h"
220 #else
221 typedef long arith_t;
222 # define ARITH_FMT "%ld"
223 #endif
224 #if ENABLE_ASH_RANDOM_SUPPORT
225 # include "random.h"
226 #else
227 # define CLEAR_RANDOM_T(rnd) ((void)0)
228 #endif
229
230 #include "NUM_APPLETS.h"
231 #if NUM_APPLETS == 1
232 /* STANDALONE does not make sense, and won't compile */
233 # undef CONFIG_FEATURE_SH_STANDALONE
234 # undef ENABLE_FEATURE_SH_STANDALONE
235 # undef IF_FEATURE_SH_STANDALONE
236 # undef IF_NOT_FEATURE_SH_STANDALONE
237 # define ENABLE_FEATURE_SH_STANDALONE 0
238 # define IF_FEATURE_SH_STANDALONE(...)
239 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
240 #endif
241
242 #ifndef PIPE_BUF
243 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
244 #endif
245
246 #if !BB_MMU
247 # error "Do not even bother, ash will not run on NOMMU machine"
248 #endif
249
250
251 /* ============ Hash table sizes. Configurable. */
252
253 #define VTABSIZE 39
254 #define ATABSIZE 39
255 #define CMDTABLESIZE 31         /* should be prime */
256
257
258 /* ============ Shell options */
259
260 static const char *const optletters_optnames[] = {
261         "e"   "errexit",
262         "f"   "noglob",
263         "I"   "ignoreeof",
264         "i"   "interactive",
265         "m"   "monitor",
266         "n"   "noexec",
267         "s"   "stdin",
268         "x"   "xtrace",
269         "v"   "verbose",
270         "C"   "noclobber",
271         "a"   "allexport",
272         "b"   "notify",
273         "u"   "nounset",
274         "\0"  "vi"
275 #if BASH_PIPEFAIL
276         ,"\0"  "pipefail"
277 #endif
278 #if DEBUG
279         ,"\0"  "nolog"
280         ,"\0"  "debug"
281 #endif
282 };
283
284 #define optletters(n)  optletters_optnames[n][0]
285 #define optnames(n)   (optletters_optnames[n] + 1)
286
287 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
288
289
290 /* ============ Misc data */
291
292 #define msg_illnum "Illegal number: %s"
293
294 /*
295  * We enclose jmp_buf in a structure so that we can declare pointers to
296  * jump locations.  The global variable handler contains the location to
297  * jump to when an exception occurs, and the global variable exception_type
298  * contains a code identifying the exception.  To implement nested
299  * exception handlers, the user should save the value of handler on entry
300  * to an inner scope, set handler to point to a jmploc structure for the
301  * inner scope, and restore handler on exit from the scope.
302  */
303 struct jmploc {
304         jmp_buf loc;
305 };
306
307 struct globals_misc {
308         uint8_t exitstatus;     /* exit status of last command */
309         uint8_t back_exitstatus;/* exit status of backquoted command */
310         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
311         int rootpid;            /* pid of main shell */
312         /* shell level: 0 for the main shell, 1 for its children, and so on */
313         int shlvl;
314 #define rootshell (!shlvl)
315         char *minusc;  /* argument to -c option */
316
317         char *curdir; // = nullstr;     /* current working directory */
318         char *physdir; // = nullstr;    /* physical working directory */
319
320         char *arg0; /* value of $0 */
321
322         struct jmploc *exception_handler;
323
324         volatile int suppress_int; /* counter */
325         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
326         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
327         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
328         smallint exception_type; /* kind of exception (0..5) */
329         /* exceptions */
330 #define EXINT 0         /* SIGINT received */
331 #define EXERROR 1       /* a generic error */
332 #define EXEXIT 4        /* exit the shell */
333
334         char nullstr[1];        /* zero length string */
335
336         char optlist[NOPTS];
337 #define eflag optlist[0]
338 #define fflag optlist[1]
339 #define Iflag optlist[2]
340 #define iflag optlist[3]
341 #define mflag optlist[4]
342 #define nflag optlist[5]
343 #define sflag optlist[6]
344 #define xflag optlist[7]
345 #define vflag optlist[8]
346 #define Cflag optlist[9]
347 #define aflag optlist[10]
348 #define bflag optlist[11]
349 #define uflag optlist[12]
350 #define viflag optlist[13]
351 #if BASH_PIPEFAIL
352 # define pipefail optlist[14]
353 #else
354 # define pipefail 0
355 #endif
356 #if DEBUG
357 # define nolog optlist[14 + BASH_PIPEFAIL]
358 # define debug optlist[15 + BASH_PIPEFAIL]
359 #endif
360
361         /* trap handler commands */
362         /*
363          * Sigmode records the current value of the signal handlers for the various
364          * modes.  A value of zero means that the current handler is not known.
365          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
366          */
367         char sigmode[NSIG - 1];
368 #define S_DFL      1            /* default signal handling (SIG_DFL) */
369 #define S_CATCH    2            /* signal is caught */
370 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
371 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
372
373         /* indicates specified signal received */
374         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
375         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
376         char *trap[NSIG];
377         char **trap_ptr;        /* used only by "trap hack" */
378
379         /* Rarely referenced stuff */
380 #if ENABLE_ASH_RANDOM_SUPPORT
381         random_t random_gen;
382 #endif
383         pid_t backgndpid;        /* pid of last background process */
384 };
385 extern struct globals_misc *const ash_ptr_to_globals_misc;
386 #define G_misc (*ash_ptr_to_globals_misc)
387 #define exitstatus        (G_misc.exitstatus )
388 #define back_exitstatus   (G_misc.back_exitstatus )
389 #define job_warning       (G_misc.job_warning)
390 #define rootpid     (G_misc.rootpid    )
391 #define shlvl       (G_misc.shlvl      )
392 #define minusc      (G_misc.minusc     )
393 #define curdir      (G_misc.curdir     )
394 #define physdir     (G_misc.physdir    )
395 #define arg0        (G_misc.arg0       )
396 #define exception_handler (G_misc.exception_handler)
397 #define exception_type    (G_misc.exception_type   )
398 #define suppress_int      (G_misc.suppress_int     )
399 #define pending_int       (G_misc.pending_int      )
400 #define got_sigchld       (G_misc.got_sigchld      )
401 #define pending_sig       (G_misc.pending_sig      )
402 #define nullstr     (G_misc.nullstr    )
403 #define optlist     (G_misc.optlist    )
404 #define sigmode     (G_misc.sigmode    )
405 #define gotsig      (G_misc.gotsig     )
406 #define may_have_traps    (G_misc.may_have_traps   )
407 #define trap        (G_misc.trap       )
408 #define trap_ptr    (G_misc.trap_ptr   )
409 #define random_gen  (G_misc.random_gen )
410 #define backgndpid  (G_misc.backgndpid )
411 #define INIT_G_misc() do { \
412         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
413         barrier(); \
414         curdir = nullstr; \
415         physdir = nullstr; \
416         trap_ptr = trap; \
417 } while (0)
418
419
420 /* ============ DEBUG */
421 #if DEBUG
422 static void trace_printf(const char *fmt, ...);
423 static void trace_vprintf(const char *fmt, va_list va);
424 # define TRACE(param)    trace_printf param
425 # define TRACEV(param)   trace_vprintf param
426 # define close(fd) do { \
427         int dfd = (fd); \
428         if (close(dfd) < 0) \
429                 bb_error_msg("bug on %d: closing %d(0x%x)", \
430                         __LINE__, dfd, dfd); \
431 } while (0)
432 #else
433 # define TRACE(param)
434 # define TRACEV(param)
435 #endif
436
437
438 /* ============ Utility functions */
439 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
440 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
441
442 static int
443 isdigit_str9(const char *str)
444 {
445         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
446         while (--maxlen && isdigit(*str))
447                 str++;
448         return (*str == '\0');
449 }
450
451 static const char *
452 var_end(const char *var)
453 {
454         while (*var)
455                 if (*var++ == '=')
456                         break;
457         return var;
458 }
459
460
461 /* ============ Interrupts / exceptions */
462
463 static void exitshell(void) NORETURN;
464
465 /*
466  * These macros allow the user to suspend the handling of interrupt signals
467  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
468  * much more efficient and portable.  (But hacking the kernel is so much
469  * more fun than worrying about efficiency and portability. :-))
470  */
471 #if DEBUG_INTONOFF
472 # define INT_OFF do { \
473         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
474         suppress_int++; \
475         barrier(); \
476 } while (0)
477 #else
478 # define INT_OFF do { \
479         suppress_int++; \
480         barrier(); \
481 } while (0)
482 #endif
483
484 /*
485  * Called to raise an exception.  Since C doesn't include exceptions, we
486  * just do a longjmp to the exception handler.  The type of exception is
487  * stored in the global variable "exception_type".
488  */
489 static void raise_exception(int) NORETURN;
490 static void
491 raise_exception(int e)
492 {
493 #if DEBUG
494         if (exception_handler == NULL)
495                 abort();
496 #endif
497         INT_OFF;
498         exception_type = e;
499         longjmp(exception_handler->loc, 1);
500 }
501 #if DEBUG
502 #define raise_exception(e) do { \
503         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
504         raise_exception(e); \
505 } while (0)
506 #endif
507
508 /*
509  * Called when a SIGINT is received.  (If the user specifies
510  * that SIGINT is to be trapped or ignored using the trap builtin, then
511  * this routine is not called.)  Suppressint is nonzero when interrupts
512  * are held using the INT_OFF macro.  (The test for iflag is just
513  * defensive programming.)
514  */
515 static void raise_interrupt(void) NORETURN;
516 static void
517 raise_interrupt(void)
518 {
519         pending_int = 0;
520         /* Signal is not automatically unmasked after it is raised,
521          * do it ourself - unmask all signals */
522         sigprocmask_allsigs(SIG_UNBLOCK);
523         /* pending_sig = 0; - now done in signal_handler() */
524
525         if (!(rootshell && iflag)) {
526                 /* Kill ourself with SIGINT */
527                 signal(SIGINT, SIG_DFL);
528                 raise(SIGINT);
529         }
530         /* bash: ^C even on empty command line sets $? */
531         exitstatus = SIGINT + 128;
532         raise_exception(EXINT);
533         /* NOTREACHED */
534 }
535 #if DEBUG
536 #define raise_interrupt() do { \
537         TRACE(("raising interrupt on line %d\n", __LINE__)); \
538         raise_interrupt(); \
539 } while (0)
540 #endif
541
542 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
543 int_on(void)
544 {
545         barrier();
546         if (--suppress_int == 0 && pending_int) {
547                 raise_interrupt();
548         }
549 }
550 #if DEBUG_INTONOFF
551 # define INT_ON do { \
552         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
553         int_on(); \
554 } while (0)
555 #else
556 # define INT_ON int_on()
557 #endif
558 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
559 force_int_on(void)
560 {
561         barrier();
562         suppress_int = 0;
563         if (pending_int)
564                 raise_interrupt();
565 }
566 #define FORCE_INT_ON force_int_on()
567
568 #define SAVE_INT(v) ((v) = suppress_int)
569
570 #define RESTORE_INT(v) do { \
571         barrier(); \
572         suppress_int = (v); \
573         if (suppress_int == 0 && pending_int) \
574                 raise_interrupt(); \
575 } while (0)
576
577
578 /* ============ Stdout/stderr output */
579
580 static void
581 outstr(const char *p, FILE *file)
582 {
583         INT_OFF;
584         fputs(p, file);
585         INT_ON;
586 }
587
588 static void
589 flush_stdout_stderr(void)
590 {
591         INT_OFF;
592         fflush_all();
593         INT_ON;
594 }
595
596 /* Was called outcslow(c,FILE*), but c was always '\n' */
597 static void
598 newline_and_flush(FILE *dest)
599 {
600         INT_OFF;
601         putc('\n', dest);
602         fflush(dest);
603         INT_ON;
604 }
605
606 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
607 static int
608 out1fmt(const char *fmt, ...)
609 {
610         va_list ap;
611         int r;
612
613         INT_OFF;
614         va_start(ap, fmt);
615         r = vprintf(fmt, ap);
616         va_end(ap);
617         INT_ON;
618         return r;
619 }
620
621 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
622 static int
623 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
624 {
625         va_list ap;
626         int ret;
627
628         INT_OFF;
629         va_start(ap, fmt);
630         ret = vsnprintf(outbuf, length, fmt, ap);
631         va_end(ap);
632         INT_ON;
633         return ret;
634 }
635
636 static void
637 out1str(const char *p)
638 {
639         outstr(p, stdout);
640 }
641
642 static void
643 out2str(const char *p)
644 {
645         outstr(p, stderr);
646         flush_stdout_stderr();
647 }
648
649
650 /* ============ Parser structures */
651
652 /* control characters in argument strings */
653 #define CTL_FIRST CTLESC
654 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
655 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
656 #define CTLENDVAR    ((unsigned char)'\203')
657 #define CTLBACKQ     ((unsigned char)'\204')
658 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
659 #define CTLENDARI    ((unsigned char)'\207')
660 #define CTLQUOTEMARK ((unsigned char)'\210')
661 #define CTL_LAST CTLQUOTEMARK
662
663 /* variable substitution byte (follows CTLVAR) */
664 #define VSTYPE  0x0f            /* type of variable substitution */
665 #define VSNUL   0x10            /* colon--treat the empty string as unset */
666
667 /* values of VSTYPE field */
668 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
669 #define VSMINUS         0x2     /* ${var-text} */
670 #define VSPLUS          0x3     /* ${var+text} */
671 #define VSQUESTION      0x4     /* ${var?message} */
672 #define VSASSIGN        0x5     /* ${var=text} */
673 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
674 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
675 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
676 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
677 #define VSLENGTH        0xa     /* ${#var} */
678 #if BASH_SUBSTR
679 #define VSSUBSTR        0xc     /* ${var:position:length} */
680 #endif
681 #if BASH_PATTERN_SUBST
682 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
683 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
684 #endif
685
686 static const char dolatstr[] ALIGN1 = {
687         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
688 };
689 #define DOLATSTRLEN 6
690
691 #define NCMD      0
692 #define NPIPE     1
693 #define NREDIR    2
694 #define NBACKGND  3
695 #define NSUBSHELL 4
696 #define NAND      5
697 #define NOR       6
698 #define NSEMI     7
699 #define NIF       8
700 #define NWHILE    9
701 #define NUNTIL   10
702 #define NFOR     11
703 #define NCASE    12
704 #define NCLIST   13
705 #define NDEFUN   14
706 #define NARG     15
707 #define NTO      16
708 #if BASH_REDIR_OUTPUT
709 #define NTO2     17
710 #endif
711 #define NCLOBBER 18
712 #define NFROM    19
713 #define NFROMTO  20
714 #define NAPPEND  21
715 #define NTOFD    22
716 #define NFROMFD  23
717 #define NHERE    24
718 #define NXHERE   25
719 #define NNOT     26
720 #define N_NUMBER 27
721
722 union node;
723
724 struct ncmd {
725         smallint type; /* Nxxxx */
726         union node *assign;
727         union node *args;
728         union node *redirect;
729 };
730
731 struct npipe {
732         smallint type;
733         smallint pipe_backgnd;
734         struct nodelist *cmdlist;
735 };
736
737 struct nredir {
738         smallint type;
739         union node *n;
740         union node *redirect;
741 };
742
743 struct nbinary {
744         smallint type;
745         union node *ch1;
746         union node *ch2;
747 };
748
749 struct nif {
750         smallint type;
751         union node *test;
752         union node *ifpart;
753         union node *elsepart;
754 };
755
756 struct nfor {
757         smallint type;
758         union node *args;
759         union node *body;
760         char *var;
761 };
762
763 struct ncase {
764         smallint type;
765         union node *expr;
766         union node *cases;
767 };
768
769 struct nclist {
770         smallint type;
771         union node *next;
772         union node *pattern;
773         union node *body;
774 };
775
776 struct narg {
777         smallint type;
778         union node *next;
779         char *text;
780         struct nodelist *backquote;
781 };
782
783 /* nfile and ndup layout must match!
784  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
785  * that it is actually NTO2 (>&file), and change its type.
786  */
787 struct nfile {
788         smallint type;
789         union node *next;
790         int fd;
791         int _unused_dupfd;
792         union node *fname;
793         char *expfname;
794 };
795
796 struct ndup {
797         smallint type;
798         union node *next;
799         int fd;
800         int dupfd;
801         union node *vname;
802         char *_unused_expfname;
803 };
804
805 struct nhere {
806         smallint type;
807         union node *next;
808         int fd;
809         union node *doc;
810 };
811
812 struct nnot {
813         smallint type;
814         union node *com;
815 };
816
817 union node {
818         smallint type;
819         struct ncmd ncmd;
820         struct npipe npipe;
821         struct nredir nredir;
822         struct nbinary nbinary;
823         struct nif nif;
824         struct nfor nfor;
825         struct ncase ncase;
826         struct nclist nclist;
827         struct narg narg;
828         struct nfile nfile;
829         struct ndup ndup;
830         struct nhere nhere;
831         struct nnot nnot;
832 };
833
834 /*
835  * NODE_EOF is returned by parsecmd when it encounters an end of file.
836  * It must be distinct from NULL.
837  */
838 #define NODE_EOF ((union node *) -1L)
839
840 struct nodelist {
841         struct nodelist *next;
842         union node *n;
843 };
844
845 struct funcnode {
846         int count;
847         union node n;
848 };
849
850 /*
851  * Free a parse tree.
852  */
853 static void
854 freefunc(struct funcnode *f)
855 {
856         if (f && --f->count < 0)
857                 free(f);
858 }
859
860
861 /* ============ Debugging output */
862
863 #if DEBUG
864
865 static FILE *tracefile;
866
867 static void
868 trace_printf(const char *fmt, ...)
869 {
870         va_list va;
871
872         if (debug != 1)
873                 return;
874         if (DEBUG_TIME)
875                 fprintf(tracefile, "%u ", (int) time(NULL));
876         if (DEBUG_PID)
877                 fprintf(tracefile, "[%u] ", (int) getpid());
878         if (DEBUG_SIG)
879                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
880         va_start(va, fmt);
881         vfprintf(tracefile, fmt, va);
882         va_end(va);
883 }
884
885 static void
886 trace_vprintf(const char *fmt, va_list va)
887 {
888         if (debug != 1)
889                 return;
890         vfprintf(tracefile, fmt, va);
891         fprintf(tracefile, "\n");
892 }
893
894 static void
895 trace_puts(const char *s)
896 {
897         if (debug != 1)
898                 return;
899         fputs(s, tracefile);
900 }
901
902 static void
903 trace_puts_quoted(char *s)
904 {
905         char *p;
906         char c;
907
908         if (debug != 1)
909                 return;
910         putc('"', tracefile);
911         for (p = s; *p; p++) {
912                 switch ((unsigned char)*p) {
913                 case '\n': c = 'n'; goto backslash;
914                 case '\t': c = 't'; goto backslash;
915                 case '\r': c = 'r'; goto backslash;
916                 case '\"': c = '\"'; goto backslash;
917                 case '\\': c = '\\'; goto backslash;
918                 case CTLESC: c = 'e'; goto backslash;
919                 case CTLVAR: c = 'v'; goto backslash;
920                 case CTLBACKQ: c = 'q'; goto backslash;
921  backslash:
922                         putc('\\', tracefile);
923                         putc(c, tracefile);
924                         break;
925                 default:
926                         if (*p >= ' ' && *p <= '~')
927                                 putc(*p, tracefile);
928                         else {
929                                 putc('\\', tracefile);
930                                 putc((*p >> 6) & 03, tracefile);
931                                 putc((*p >> 3) & 07, tracefile);
932                                 putc(*p & 07, tracefile);
933                         }
934                         break;
935                 }
936         }
937         putc('"', tracefile);
938 }
939
940 static void
941 trace_puts_args(char **ap)
942 {
943         if (debug != 1)
944                 return;
945         if (!*ap)
946                 return;
947         while (1) {
948                 trace_puts_quoted(*ap);
949                 if (!*++ap) {
950                         putc('\n', tracefile);
951                         break;
952                 }
953                 putc(' ', tracefile);
954         }
955 }
956
957 static void
958 opentrace(void)
959 {
960         char s[100];
961 #ifdef O_APPEND
962         int flags;
963 #endif
964
965         if (debug != 1) {
966                 if (tracefile)
967                         fflush(tracefile);
968                 /* leave open because libedit might be using it */
969                 return;
970         }
971         strcpy(s, "./trace");
972         if (tracefile) {
973                 if (!freopen(s, "a", tracefile)) {
974                         fprintf(stderr, "Can't re-open %s\n", s);
975                         debug = 0;
976                         return;
977                 }
978         } else {
979                 tracefile = fopen(s, "a");
980                 if (tracefile == NULL) {
981                         fprintf(stderr, "Can't open %s\n", s);
982                         debug = 0;
983                         return;
984                 }
985         }
986 #ifdef O_APPEND
987         flags = fcntl(fileno(tracefile), F_GETFL);
988         if (flags >= 0)
989                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
990 #endif
991         setlinebuf(tracefile);
992         fputs("\nTracing started.\n", tracefile);
993 }
994
995 static void
996 indent(int amount, char *pfx, FILE *fp)
997 {
998         int i;
999
1000         for (i = 0; i < amount; i++) {
1001                 if (pfx && i == amount - 1)
1002                         fputs(pfx, fp);
1003                 putc('\t', fp);
1004         }
1005 }
1006
1007 /* little circular references here... */
1008 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1009
1010 static void
1011 sharg(union node *arg, FILE *fp)
1012 {
1013         char *p;
1014         struct nodelist *bqlist;
1015         unsigned char subtype;
1016
1017         if (arg->type != NARG) {
1018                 out1fmt("<node type %d>\n", arg->type);
1019                 abort();
1020         }
1021         bqlist = arg->narg.backquote;
1022         for (p = arg->narg.text; *p; p++) {
1023                 switch ((unsigned char)*p) {
1024                 case CTLESC:
1025                         p++;
1026                         putc(*p, fp);
1027                         break;
1028                 case CTLVAR:
1029                         putc('$', fp);
1030                         putc('{', fp);
1031                         subtype = *++p;
1032                         if (subtype == VSLENGTH)
1033                                 putc('#', fp);
1034
1035                         while (*p != '=') {
1036                                 putc(*p, fp);
1037                                 p++;
1038                         }
1039
1040                         if (subtype & VSNUL)
1041                                 putc(':', fp);
1042
1043                         switch (subtype & VSTYPE) {
1044                         case VSNORMAL:
1045                                 putc('}', fp);
1046                                 break;
1047                         case VSMINUS:
1048                                 putc('-', fp);
1049                                 break;
1050                         case VSPLUS:
1051                                 putc('+', fp);
1052                                 break;
1053                         case VSQUESTION:
1054                                 putc('?', fp);
1055                                 break;
1056                         case VSASSIGN:
1057                                 putc('=', fp);
1058                                 break;
1059                         case VSTRIMLEFT:
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMLEFTMAX:
1063                                 putc('#', fp);
1064                                 putc('#', fp);
1065                                 break;
1066                         case VSTRIMRIGHT:
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSTRIMRIGHTMAX:
1070                                 putc('%', fp);
1071                                 putc('%', fp);
1072                                 break;
1073                         case VSLENGTH:
1074                                 break;
1075                         default:
1076                                 out1fmt("<subtype %d>", subtype);
1077                         }
1078                         break;
1079                 case CTLENDVAR:
1080                         putc('}', fp);
1081                         break;
1082                 case CTLBACKQ:
1083                         putc('$', fp);
1084                         putc('(', fp);
1085                         shtree(bqlist->n, -1, NULL, fp);
1086                         putc(')', fp);
1087                         break;
1088                 default:
1089                         putc(*p, fp);
1090                         break;
1091                 }
1092         }
1093 }
1094
1095 static void
1096 shcmd(union node *cmd, FILE *fp)
1097 {
1098         union node *np;
1099         int first;
1100         const char *s;
1101         int dftfd;
1102
1103         first = 1;
1104         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1105                 if (!first)
1106                         putc(' ', fp);
1107                 sharg(np, fp);
1108                 first = 0;
1109         }
1110         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1111                 if (!first)
1112                         putc(' ', fp);
1113                 dftfd = 0;
1114                 switch (np->nfile.type) {
1115                 case NTO:      s = ">>"+1; dftfd = 1; break;
1116                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1117                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1118 #if BASH_REDIR_OUTPUT
1119                 case NTO2:
1120 #endif
1121                 case NTOFD:    s = ">&"; dftfd = 1; break;
1122                 case NFROM:    s = "<"; break;
1123                 case NFROMFD:  s = "<&"; break;
1124                 case NFROMTO:  s = "<>"; break;
1125                 default:       s = "*error*"; break;
1126                 }
1127                 if (np->nfile.fd != dftfd)
1128                         fprintf(fp, "%d", np->nfile.fd);
1129                 fputs(s, fp);
1130                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1131                         fprintf(fp, "%d", np->ndup.dupfd);
1132                 } else {
1133                         sharg(np->nfile.fname, fp);
1134                 }
1135                 first = 0;
1136         }
1137 }
1138
1139 static void
1140 shtree(union node *n, int ind, char *pfx, FILE *fp)
1141 {
1142         struct nodelist *lp;
1143         const char *s;
1144
1145         if (n == NULL)
1146                 return;
1147
1148         indent(ind, pfx, fp);
1149
1150         if (n == NODE_EOF) {
1151                 fputs("<EOF>", fp);
1152                 return;
1153         }
1154
1155         switch (n->type) {
1156         case NSEMI:
1157                 s = "; ";
1158                 goto binop;
1159         case NAND:
1160                 s = " && ";
1161                 goto binop;
1162         case NOR:
1163                 s = " || ";
1164  binop:
1165                 shtree(n->nbinary.ch1, ind, NULL, fp);
1166                 /* if (ind < 0) */
1167                         fputs(s, fp);
1168                 shtree(n->nbinary.ch2, ind, NULL, fp);
1169                 break;
1170         case NCMD:
1171                 shcmd(n, fp);
1172                 if (ind >= 0)
1173                         putc('\n', fp);
1174                 break;
1175         case NPIPE:
1176                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1177                         shtree(lp->n, 0, NULL, fp);
1178                         if (lp->next)
1179                                 fputs(" | ", fp);
1180                 }
1181                 if (n->npipe.pipe_backgnd)
1182                         fputs(" &", fp);
1183                 if (ind >= 0)
1184                         putc('\n', fp);
1185                 break;
1186         default:
1187                 fprintf(fp, "<node type %d>", n->type);
1188                 if (ind >= 0)
1189                         putc('\n', fp);
1190                 break;
1191         }
1192 }
1193
1194 static void
1195 showtree(union node *n)
1196 {
1197         trace_puts("showtree called\n");
1198         shtree(n, 1, NULL, stderr);
1199 }
1200
1201 #endif /* DEBUG */
1202
1203
1204 /* ============ Parser data */
1205
1206 /*
1207  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1208  */
1209 struct strlist {
1210         struct strlist *next;
1211         char *text;
1212 };
1213
1214 struct alias;
1215
1216 struct strpush {
1217         struct strpush *prev;   /* preceding string on stack */
1218         char *prev_string;
1219         int prev_left_in_line;
1220 #if ENABLE_ASH_ALIAS
1221         struct alias *ap;       /* if push was associated with an alias */
1222 #endif
1223         char *string;           /* remember the string since it may change */
1224
1225         /* Remember last two characters for pungetc. */
1226         int lastc[2];
1227
1228         /* Number of outstanding calls to pungetc. */
1229         int unget;
1230 };
1231
1232 /*
1233  * The parsefile structure pointed to by the global variable parsefile
1234  * contains information about the current file being read.
1235  */
1236 struct parsefile {
1237         struct parsefile *prev; /* preceding file on stack */
1238         int linno;              /* current line */
1239         int pf_fd;              /* file descriptor (or -1 if string) */
1240         int left_in_line;       /* number of chars left in this line */
1241         int left_in_buffer;     /* number of chars left in this buffer past the line */
1242         char *next_to_pgetc;    /* next char in buffer */
1243         char *buf;              /* input buffer */
1244         struct strpush *strpush; /* for pushing strings at this level */
1245         struct strpush basestrpush; /* so pushing one is fast */
1246
1247         /* Remember last two characters for pungetc. */
1248         int lastc[2];
1249
1250         /* Number of outstanding calls to pungetc. */
1251         int unget;
1252 };
1253
1254 static struct parsefile basepf;        /* top level input file */
1255 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1256 static int startlinno;                 /* line # where last token started */
1257 static char *commandname;              /* currently executing command */
1258
1259
1260 /* ============ Message printing */
1261
1262 static void
1263 ash_vmsg(const char *msg, va_list ap)
1264 {
1265         fprintf(stderr, "%s: ", arg0);
1266         if (commandname) {
1267                 if (strcmp(arg0, commandname))
1268                         fprintf(stderr, "%s: ", commandname);
1269                 if (!iflag || g_parsefile->pf_fd > 0)
1270                         fprintf(stderr, "line %d: ", startlinno);
1271         }
1272         vfprintf(stderr, msg, ap);
1273         newline_and_flush(stderr);
1274 }
1275
1276 /*
1277  * Exverror is called to raise the error exception.  If the second argument
1278  * is not NULL then error prints an error message using printf style
1279  * formatting.  It then raises the error exception.
1280  */
1281 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1282 static void
1283 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1284 {
1285 #if DEBUG
1286         if (msg) {
1287                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1288                 TRACEV((msg, ap));
1289         } else
1290                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1291         if (msg)
1292 #endif
1293                 ash_vmsg(msg, ap);
1294
1295         flush_stdout_stderr();
1296         raise_exception(cond);
1297         /* NOTREACHED */
1298 }
1299
1300 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1301 static void
1302 ash_msg_and_raise_error(const char *msg, ...)
1303 {
1304         va_list ap;
1305
1306         exitstatus = 2;
1307
1308         va_start(ap, msg);
1309         ash_vmsg_and_raise(EXERROR, msg, ap);
1310         /* NOTREACHED */
1311         va_end(ap);
1312 }
1313
1314 /*
1315  * Use '%m' to append error string on platforms that support it, '%s' and
1316  * strerror() on those that don't.
1317  *
1318  * 'fmt' must be a string literal.
1319  */
1320 #ifdef HAVE_PRINTF_PERCENTM
1321 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1322 #else
1323 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1324 #endif
1325
1326 static void raise_error_syntax(const char *) NORETURN;
1327 static void
1328 raise_error_syntax(const char *msg)
1329 {
1330         ash_msg_and_raise_error("syntax error: %s", msg);
1331         /* NOTREACHED */
1332 }
1333
1334 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1335 static void
1336 ash_msg_and_raise(int cond, const char *msg, ...)
1337 {
1338         va_list ap;
1339
1340         va_start(ap, msg);
1341         ash_vmsg_and_raise(cond, msg, ap);
1342         /* NOTREACHED */
1343         va_end(ap);
1344 }
1345
1346 /*
1347  * error/warning routines for external builtins
1348  */
1349 static void
1350 ash_msg(const char *fmt, ...)
1351 {
1352         va_list ap;
1353
1354         va_start(ap, fmt);
1355         ash_vmsg(fmt, ap);
1356         va_end(ap);
1357 }
1358
1359 /*
1360  * Return a string describing an error.  The returned string may be a
1361  * pointer to a static buffer that will be overwritten on the next call.
1362  * Action describes the operation that got the error.
1363  */
1364 static const char *
1365 errmsg(int e, const char *em)
1366 {
1367         if (e == ENOENT || e == ENOTDIR) {
1368                 return em;
1369         }
1370         return strerror(e);
1371 }
1372
1373
1374 /* ============ Memory allocation */
1375
1376 #if 0
1377 /* I consider these wrappers nearly useless:
1378  * ok, they return you to nearest exception handler, but
1379  * how much memory do you leak in the process, making
1380  * memory starvation worse?
1381  */
1382 static void *
1383 ckrealloc(void * p, size_t nbytes)
1384 {
1385         p = realloc(p, nbytes);
1386         if (!p)
1387                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1388         return p;
1389 }
1390
1391 static void *
1392 ckmalloc(size_t nbytes)
1393 {
1394         return ckrealloc(NULL, nbytes);
1395 }
1396
1397 static void *
1398 ckzalloc(size_t nbytes)
1399 {
1400         return memset(ckmalloc(nbytes), 0, nbytes);
1401 }
1402
1403 static char *
1404 ckstrdup(const char *s)
1405 {
1406         char *p = strdup(s);
1407         if (!p)
1408                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1409         return p;
1410 }
1411 #else
1412 /* Using bbox equivalents. They exit if out of memory */
1413 # define ckrealloc xrealloc
1414 # define ckmalloc  xmalloc
1415 # define ckzalloc  xzalloc
1416 # define ckstrdup  xstrdup
1417 #endif
1418
1419 /*
1420  * It appears that grabstackstr() will barf with such alignments
1421  * because stalloc() will return a string allocated in a new stackblock.
1422  */
1423 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1424 enum {
1425         /* Most machines require the value returned from malloc to be aligned
1426          * in some way.  The following macro will get this right
1427          * on many machines.  */
1428         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1429         /* Minimum size of a block */
1430         MINSIZE = SHELL_ALIGN(504),
1431 };
1432
1433 struct stack_block {
1434         struct stack_block *prev;
1435         char space[MINSIZE];
1436 };
1437
1438 struct stackmark {
1439         struct stack_block *stackp;
1440         char *stacknxt;
1441         size_t stacknleft;
1442 };
1443
1444
1445 struct globals_memstack {
1446         struct stack_block *g_stackp; // = &stackbase;
1447         char *g_stacknxt; // = stackbase.space;
1448         char *sstrend; // = stackbase.space + MINSIZE;
1449         size_t g_stacknleft; // = MINSIZE;
1450         struct stack_block stackbase;
1451 };
1452 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1453 #define G_memstack (*ash_ptr_to_globals_memstack)
1454 #define g_stackp     (G_memstack.g_stackp    )
1455 #define g_stacknxt   (G_memstack.g_stacknxt  )
1456 #define sstrend      (G_memstack.sstrend     )
1457 #define g_stacknleft (G_memstack.g_stacknleft)
1458 #define stackbase    (G_memstack.stackbase   )
1459 #define INIT_G_memstack() do { \
1460         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1461         barrier(); \
1462         g_stackp = &stackbase; \
1463         g_stacknxt = stackbase.space; \
1464         g_stacknleft = MINSIZE; \
1465         sstrend = stackbase.space + MINSIZE; \
1466 } while (0)
1467
1468
1469 #define stackblock()     ((void *)g_stacknxt)
1470 #define stackblocksize() g_stacknleft
1471
1472 /*
1473  * Parse trees for commands are allocated in lifo order, so we use a stack
1474  * to make this more efficient, and also to avoid all sorts of exception
1475  * handling code to handle interrupts in the middle of a parse.
1476  *
1477  * The size 504 was chosen because the Ultrix malloc handles that size
1478  * well.
1479  */
1480 static void *
1481 stalloc(size_t nbytes)
1482 {
1483         char *p;
1484         size_t aligned;
1485
1486         aligned = SHELL_ALIGN(nbytes);
1487         if (aligned > g_stacknleft) {
1488                 size_t len;
1489                 size_t blocksize;
1490                 struct stack_block *sp;
1491
1492                 blocksize = aligned;
1493                 if (blocksize < MINSIZE)
1494                         blocksize = MINSIZE;
1495                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1496                 if (len < blocksize)
1497                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1498                 INT_OFF;
1499                 sp = ckmalloc(len);
1500                 sp->prev = g_stackp;
1501                 g_stacknxt = sp->space;
1502                 g_stacknleft = blocksize;
1503                 sstrend = g_stacknxt + blocksize;
1504                 g_stackp = sp;
1505                 INT_ON;
1506         }
1507         p = g_stacknxt;
1508         g_stacknxt += aligned;
1509         g_stacknleft -= aligned;
1510         return p;
1511 }
1512
1513 static void *
1514 stzalloc(size_t nbytes)
1515 {
1516         return memset(stalloc(nbytes), 0, nbytes);
1517 }
1518
1519 static void
1520 stunalloc(void *p)
1521 {
1522 #if DEBUG
1523         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1524                 write(STDERR_FILENO, "stunalloc\n", 10);
1525                 abort();
1526         }
1527 #endif
1528         g_stacknleft += g_stacknxt - (char *)p;
1529         g_stacknxt = p;
1530 }
1531
1532 /*
1533  * Like strdup but works with the ash stack.
1534  */
1535 static char *
1536 sstrdup(const char *p)
1537 {
1538         size_t len = strlen(p) + 1;
1539         return memcpy(stalloc(len), p, len);
1540 }
1541
1542 static inline void
1543 grabstackblock(size_t len)
1544 {
1545         stalloc(len);
1546 }
1547
1548 static void
1549 pushstackmark(struct stackmark *mark, size_t len)
1550 {
1551         mark->stackp = g_stackp;
1552         mark->stacknxt = g_stacknxt;
1553         mark->stacknleft = g_stacknleft;
1554         grabstackblock(len);
1555 }
1556
1557 static void
1558 setstackmark(struct stackmark *mark)
1559 {
1560         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1561 }
1562
1563 static void
1564 popstackmark(struct stackmark *mark)
1565 {
1566         struct stack_block *sp;
1567
1568         if (!mark->stackp)
1569                 return;
1570
1571         INT_OFF;
1572         while (g_stackp != mark->stackp) {
1573                 sp = g_stackp;
1574                 g_stackp = sp->prev;
1575                 free(sp);
1576         }
1577         g_stacknxt = mark->stacknxt;
1578         g_stacknleft = mark->stacknleft;
1579         sstrend = mark->stacknxt + mark->stacknleft;
1580         INT_ON;
1581 }
1582
1583 /*
1584  * When the parser reads in a string, it wants to stick the string on the
1585  * stack and only adjust the stack pointer when it knows how big the
1586  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1587  * of space on top of the stack and stackblocklen returns the length of
1588  * this block.  Growstackblock will grow this space by at least one byte,
1589  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1590  * part of the block that has been used.
1591  */
1592 static void
1593 growstackblock(void)
1594 {
1595         size_t newlen;
1596
1597         newlen = g_stacknleft * 2;
1598         if (newlen < g_stacknleft)
1599                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1600         if (newlen < 128)
1601                 newlen += 128;
1602
1603         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1604                 struct stack_block *sp;
1605                 struct stack_block *prevstackp;
1606                 size_t grosslen;
1607
1608                 INT_OFF;
1609                 sp = g_stackp;
1610                 prevstackp = sp->prev;
1611                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1612                 sp = ckrealloc(sp, grosslen);
1613                 sp->prev = prevstackp;
1614                 g_stackp = sp;
1615                 g_stacknxt = sp->space;
1616                 g_stacknleft = newlen;
1617                 sstrend = sp->space + newlen;
1618                 INT_ON;
1619         } else {
1620                 char *oldspace = g_stacknxt;
1621                 size_t oldlen = g_stacknleft;
1622                 char *p = stalloc(newlen);
1623
1624                 /* free the space we just allocated */
1625                 g_stacknxt = memcpy(p, oldspace, oldlen);
1626                 g_stacknleft += newlen;
1627         }
1628 }
1629
1630 /*
1631  * The following routines are somewhat easier to use than the above.
1632  * The user declares a variable of type STACKSTR, which may be declared
1633  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1634  * the user uses the macro STPUTC to add characters to the string.  In
1635  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1636  * grown as necessary.  When the user is done, she can just leave the
1637  * string there and refer to it using stackblock().  Or she can allocate
1638  * the space for it using grabstackstr().  If it is necessary to allow
1639  * someone else to use the stack temporarily and then continue to grow
1640  * the string, the user should use grabstack to allocate the space, and
1641  * then call ungrabstr(p) to return to the previous mode of operation.
1642  *
1643  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1644  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1645  * is space for at least one character.
1646  */
1647 static void *
1648 growstackstr(void)
1649 {
1650         size_t len = stackblocksize();
1651         growstackblock();
1652         return (char *)stackblock() + len;
1653 }
1654
1655 /*
1656  * Called from CHECKSTRSPACE.
1657  */
1658 static char *
1659 makestrspace(size_t newlen, char *p)
1660 {
1661         size_t len = p - g_stacknxt;
1662         size_t size;
1663
1664         for (;;) {
1665                 size_t nleft;
1666
1667                 size = stackblocksize();
1668                 nleft = size - len;
1669                 if (nleft >= newlen)
1670                         break;
1671                 growstackblock();
1672         }
1673         return (char *)stackblock() + len;
1674 }
1675
1676 static char *
1677 stack_nputstr(const char *s, size_t n, char *p)
1678 {
1679         p = makestrspace(n, p);
1680         p = (char *)mempcpy(p, s, n);
1681         return p;
1682 }
1683
1684 static char *
1685 stack_putstr(const char *s, char *p)
1686 {
1687         return stack_nputstr(s, strlen(s), p);
1688 }
1689
1690 static char *
1691 _STPUTC(int c, char *p)
1692 {
1693         if (p == sstrend)
1694                 p = growstackstr();
1695         *p++ = c;
1696         return p;
1697 }
1698
1699 #define STARTSTACKSTR(p)        ((p) = stackblock())
1700 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1701 #define CHECKSTRSPACE(n, p) do { \
1702         char *q = (p); \
1703         size_t l = (n); \
1704         size_t m = sstrend - q; \
1705         if (l > m) \
1706                 (p) = makestrspace(l, q); \
1707 } while (0)
1708 #define USTPUTC(c, p)           (*(p)++ = (c))
1709 #define STACKSTRNUL(p) do { \
1710         if ((p) == sstrend) \
1711                 (p) = growstackstr(); \
1712         *(p) = '\0'; \
1713 } while (0)
1714 #define STUNPUTC(p)             (--(p))
1715 #define STTOPC(p)               ((p)[-1])
1716 #define STADJUST(amount, p)     ((p) += (amount))
1717
1718 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1719 #define ungrabstackstr(s, p)    stunalloc(s)
1720 #define stackstrend()           ((void *)sstrend)
1721
1722
1723 /* ============ String helpers */
1724
1725 /*
1726  * prefix -- see if pfx is a prefix of string.
1727  */
1728 static char *
1729 prefix(const char *string, const char *pfx)
1730 {
1731         while (*pfx) {
1732                 if (*pfx++ != *string++)
1733                         return NULL;
1734         }
1735         return (char *) string;
1736 }
1737
1738 /*
1739  * Check for a valid number.  This should be elsewhere.
1740  */
1741 static int
1742 is_number(const char *p)
1743 {
1744         do {
1745                 if (!isdigit(*p))
1746                         return 0;
1747         } while (*++p != '\0');
1748         return 1;
1749 }
1750
1751 /*
1752  * Convert a string of digits to an integer, printing an error message on
1753  * failure.
1754  */
1755 static int
1756 number(const char *s)
1757 {
1758         if (!is_number(s))
1759                 ash_msg_and_raise_error(msg_illnum, s);
1760         return atoi(s);
1761 }
1762
1763 /*
1764  * Produce a single quoted string suitable as input to the shell.
1765  * The return string is allocated on the stack.
1766  */
1767 static char *
1768 single_quote(const char *s)
1769 {
1770         char *p;
1771
1772         STARTSTACKSTR(p);
1773
1774         do {
1775                 char *q;
1776                 size_t len;
1777
1778                 len = strchrnul(s, '\'') - s;
1779
1780                 q = p = makestrspace(len + 3, p);
1781
1782                 *q++ = '\'';
1783                 q = (char *)mempcpy(q, s, len);
1784                 *q++ = '\'';
1785                 s += len;
1786
1787                 STADJUST(q - p, p);
1788
1789                 if (*s != '\'')
1790                         break;
1791                 len = 0;
1792                 do len++; while (*++s == '\'');
1793
1794                 q = p = makestrspace(len + 3, p);
1795
1796                 *q++ = '"';
1797                 q = (char *)mempcpy(q, s - len, len);
1798                 *q++ = '"';
1799
1800                 STADJUST(q - p, p);
1801         } while (*s);
1802
1803         USTPUTC('\0', p);
1804
1805         return stackblock();
1806 }
1807
1808 /*
1809  * Produce a possibly single quoted string suitable as input to the shell.
1810  * If quoting was done, the return string is allocated on the stack,
1811  * otherwise a pointer to the original string is returned.
1812  */
1813 static const char *
1814 maybe_single_quote(const char *s)
1815 {
1816         const char *p = s;
1817
1818         while (*p) {
1819                 /* Assuming ACSII */
1820                 /* quote ctrl_chars space !"#$%&'()* */
1821                 if (*p < '+')
1822                         goto need_quoting;
1823                 /* quote ;<=>? */
1824                 if (*p >= ';' && *p <= '?')
1825                         goto need_quoting;
1826                 /* quote `[\ */
1827                 if (*p == '`')
1828                         goto need_quoting;
1829                 if (*p == '[')
1830                         goto need_quoting;
1831                 if (*p == '\\')
1832                         goto need_quoting;
1833                 /* quote {|}~ DEL and high bytes */
1834                 if (*p > 'z')
1835                         goto need_quoting;
1836                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1837                 /* TODO: maybe avoid quoting % */
1838                 p++;
1839         }
1840         return s;
1841
1842  need_quoting:
1843         return single_quote(s);
1844 }
1845
1846
1847 /* ============ nextopt */
1848
1849 static char **argptr;                  /* argument list for builtin commands */
1850 static char *optionarg;                /* set by nextopt (like getopt) */
1851 static char *optptr;                   /* used by nextopt */
1852
1853 /*
1854  * XXX - should get rid of. Have all builtins use getopt(3).
1855  * The library getopt must have the BSD extension static variable
1856  * "optreset", otherwise it can't be used within the shell safely.
1857  *
1858  * Standard option processing (a la getopt) for builtin routines.
1859  * The only argument that is passed to nextopt is the option string;
1860  * the other arguments are unnecessary. It returns the character,
1861  * or '\0' on end of input.
1862  */
1863 static int
1864 nextopt(const char *optstring)
1865 {
1866         char *p;
1867         const char *q;
1868         char c;
1869
1870         p = optptr;
1871         if (p == NULL || *p == '\0') {
1872                 /* We ate entire "-param", take next one */
1873                 p = *argptr;
1874                 if (p == NULL)
1875                         return '\0';
1876                 if (*p != '-')
1877                         return '\0';
1878                 if (*++p == '\0') /* just "-" ? */
1879                         return '\0';
1880                 argptr++;
1881                 if (LONE_DASH(p)) /* "--" ? */
1882                         return '\0';
1883                 /* p => next "-param" */
1884         }
1885         /* p => some option char in the middle of a "-param" */
1886         c = *p++;
1887         for (q = optstring; *q != c;) {
1888                 if (*q == '\0')
1889                         ash_msg_and_raise_error("illegal option -%c", c);
1890                 if (*++q == ':')
1891                         q++;
1892         }
1893         if (*++q == ':') {
1894                 if (*p == '\0') {
1895                         p = *argptr++;
1896                         if (p == NULL)
1897                                 ash_msg_and_raise_error("no arg for -%c option", c);
1898                 }
1899                 optionarg = p;
1900                 p = NULL;
1901         }
1902         optptr = p;
1903         return c;
1904 }
1905
1906
1907 /* ============ Shell variables */
1908
1909 struct shparam {
1910         int nparam;             /* # of positional parameters (without $0) */
1911 #if ENABLE_ASH_GETOPTS
1912         int optind;             /* next parameter to be processed by getopts */
1913         int optoff;             /* used by getopts */
1914 #endif
1915         unsigned char malloced; /* if parameter list dynamically allocated */
1916         char **p;               /* parameter list */
1917 };
1918
1919 /*
1920  * Free the list of positional parameters.
1921  */
1922 static void
1923 freeparam(volatile struct shparam *param)
1924 {
1925         if (param->malloced) {
1926                 char **ap, **ap1;
1927                 ap = ap1 = param->p;
1928                 while (*ap)
1929                         free(*ap++);
1930                 free(ap1);
1931         }
1932 }
1933
1934 #if ENABLE_ASH_GETOPTS
1935 static void FAST_FUNC getoptsreset(const char *value);
1936 #endif
1937
1938 struct var {
1939         struct var *next;               /* next entry in hash list */
1940         int flags;                      /* flags are defined above */
1941         const char *var_text;           /* name=value */
1942         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1943                                         /* the variable gets set/unset */
1944 };
1945
1946 struct localvar {
1947         struct localvar *next;          /* next local variable in list */
1948         struct var *vp;                 /* the variable that was made local */
1949         int flags;                      /* saved flags */
1950         const char *text;               /* saved text */
1951 };
1952
1953 /* flags */
1954 #define VEXPORT         0x01    /* variable is exported */
1955 #define VREADONLY       0x02    /* variable cannot be modified */
1956 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1957 #define VTEXTFIXED      0x08    /* text is statically allocated */
1958 #define VSTACK          0x10    /* text is allocated on the stack */
1959 #define VUNSET          0x20    /* the variable is not set */
1960 #define VNOFUNC         0x40    /* don't call the callback function */
1961 #define VNOSET          0x80    /* do not set variable - just readonly test */
1962 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1963 #if ENABLE_ASH_RANDOM_SUPPORT
1964 # define VDYNAMIC       0x200   /* dynamic variable */
1965 #else
1966 # define VDYNAMIC       0
1967 #endif
1968
1969
1970 /* Need to be before varinit_data[] */
1971 #if ENABLE_LOCALE_SUPPORT
1972 static void FAST_FUNC
1973 change_lc_all(const char *value)
1974 {
1975         if (value && *value != '\0')
1976                 setlocale(LC_ALL, value);
1977 }
1978 static void FAST_FUNC
1979 change_lc_ctype(const char *value)
1980 {
1981         if (value && *value != '\0')
1982                 setlocale(LC_CTYPE, value);
1983 }
1984 #endif
1985 #if ENABLE_ASH_MAIL
1986 static void chkmail(void);
1987 static void changemail(const char *var_value) FAST_FUNC;
1988 #else
1989 # define chkmail()  ((void)0)
1990 #endif
1991 static void changepath(const char *) FAST_FUNC;
1992 #if ENABLE_ASH_RANDOM_SUPPORT
1993 static void change_random(const char *) FAST_FUNC;
1994 #endif
1995
1996 static const struct {
1997         int flags;
1998         const char *var_text;
1999         void (*var_func)(const char *) FAST_FUNC;
2000 } varinit_data[] = {
2001         /*
2002          * Note: VEXPORT would not work correctly here for NOFORK applets:
2003          * some environment strings may be constant.
2004          */
2005         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2006 #if ENABLE_ASH_MAIL
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2008         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2009 #endif
2010         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2011         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2013         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2014 #if ENABLE_ASH_GETOPTS
2015         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2016 #endif
2017 #if ENABLE_ASH_RANDOM_SUPPORT
2018         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2019 #endif
2020 #if ENABLE_LOCALE_SUPPORT
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2022         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2023 #endif
2024 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2025         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2026 #endif
2027 };
2028
2029 struct redirtab;
2030
2031 struct globals_var {
2032         struct shparam shellparam;      /* $@ current positional parameters */
2033         struct redirtab *redirlist;
2034         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2035         struct var *vartab[VTABSIZE];
2036         struct var varinit[ARRAY_SIZE(varinit_data)];
2037 };
2038 extern struct globals_var *const ash_ptr_to_globals_var;
2039 #define G_var (*ash_ptr_to_globals_var)
2040 #define shellparam    (G_var.shellparam   )
2041 //#define redirlist     (G_var.redirlist    )
2042 #define preverrout_fd (G_var.preverrout_fd)
2043 #define vartab        (G_var.vartab       )
2044 #define varinit       (G_var.varinit      )
2045 #define INIT_G_var() do { \
2046         unsigned i; \
2047         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2048         barrier(); \
2049         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2050                 varinit[i].flags    = varinit_data[i].flags; \
2051                 varinit[i].var_text = varinit_data[i].var_text; \
2052                 varinit[i].var_func = varinit_data[i].var_func; \
2053         } \
2054 } while (0)
2055
2056 #define vifs      varinit[0]
2057 #if ENABLE_ASH_MAIL
2058 # define vmail    (&vifs)[1]
2059 # define vmpath   (&vmail)[1]
2060 # define vpath    (&vmpath)[1]
2061 #else
2062 # define vpath    (&vifs)[1]
2063 #endif
2064 #define vps1      (&vpath)[1]
2065 #define vps2      (&vps1)[1]
2066 #define vps4      (&vps2)[1]
2067 #if ENABLE_ASH_GETOPTS
2068 # define voptind  (&vps4)[1]
2069 # if ENABLE_ASH_RANDOM_SUPPORT
2070 #  define vrandom (&voptind)[1]
2071 # endif
2072 #else
2073 # if ENABLE_ASH_RANDOM_SUPPORT
2074 #  define vrandom (&vps4)[1]
2075 # endif
2076 #endif
2077
2078 /*
2079  * The following macros access the values of the above variables.
2080  * They have to skip over the name.  They return the null string
2081  * for unset variables.
2082  */
2083 #define ifsval()        (vifs.var_text + 4)
2084 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2085 #if ENABLE_ASH_MAIL
2086 # define mailval()      (vmail.var_text + 5)
2087 # define mpathval()     (vmpath.var_text + 9)
2088 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2089 #endif
2090 #define pathval()       (vpath.var_text + 5)
2091 #define ps1val()        (vps1.var_text + 4)
2092 #define ps2val()        (vps2.var_text + 4)
2093 #define ps4val()        (vps4.var_text + 4)
2094 #if ENABLE_ASH_GETOPTS
2095 # define optindval()    (voptind.var_text + 7)
2096 #endif
2097
2098 #if ENABLE_ASH_GETOPTS
2099 static void FAST_FUNC
2100 getoptsreset(const char *value)
2101 {
2102         shellparam.optind = 1;
2103         if (is_number(value))
2104                 shellparam.optind = number(value) ?: 1;
2105         shellparam.optoff = -1;
2106 }
2107 #endif
2108
2109 /*
2110  * Compares two strings up to the first = or '\0'.  The first
2111  * string must be terminated by '='; the second may be terminated by
2112  * either '=' or '\0'.
2113  */
2114 static int
2115 varcmp(const char *p, const char *q)
2116 {
2117         int c, d;
2118
2119         while ((c = *p) == (d = *q)) {
2120                 if (c == '\0' || c == '=')
2121                         goto out;
2122                 p++;
2123                 q++;
2124         }
2125         if (c == '=')
2126                 c = '\0';
2127         if (d == '=')
2128                 d = '\0';
2129  out:
2130         return c - d;
2131 }
2132
2133 /*
2134  * Find the appropriate entry in the hash table from the name.
2135  */
2136 static struct var **
2137 hashvar(const char *p)
2138 {
2139         unsigned hashval;
2140
2141         hashval = ((unsigned char) *p) << 4;
2142         while (*p && *p != '=')
2143                 hashval += (unsigned char) *p++;
2144         return &vartab[hashval % VTABSIZE];
2145 }
2146
2147 static int
2148 vpcmp(const void *a, const void *b)
2149 {
2150         return varcmp(*(const char **)a, *(const char **)b);
2151 }
2152
2153 /*
2154  * This routine initializes the builtin variables.
2155  */
2156 static void
2157 initvar(void)
2158 {
2159         struct var *vp;
2160         struct var *end;
2161         struct var **vpp;
2162
2163         /*
2164          * PS1 depends on uid
2165          */
2166 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2167         vps1.var_text = "PS1=\\w \\$ ";
2168 #else
2169         if (!geteuid())
2170                 vps1.var_text = "PS1=# ";
2171 #endif
2172         vp = varinit;
2173         end = vp + ARRAY_SIZE(varinit);
2174         do {
2175                 vpp = hashvar(vp->var_text);
2176                 vp->next = *vpp;
2177                 *vpp = vp;
2178         } while (++vp < end);
2179 }
2180
2181 static struct var **
2182 findvar(struct var **vpp, const char *name)
2183 {
2184         for (; *vpp; vpp = &(*vpp)->next) {
2185                 if (varcmp((*vpp)->var_text, name) == 0) {
2186                         break;
2187                 }
2188         }
2189         return vpp;
2190 }
2191
2192 /*
2193  * Find the value of a variable.  Returns NULL if not set.
2194  */
2195 static const char* FAST_FUNC
2196 lookupvar(const char *name)
2197 {
2198         struct var *v;
2199
2200         v = *findvar(hashvar(name), name);
2201         if (v) {
2202 #if ENABLE_ASH_RANDOM_SUPPORT
2203         /*
2204          * Dynamic variables are implemented roughly the same way they are
2205          * in bash. Namely, they're "special" so long as they aren't unset.
2206          * As soon as they're unset, they're no longer dynamic, and dynamic
2207          * lookup will no longer happen at that point. -- PFM.
2208          */
2209                 if (v->flags & VDYNAMIC)
2210                         v->var_func(NULL);
2211 #endif
2212                 if (!(v->flags & VUNSET))
2213                         return var_end(v->var_text);
2214         }
2215         return NULL;
2216 }
2217
2218 #if ENABLE_UNICODE_SUPPORT
2219 static void
2220 reinit_unicode_for_ash(void)
2221 {
2222         /* Unicode support should be activated even if LANG is set
2223          * _during_ shell execution, not only if it was set when
2224          * shell was started. Therefore, re-check LANG every time:
2225          */
2226         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2227          || ENABLE_UNICODE_USING_LOCALE
2228         ) {
2229                 const char *s = lookupvar("LC_ALL");
2230                 if (!s) s = lookupvar("LC_CTYPE");
2231                 if (!s) s = lookupvar("LANG");
2232                 reinit_unicode(s);
2233         }
2234 }
2235 #else
2236 # define reinit_unicode_for_ash() ((void)0)
2237 #endif
2238
2239 /*
2240  * Search the environment of a builtin command.
2241  */
2242 static ALWAYS_INLINE const char *
2243 bltinlookup(const char *name)
2244 {
2245         return lookupvar(name);
2246 }
2247
2248 /*
2249  * Same as setvar except that the variable and value are passed in
2250  * the first argument as name=value.  Since the first argument will
2251  * be actually stored in the table, it should not be a string that
2252  * will go away.
2253  * Called with interrupts off.
2254  */
2255 static struct var *
2256 setvareq(char *s, int flags)
2257 {
2258         struct var *vp, **vpp;
2259
2260         vpp = hashvar(s);
2261         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2262         vpp = findvar(vpp, s);
2263         vp = *vpp;
2264         if (vp) {
2265                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2266                         const char *n;
2267
2268                         if (flags & VNOSAVE)
2269                                 free(s);
2270                         n = vp->var_text;
2271                         exitstatus = 1;
2272                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2273                 }
2274
2275                 if (flags & VNOSET)
2276                         goto out;
2277
2278                 if (vp->var_func && !(flags & VNOFUNC))
2279                         vp->var_func(var_end(s));
2280
2281                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2282                         free((char*)vp->var_text);
2283
2284                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2285                         *vpp = vp->next;
2286                         free(vp);
2287  out_free:
2288                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2289                                 free(s);
2290                         goto out;
2291                 }
2292
2293                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2294         } else {
2295                 /* variable s is not found */
2296                 if (flags & VNOSET)
2297                         goto out;
2298                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2299                         goto out_free;
2300                 vp = ckzalloc(sizeof(*vp));
2301                 vp->next = *vpp;
2302                 /*vp->func = NULL; - ckzalloc did it */
2303                 *vpp = vp;
2304         }
2305         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2306                 s = ckstrdup(s);
2307         vp->var_text = s;
2308         vp->flags = flags;
2309
2310  out:
2311         return vp;
2312 }
2313
2314 /*
2315  * Set the value of a variable.  The flags argument is ored with the
2316  * flags of the variable.  If val is NULL, the variable is unset.
2317  */
2318 static struct var *
2319 setvar(const char *name, const char *val, int flags)
2320 {
2321         const char *q;
2322         char *p;
2323         char *nameeq;
2324         size_t namelen;
2325         size_t vallen;
2326         struct var *vp;
2327
2328         q = endofname(name);
2329         p = strchrnul(q, '=');
2330         namelen = p - name;
2331         if (!namelen || p != q)
2332                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2333         vallen = 0;
2334         if (val == NULL) {
2335                 flags |= VUNSET;
2336         } else {
2337                 vallen = strlen(val);
2338         }
2339
2340         INT_OFF;
2341         nameeq = ckmalloc(namelen + vallen + 2);
2342         p = mempcpy(nameeq, name, namelen);
2343         if (val) {
2344                 *p++ = '=';
2345                 p = mempcpy(p, val, vallen);
2346         }
2347         *p = '\0';
2348         vp = setvareq(nameeq, flags | VNOSAVE);
2349         INT_ON;
2350
2351         return vp;
2352 }
2353
2354 static void FAST_FUNC
2355 setvar0(const char *name, const char *val)
2356 {
2357         setvar(name, val, 0);
2358 }
2359
2360 /*
2361  * Unset the specified variable.
2362  */
2363 static void
2364 unsetvar(const char *s)
2365 {
2366         setvar(s, NULL, 0);
2367 }
2368
2369 /*
2370  * Process a linked list of variable assignments.
2371  */
2372 static void
2373 listsetvar(struct strlist *list_set_var, int flags)
2374 {
2375         struct strlist *lp = list_set_var;
2376
2377         if (!lp)
2378                 return;
2379         INT_OFF;
2380         do {
2381                 setvareq(lp->text, flags);
2382                 lp = lp->next;
2383         } while (lp);
2384         INT_ON;
2385 }
2386
2387 /*
2388  * Generate a list of variables satisfying the given conditions.
2389  */
2390 static char **
2391 listvars(int on, int off, char ***end)
2392 {
2393         struct var **vpp;
2394         struct var *vp;
2395         char **ep;
2396         int mask;
2397
2398         STARTSTACKSTR(ep);
2399         vpp = vartab;
2400         mask = on | off;
2401         do {
2402                 for (vp = *vpp; vp; vp = vp->next) {
2403                         if ((vp->flags & mask) == on) {
2404                                 if (ep == stackstrend())
2405                                         ep = growstackstr();
2406                                 *ep++ = (char*)vp->var_text;
2407                         }
2408                 }
2409         } while (++vpp < vartab + VTABSIZE);
2410         if (ep == stackstrend())
2411                 ep = growstackstr();
2412         if (end)
2413                 *end = ep;
2414         *ep++ = NULL;
2415         return grabstackstr(ep);
2416 }
2417
2418
2419 /* ============ Path search helper
2420  *
2421  * The variable path (passed by reference) should be set to the start
2422  * of the path before the first call; path_advance will update
2423  * this value as it proceeds.  Successive calls to path_advance will return
2424  * the possible path expansions in sequence.  If an option (indicated by
2425  * a percent sign) appears in the path entry then the global variable
2426  * pathopt will be set to point to it; otherwise pathopt will be set to
2427  * NULL.
2428  */
2429 static const char *pathopt;     /* set by path_advance */
2430
2431 static char *
2432 path_advance(const char **path, const char *name)
2433 {
2434         const char *p;
2435         char *q;
2436         const char *start;
2437         size_t len;
2438
2439         if (*path == NULL)
2440                 return NULL;
2441         start = *path;
2442         for (p = start; *p && *p != ':' && *p != '%'; p++)
2443                 continue;
2444         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2445         while (stackblocksize() < len)
2446                 growstackblock();
2447         q = stackblock();
2448         if (p != start) {
2449                 q = mempcpy(q, start, p - start);
2450                 *q++ = '/';
2451         }
2452         strcpy(q, name);
2453         pathopt = NULL;
2454         if (*p == '%') {
2455                 pathopt = ++p;
2456                 while (*p && *p != ':')
2457                         p++;
2458         }
2459         if (*p == ':')
2460                 *path = p + 1;
2461         else
2462                 *path = NULL;
2463         return stalloc(len);
2464 }
2465
2466
2467 /* ============ Prompt */
2468
2469 static smallint doprompt;                   /* if set, prompt the user */
2470 static smallint needprompt;                 /* true if interactive and at start of line */
2471
2472 #if ENABLE_FEATURE_EDITING
2473 static line_input_t *line_input_state;
2474 static const char *cmdedit_prompt;
2475 static void
2476 putprompt(const char *s)
2477 {
2478         if (ENABLE_ASH_EXPAND_PRMT) {
2479                 free((char*)cmdedit_prompt);
2480                 cmdedit_prompt = ckstrdup(s);
2481                 return;
2482         }
2483         cmdedit_prompt = s;
2484 }
2485 #else
2486 static void
2487 putprompt(const char *s)
2488 {
2489         out2str(s);
2490 }
2491 #endif
2492
2493 /* expandstr() needs parsing machinery, so it is far away ahead... */
2494 static const char *expandstr(const char *ps, int syntax_type);
2495 /* Values for syntax param */
2496 #define BASESYNTAX 0    /* not in quotes */
2497 #define DQSYNTAX   1    /* in double quotes */
2498 #define SQSYNTAX   2    /* in single quotes */
2499 #define ARISYNTAX  3    /* in arithmetic */
2500 #if ENABLE_ASH_EXPAND_PRMT
2501 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2502 #endif
2503 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2504
2505 /*
2506  * called by editline -- any expansions to the prompt should be added here.
2507  */
2508 static void
2509 setprompt_if(smallint do_set, int whichprompt)
2510 {
2511         const char *prompt;
2512         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2513
2514         if (!do_set)
2515                 return;
2516
2517         needprompt = 0;
2518
2519         switch (whichprompt) {
2520         case 1:
2521                 prompt = ps1val();
2522                 break;
2523         case 2:
2524                 prompt = ps2val();
2525                 break;
2526         default:                        /* 0 */
2527                 prompt = nullstr;
2528         }
2529 #if ENABLE_ASH_EXPAND_PRMT
2530         pushstackmark(&smark, stackblocksize());
2531         putprompt(expandstr(prompt, PSSYNTAX));
2532         popstackmark(&smark);
2533 #else
2534         putprompt(prompt);
2535 #endif
2536 }
2537
2538
2539 /* ============ The cd and pwd commands */
2540
2541 #define CD_PHYSICAL 1
2542 #define CD_PRINT 2
2543
2544 static int
2545 cdopt(void)
2546 {
2547         int flags = 0;
2548         int i, j;
2549
2550         j = 'L';
2551         while ((i = nextopt("LP")) != '\0') {
2552                 if (i != j) {
2553                         flags ^= CD_PHYSICAL;
2554                         j = i;
2555                 }
2556         }
2557
2558         return flags;
2559 }
2560
2561 /*
2562  * Update curdir (the name of the current directory) in response to a
2563  * cd command.
2564  */
2565 static const char *
2566 updatepwd(const char *dir)
2567 {
2568         char *new;
2569         char *p;
2570         char *cdcomppath;
2571         const char *lim;
2572
2573         cdcomppath = sstrdup(dir);
2574         STARTSTACKSTR(new);
2575         if (*dir != '/') {
2576                 if (curdir == nullstr)
2577                         return 0;
2578                 new = stack_putstr(curdir, new);
2579         }
2580         new = makestrspace(strlen(dir) + 2, new);
2581         lim = (char *)stackblock() + 1;
2582         if (*dir != '/') {
2583                 if (new[-1] != '/')
2584                         USTPUTC('/', new);
2585                 if (new > lim && *lim == '/')
2586                         lim++;
2587         } else {
2588                 USTPUTC('/', new);
2589                 cdcomppath++;
2590                 if (dir[1] == '/' && dir[2] != '/') {
2591                         USTPUTC('/', new);
2592                         cdcomppath++;
2593                         lim++;
2594                 }
2595         }
2596         p = strtok(cdcomppath, "/");
2597         while (p) {
2598                 switch (*p) {
2599                 case '.':
2600                         if (p[1] == '.' && p[2] == '\0') {
2601                                 while (new > lim) {
2602                                         STUNPUTC(new);
2603                                         if (new[-1] == '/')
2604                                                 break;
2605                                 }
2606                                 break;
2607                         }
2608                         if (p[1] == '\0')
2609                                 break;
2610                         /* fall through */
2611                 default:
2612                         new = stack_putstr(p, new);
2613                         USTPUTC('/', new);
2614                 }
2615                 p = strtok(NULL, "/");
2616         }
2617         if (new > lim)
2618                 STUNPUTC(new);
2619         *new = 0;
2620         return stackblock();
2621 }
2622
2623 /*
2624  * Find out what the current directory is. If we already know the current
2625  * directory, this routine returns immediately.
2626  */
2627 static char *
2628 getpwd(void)
2629 {
2630         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2631         return dir ? dir : nullstr;
2632 }
2633
2634 static void
2635 setpwd(const char *val, int setold)
2636 {
2637         char *oldcur, *dir;
2638
2639         oldcur = dir = curdir;
2640
2641         if (setold) {
2642                 setvar("OLDPWD", oldcur, VEXPORT);
2643         }
2644         INT_OFF;
2645         if (physdir != nullstr) {
2646                 if (physdir != oldcur)
2647                         free(physdir);
2648                 physdir = nullstr;
2649         }
2650         if (oldcur == val || !val) {
2651                 char *s = getpwd();
2652                 physdir = s;
2653                 if (!val)
2654                         dir = s;
2655         } else
2656                 dir = ckstrdup(val);
2657         if (oldcur != dir && oldcur != nullstr) {
2658                 free(oldcur);
2659         }
2660         curdir = dir;
2661         INT_ON;
2662         setvar("PWD", dir, VEXPORT);
2663 }
2664
2665 static void hashcd(void);
2666
2667 /*
2668  * Actually do the chdir.  We also call hashcd to let other routines
2669  * know that the current directory has changed.
2670  */
2671 static int
2672 docd(const char *dest, int flags)
2673 {
2674         const char *dir = NULL;
2675         int err;
2676
2677         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2678
2679         INT_OFF;
2680         if (!(flags & CD_PHYSICAL)) {
2681                 dir = updatepwd(dest);
2682                 if (dir)
2683                         dest = dir;
2684         }
2685         err = chdir(dest);
2686         if (err)
2687                 goto out;
2688         setpwd(dir, 1);
2689         hashcd();
2690  out:
2691         INT_ON;
2692         return err;
2693 }
2694
2695 static int FAST_FUNC
2696 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2697 {
2698         const char *dest;
2699         const char *path;
2700         const char *p;
2701         char c;
2702         struct stat statb;
2703         int flags;
2704
2705         flags = cdopt();
2706         dest = *argptr;
2707         if (!dest)
2708                 dest = bltinlookup("HOME");
2709         else if (LONE_DASH(dest)) {
2710                 dest = bltinlookup("OLDPWD");
2711                 flags |= CD_PRINT;
2712         }
2713         if (!dest)
2714                 dest = nullstr;
2715         if (*dest == '/')
2716                 goto step6;
2717         if (*dest == '.') {
2718                 c = dest[1];
2719  dotdot:
2720                 switch (c) {
2721                 case '\0':
2722                 case '/':
2723                         goto step6;
2724                 case '.':
2725                         c = dest[2];
2726                         if (c != '.')
2727                                 goto dotdot;
2728                 }
2729         }
2730         if (!*dest)
2731                 dest = ".";
2732         path = bltinlookup("CDPATH");
2733         while (path) {
2734                 c = *path;
2735                 p = path_advance(&path, dest);
2736                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2737                         if (c && c != ':')
2738                                 flags |= CD_PRINT;
2739  docd:
2740                         if (!docd(p, flags))
2741                                 goto out;
2742                         goto err;
2743                 }
2744         }
2745
2746  step6:
2747         p = dest;
2748         goto docd;
2749
2750  err:
2751         ash_msg_and_raise_error("can't cd to %s", dest);
2752         /* NOTREACHED */
2753  out:
2754         if (flags & CD_PRINT)
2755                 out1fmt("%s\n", curdir);
2756         return 0;
2757 }
2758
2759 static int FAST_FUNC
2760 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2761 {
2762         int flags;
2763         const char *dir = curdir;
2764
2765         flags = cdopt();
2766         if (flags) {
2767                 if (physdir == nullstr)
2768                         setpwd(dir, 0);
2769                 dir = physdir;
2770         }
2771         out1fmt("%s\n", dir);
2772         return 0;
2773 }
2774
2775
2776 /* ============ ... */
2777
2778
2779 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2780
2781 /* Syntax classes */
2782 #define CWORD     0             /* character is nothing special */
2783 #define CNL       1             /* newline character */
2784 #define CBACK     2             /* a backslash character */
2785 #define CSQUOTE   3             /* single quote */
2786 #define CDQUOTE   4             /* double quote */
2787 #define CENDQUOTE 5             /* a terminating quote */
2788 #define CBQUOTE   6             /* backwards single quote */
2789 #define CVAR      7             /* a dollar sign */
2790 #define CENDVAR   8             /* a '}' character */
2791 #define CLP       9             /* a left paren in arithmetic */
2792 #define CRP      10             /* a right paren in arithmetic */
2793 #define CENDFILE 11             /* end of file */
2794 #define CCTL     12             /* like CWORD, except it must be escaped */
2795 #define CSPCL    13             /* these terminate a word */
2796 #define CIGN     14             /* character should be ignored */
2797
2798 #define PEOF     256
2799 #if ENABLE_ASH_ALIAS
2800 # define PEOA    257
2801 #endif
2802
2803 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2804
2805 #if ENABLE_FEATURE_SH_MATH
2806 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2807 #else
2808 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2809 #endif
2810 static const uint16_t S_I_T[] ALIGN2 = {
2811 #if ENABLE_ASH_ALIAS
2812         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2813 #endif
2814         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2815         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2816         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2817         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2818         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2819         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2820         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2821         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2822         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2823         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2824         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2825 #if !USE_SIT_FUNCTION
2826         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2827         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2828         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2829 #endif
2830 #undef SIT_ITEM
2831 };
2832 /* Constants below must match table above */
2833 enum {
2834 #if ENABLE_ASH_ALIAS
2835         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2836 #endif
2837         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2838         CNL_CNL_CNL_CNL                    , /*  2 */
2839         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2840         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2841         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2842         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2843         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2844         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2845         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2846         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2847         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2848         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2849         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2850         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2851 };
2852
2853 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2854  * caller must ensure proper cast on it if c is *char_ptr!
2855  */
2856 #if USE_SIT_FUNCTION
2857
2858 static int
2859 SIT(int c, int syntax)
2860 {
2861         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2862         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2863         /*
2864          * This causes '/' to be prepended with CTLESC in dquoted string,
2865          * making "./file"* treated incorrectly because we feed
2866          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2867          * The "homegrown" glob implementation is okay with that,
2868          * but glibc one isn't. With '/' always treated as CWORD,
2869          * both work fine.
2870          */
2871 # if ENABLE_ASH_ALIAS
2872         static const uint8_t syntax_index_table[] ALIGN1 = {
2873                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2874                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2875                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2876                 11, 3                           /* "}~" */
2877         };
2878 # else
2879         static const uint8_t syntax_index_table[] ALIGN1 = {
2880                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2881                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2882                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2883                 10, 2                           /* "}~" */
2884         };
2885 # endif
2886         const char *s;
2887         int indx;
2888
2889         if (c == PEOF)
2890                 return CENDFILE;
2891 # if ENABLE_ASH_ALIAS
2892         if (c == PEOA)
2893                 indx = 0;
2894         else
2895 # endif
2896         {
2897                 /* Cast is purely for paranoia here,
2898                  * just in case someone passed signed char to us */
2899                 if ((unsigned char)c >= CTL_FIRST
2900                  && (unsigned char)c <= CTL_LAST
2901                 ) {
2902                         return CCTL;
2903                 }
2904                 s = strchrnul(spec_symbls, c);
2905                 if (*s == '\0')
2906                         return CWORD;
2907                 indx = syntax_index_table[s - spec_symbls];
2908         }
2909         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2910 }
2911
2912 #else   /* !USE_SIT_FUNCTION */
2913
2914 static const uint8_t syntax_index_table[] ALIGN1 = {
2915         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2916         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2923         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2924         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2925         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2926         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2927         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2946         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2947         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2948         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2949         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2950         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2951         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2953         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2955         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2956         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2957         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2958         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2961         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2962         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2963 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2964         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2978         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2979         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2980         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2981         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3006         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3009         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3010         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3011         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3014         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3015         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3016         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3039         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3040         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3041         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3042         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3043         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3044         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3045         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3046         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3047         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3048         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3049         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3050         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3051         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3052         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3053         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3054         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3173         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3174 # if ENABLE_ASH_ALIAS
3175         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3176 # endif
3177 };
3178
3179 #if 1
3180 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3181 #else /* debug version, caught one signed char bug */
3182 # define SIT(c, syntax) \
3183         ({ \
3184                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3185                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3186                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3187                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3188                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3189         })
3190 #endif
3191
3192 #endif  /* !USE_SIT_FUNCTION */
3193
3194
3195 /* ============ Alias handling */
3196
3197 #if ENABLE_ASH_ALIAS
3198
3199 #define ALIASINUSE 1
3200 #define ALIASDEAD  2
3201
3202 struct alias {
3203         struct alias *next;
3204         char *name;
3205         char *val;
3206         int flag;
3207 };
3208
3209
3210 static struct alias **atab; // [ATABSIZE];
3211 #define INIT_G_alias() do { \
3212         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3213 } while (0)
3214
3215
3216 static struct alias **
3217 __lookupalias(const char *name)
3218 {
3219         unsigned int hashval;
3220         struct alias **app;
3221         const char *p;
3222         unsigned int ch;
3223
3224         p = name;
3225
3226         ch = (unsigned char)*p;
3227         hashval = ch << 4;
3228         while (ch) {
3229                 hashval += ch;
3230                 ch = (unsigned char)*++p;
3231         }
3232         app = &atab[hashval % ATABSIZE];
3233
3234         for (; *app; app = &(*app)->next) {
3235                 if (strcmp(name, (*app)->name) == 0) {
3236                         break;
3237                 }
3238         }
3239
3240         return app;
3241 }
3242
3243 static struct alias *
3244 lookupalias(const char *name, int check)
3245 {
3246         struct alias *ap = *__lookupalias(name);
3247
3248         if (check && ap && (ap->flag & ALIASINUSE))
3249                 return NULL;
3250         return ap;
3251 }
3252
3253 static struct alias *
3254 freealias(struct alias *ap)
3255 {
3256         struct alias *next;
3257
3258         if (ap->flag & ALIASINUSE) {
3259                 ap->flag |= ALIASDEAD;
3260                 return ap;
3261         }
3262
3263         next = ap->next;
3264         free(ap->name);
3265         free(ap->val);
3266         free(ap);
3267         return next;
3268 }
3269
3270 static void
3271 setalias(const char *name, const char *val)
3272 {
3273         struct alias *ap, **app;
3274
3275         app = __lookupalias(name);
3276         ap = *app;
3277         INT_OFF;
3278         if (ap) {
3279                 if (!(ap->flag & ALIASINUSE)) {
3280                         free(ap->val);
3281                 }
3282                 ap->val = ckstrdup(val);
3283                 ap->flag &= ~ALIASDEAD;
3284         } else {
3285                 /* not found */
3286                 ap = ckzalloc(sizeof(struct alias));
3287                 ap->name = ckstrdup(name);
3288                 ap->val = ckstrdup(val);
3289                 /*ap->flag = 0; - ckzalloc did it */
3290                 /*ap->next = NULL;*/
3291                 *app = ap;
3292         }
3293         INT_ON;
3294 }
3295
3296 static int
3297 unalias(const char *name)
3298 {
3299         struct alias **app;
3300
3301         app = __lookupalias(name);
3302
3303         if (*app) {
3304                 INT_OFF;
3305                 *app = freealias(*app);
3306                 INT_ON;
3307                 return 0;
3308         }
3309
3310         return 1;
3311 }
3312
3313 static void
3314 rmaliases(void)
3315 {
3316         struct alias *ap, **app;
3317         int i;
3318
3319         INT_OFF;
3320         for (i = 0; i < ATABSIZE; i++) {
3321                 app = &atab[i];
3322                 for (ap = *app; ap; ap = *app) {
3323                         *app = freealias(*app);
3324                         if (ap == *app) {
3325                                 app = &ap->next;
3326                         }
3327                 }
3328         }
3329         INT_ON;
3330 }
3331
3332 static void
3333 printalias(const struct alias *ap)
3334 {
3335         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3336 }
3337
3338 /*
3339  * TODO - sort output
3340  */
3341 static int FAST_FUNC
3342 aliascmd(int argc UNUSED_PARAM, char **argv)
3343 {
3344         char *n, *v;
3345         int ret = 0;
3346         struct alias *ap;
3347
3348         if (!argv[1]) {
3349                 int i;
3350
3351                 for (i = 0; i < ATABSIZE; i++) {
3352                         for (ap = atab[i]; ap; ap = ap->next) {
3353                                 printalias(ap);
3354                         }
3355                 }
3356                 return 0;
3357         }
3358         while ((n = *++argv) != NULL) {
3359                 v = strchr(n+1, '=');
3360                 if (v == NULL) { /* n+1: funny ksh stuff */
3361                         ap = *__lookupalias(n);
3362                         if (ap == NULL) {
3363                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3364                                 ret = 1;
3365                         } else
3366                                 printalias(ap);
3367                 } else {
3368                         *v++ = '\0';
3369                         setalias(n, v);
3370                 }
3371         }
3372
3373         return ret;
3374 }
3375
3376 static int FAST_FUNC
3377 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3378 {
3379         int i;
3380
3381         while (nextopt("a") != '\0') {
3382                 rmaliases();
3383                 return 0;
3384         }
3385         for (i = 0; *argptr; argptr++) {
3386                 if (unalias(*argptr)) {
3387                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3388                         i = 1;
3389                 }
3390         }
3391
3392         return i;
3393 }
3394
3395 #endif /* ASH_ALIAS */
3396
3397
3398 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3399 #define FORK_FG    0
3400 #define FORK_BG    1
3401 #define FORK_NOJOB 2
3402
3403 /* mode flags for showjob(s) */
3404 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3405 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3406 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3407 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3408
3409 /*
3410  * A job structure contains information about a job.  A job is either a
3411  * single process or a set of processes contained in a pipeline.  In the
3412  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3413  * array of pids.
3414  */
3415 struct procstat {
3416         pid_t   ps_pid;         /* process id */
3417         int     ps_status;      /* last process status from wait() */
3418         char    *ps_cmd;        /* text of command being run */
3419 };
3420
3421 struct job {
3422         struct procstat ps0;    /* status of process */
3423         struct procstat *ps;    /* status or processes when more than one */
3424 #if JOBS
3425         int stopstatus;         /* status of a stopped job */
3426 #endif
3427         unsigned nprocs;        /* number of processes */
3428
3429 #define JOBRUNNING      0       /* at least one proc running */
3430 #define JOBSTOPPED      1       /* all procs are stopped */
3431 #define JOBDONE         2       /* all procs are completed */
3432         unsigned
3433                 state: 8,
3434 #if JOBS
3435                 sigint: 1,      /* job was killed by SIGINT */
3436                 jobctl: 1,      /* job running under job control */
3437 #endif
3438                 waited: 1,      /* true if this entry has been waited for */
3439                 used: 1,        /* true if this entry is in used */
3440                 changed: 1;     /* true if status has changed */
3441         struct job *prev_job;   /* previous job */
3442 };
3443
3444 static struct job *makejob(/*union node *,*/ int);
3445 static int forkshell(struct job *, union node *, int);
3446 static int waitforjob(struct job *);
3447
3448 #if !JOBS
3449 enum { doing_jobctl = 0 };
3450 #define setjobctl(on) do {} while (0)
3451 #else
3452 static smallint doing_jobctl; //references:8
3453 static void setjobctl(int);
3454 #endif
3455
3456 /*
3457  * Ignore a signal.
3458  */
3459 static void
3460 ignoresig(int signo)
3461 {
3462         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3463         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3464                 /* No, need to do it */
3465                 signal(signo, SIG_IGN);
3466         }
3467         sigmode[signo - 1] = S_HARD_IGN;
3468 }
3469
3470 /*
3471  * Only one usage site - in setsignal()
3472  */
3473 static void
3474 signal_handler(int signo)
3475 {
3476         if (signo == SIGCHLD) {
3477                 got_sigchld = 1;
3478                 if (!trap[SIGCHLD])
3479                         return;
3480         }
3481
3482         gotsig[signo - 1] = 1;
3483         pending_sig = signo;
3484
3485         if (signo == SIGINT && !trap[SIGINT]) {
3486                 if (!suppress_int) {
3487                         pending_sig = 0;
3488                         raise_interrupt(); /* does not return */
3489                 }
3490                 pending_int = 1;
3491         }
3492 }
3493
3494 /*
3495  * Set the signal handler for the specified signal.  The routine figures
3496  * out what it should be set to.
3497  */
3498 static void
3499 setsignal(int signo)
3500 {
3501         char *t;
3502         char cur_act, new_act;
3503         struct sigaction act;
3504
3505         t = trap[signo];
3506         new_act = S_DFL;
3507         if (t != NULL) { /* trap for this sig is set */
3508                 new_act = S_CATCH;
3509                 if (t[0] == '\0') /* trap is "": ignore this sig */
3510                         new_act = S_IGN;
3511         }
3512
3513         if (rootshell && new_act == S_DFL) {
3514                 switch (signo) {
3515                 case SIGINT:
3516                         if (iflag || minusc || sflag == 0)
3517                                 new_act = S_CATCH;
3518                         break;
3519                 case SIGQUIT:
3520 #if DEBUG
3521                         if (debug)
3522                                 break;
3523 #endif
3524                         /* man bash:
3525                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3526                          * commands run by bash have signal handlers
3527                          * set to the values inherited by the shell
3528                          * from its parent". */
3529                         new_act = S_IGN;
3530                         break;
3531                 case SIGTERM:
3532                         if (iflag)
3533                                 new_act = S_IGN;
3534                         break;
3535 #if JOBS
3536                 case SIGTSTP:
3537                 case SIGTTOU:
3538                         if (mflag)
3539                                 new_act = S_IGN;
3540                         break;
3541 #endif
3542                 }
3543         }
3544         /* if !rootshell, we reset SIGQUIT to DFL,
3545          * whereas we have to restore it to what shell got on entry.
3546          * This is handled by the fact that if signal was IGNored on entry,
3547          * then cur_act is S_HARD_IGN and we never change its sigaction
3548          * (see code below).
3549          */
3550
3551         if (signo == SIGCHLD)
3552                 new_act = S_CATCH;
3553
3554         t = &sigmode[signo - 1];
3555         cur_act = *t;
3556         if (cur_act == 0) {
3557                 /* current setting is not yet known */
3558                 if (sigaction(signo, NULL, &act)) {
3559                         /* pretend it worked; maybe we should give a warning,
3560                          * but other shells don't. We don't alter sigmode,
3561                          * so we retry every time.
3562                          * btw, in Linux it never fails. --vda */
3563                         return;
3564                 }
3565                 if (act.sa_handler == SIG_IGN) {
3566                         cur_act = S_HARD_IGN;
3567                         if (mflag
3568                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3569                         ) {
3570                                 cur_act = S_IGN;   /* don't hard ignore these */
3571                         }
3572                 }
3573                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3574                         /* installing SIG_DFL over SIG_DFL is a no-op */
3575                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3576                         *t = S_DFL;
3577                         return;
3578                 }
3579         }
3580         if (cur_act == S_HARD_IGN || cur_act == new_act)
3581                 return;
3582
3583         *t = new_act;
3584
3585         act.sa_handler = SIG_DFL;
3586         switch (new_act) {
3587         case S_CATCH:
3588                 act.sa_handler = signal_handler;
3589                 break;
3590         case S_IGN:
3591                 act.sa_handler = SIG_IGN;
3592                 break;
3593         }
3594         /* flags and mask matter only if !DFL and !IGN, but we do it
3595          * for all cases for more deterministic behavior:
3596          */
3597         act.sa_flags = 0; //TODO: why not SA_RESTART?
3598         sigfillset(&act.sa_mask);
3599
3600         sigaction_set(signo, &act);
3601 }
3602
3603 /* mode flags for set_curjob */
3604 #define CUR_DELETE 2
3605 #define CUR_RUNNING 1
3606 #define CUR_STOPPED 0
3607
3608 #if JOBS
3609 /* pgrp of shell on invocation */
3610 static int initialpgrp; //references:2
3611 static int ttyfd = -1; //5
3612 #endif
3613 /* array of jobs */
3614 static struct job *jobtab; //5
3615 /* size of array */
3616 static unsigned njobs; //4
3617 /* current job */
3618 static struct job *curjob; //lots
3619 /* number of presumed living untracked jobs */
3620 static int jobless; //4
3621
3622 #if 0
3623 /* Bash has a feature: it restores termios after a successful wait for
3624  * a foreground job which had at least one stopped or sigkilled member.
3625  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3626  * properly restoring tty state. Should we do this too?
3627  * A reproducer: ^Z an interactive python:
3628  *
3629  * # python
3630  * Python 2.7.12 (...)
3631  * >>> ^Z
3632  *      { python leaves tty in -icanon -echo state. We do survive that... }
3633  *  [1]+  Stopped                    python
3634  *      { ...however, next program (python #2) does not survive it well: }
3635  * # python
3636  * Python 2.7.12 (...)
3637  * >>> Traceback (most recent call last):
3638  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3639  *   File "<stdin>", line 1, in <module>
3640  * NameError: name 'qwerty' is not defined
3641  *
3642  * The implementation below is modeled on bash code and seems to work.
3643  * However, I'm not sure we should do this. For one: what if I'd fg
3644  * the stopped python instead? It'll be confused by "restored" tty state.
3645  */
3646 static struct termios shell_tty_info;
3647 static void
3648 get_tty_state(void)
3649 {
3650         if (rootshell && ttyfd >= 0)
3651                 tcgetattr(ttyfd, &shell_tty_info);
3652 }
3653 static void
3654 set_tty_state(void)
3655 {
3656         /* if (rootshell) - caller ensures this */
3657         if (ttyfd >= 0)
3658                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3659 }
3660 static int
3661 job_signal_status(struct job *jp)
3662 {
3663         int status;
3664         unsigned i;
3665         struct procstat *ps = jp->ps;
3666         for (i = 0; i < jp->nprocs; i++) {
3667                 status = ps[i].ps_status;
3668                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3669                         return status;
3670         }
3671         return 0;
3672 }
3673 static void
3674 restore_tty_if_stopped_or_signaled(struct job *jp)
3675 {
3676 //TODO: check what happens if we come from waitforjob() in expbackq()
3677         if (rootshell) {
3678                 int s = job_signal_status(jp);
3679                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3680                         set_tty_state();
3681         }
3682 }
3683 #else
3684 # define get_tty_state() ((void)0)
3685 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3686 #endif
3687
3688 static void
3689 set_curjob(struct job *jp, unsigned mode)
3690 {
3691         struct job *jp1;
3692         struct job **jpp, **curp;
3693
3694         /* first remove from list */
3695         jpp = curp = &curjob;
3696         while (1) {
3697                 jp1 = *jpp;
3698                 if (jp1 == jp)
3699                         break;
3700                 jpp = &jp1->prev_job;
3701         }
3702         *jpp = jp1->prev_job;
3703
3704         /* Then re-insert in correct position */
3705         jpp = curp;
3706         switch (mode) {
3707         default:
3708 #if DEBUG
3709                 abort();
3710 #endif
3711         case CUR_DELETE:
3712                 /* job being deleted */
3713                 break;
3714         case CUR_RUNNING:
3715                 /* newly created job or backgrounded job,
3716                  * put after all stopped jobs.
3717                  */
3718                 while (1) {
3719                         jp1 = *jpp;
3720 #if JOBS
3721                         if (!jp1 || jp1->state != JOBSTOPPED)
3722 #endif
3723                                 break;
3724                         jpp = &jp1->prev_job;
3725                 }
3726                 /* FALLTHROUGH */
3727 #if JOBS
3728         case CUR_STOPPED:
3729 #endif
3730                 /* newly stopped job - becomes curjob */
3731                 jp->prev_job = *jpp;
3732                 *jpp = jp;
3733                 break;
3734         }
3735 }
3736
3737 #if JOBS || DEBUG
3738 static int
3739 jobno(const struct job *jp)
3740 {
3741         return jp - jobtab + 1;
3742 }
3743 #endif
3744
3745 /*
3746  * Convert a job name to a job structure.
3747  */
3748 #if !JOBS
3749 #define getjob(name, getctl) getjob(name)
3750 #endif
3751 static struct job *
3752 getjob(const char *name, int getctl)
3753 {
3754         struct job *jp;
3755         struct job *found;
3756         const char *err_msg = "%s: no such job";
3757         unsigned num;
3758         int c;
3759         const char *p;
3760         char *(*match)(const char *, const char *);
3761
3762         jp = curjob;
3763         p = name;
3764         if (!p)
3765                 goto currentjob;
3766
3767         if (*p != '%')
3768                 goto err;
3769
3770         c = *++p;
3771         if (!c)
3772                 goto currentjob;
3773
3774         if (!p[1]) {
3775                 if (c == '+' || c == '%') {
3776  currentjob:
3777                         err_msg = "No current job";
3778                         goto check;
3779                 }
3780                 if (c == '-') {
3781                         if (jp)
3782                                 jp = jp->prev_job;
3783                         err_msg = "No previous job";
3784  check:
3785                         if (!jp)
3786                                 goto err;
3787                         goto gotit;
3788                 }
3789         }
3790
3791         if (is_number(p)) {
3792                 num = atoi(p);
3793                 if (num > 0 && num <= njobs) {
3794                         jp = jobtab + num - 1;
3795                         if (jp->used)
3796                                 goto gotit;
3797                         goto err;
3798                 }
3799         }
3800
3801         match = prefix;
3802         if (*p == '?') {
3803                 match = strstr;
3804                 p++;
3805         }
3806
3807         found = NULL;
3808         while (jp) {
3809                 if (match(jp->ps[0].ps_cmd, p)) {
3810                         if (found)
3811                                 goto err;
3812                         found = jp;
3813                         err_msg = "%s: ambiguous";
3814                 }
3815                 jp = jp->prev_job;
3816         }
3817         if (!found)
3818                 goto err;
3819         jp = found;
3820
3821  gotit:
3822 #if JOBS
3823         err_msg = "job %s not created under job control";
3824         if (getctl && jp->jobctl == 0)
3825                 goto err;
3826 #endif
3827         return jp;
3828  err:
3829         ash_msg_and_raise_error(err_msg, name);
3830 }
3831
3832 /*
3833  * Mark a job structure as unused.
3834  */
3835 static void
3836 freejob(struct job *jp)
3837 {
3838         struct procstat *ps;
3839         int i;
3840
3841         INT_OFF;
3842         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3843                 if (ps->ps_cmd != nullstr)
3844                         free(ps->ps_cmd);
3845         }
3846         if (jp->ps != &jp->ps0)
3847                 free(jp->ps);
3848         jp->used = 0;
3849         set_curjob(jp, CUR_DELETE);
3850         INT_ON;
3851 }
3852
3853 #if JOBS
3854 static void
3855 xtcsetpgrp(int fd, pid_t pgrp)
3856 {
3857         if (tcsetpgrp(fd, pgrp))
3858                 ash_msg_and_raise_perror("can't set tty process group");
3859 }
3860
3861 /*
3862  * Turn job control on and off.
3863  *
3864  * Note:  This code assumes that the third arg to ioctl is a character
3865  * pointer, which is true on Berkeley systems but not System V.  Since
3866  * System V doesn't have job control yet, this isn't a problem now.
3867  *
3868  * Called with interrupts off.
3869  */
3870 static void
3871 setjobctl(int on)
3872 {
3873         int fd;
3874         int pgrp;
3875
3876         if (on == doing_jobctl || rootshell == 0)
3877                 return;
3878         if (on) {
3879                 int ofd;
3880                 ofd = fd = open(_PATH_TTY, O_RDWR);
3881                 if (fd < 0) {
3882         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3883          * That sometimes helps to acquire controlling tty.
3884          * Obviously, a workaround for bugs when someone
3885          * failed to provide a controlling tty to bash! :) */
3886                         fd = 2;
3887                         while (!isatty(fd))
3888                                 if (--fd < 0)
3889                                         goto out;
3890                 }
3891                 /* fd is a tty at this point */
3892                 fd = fcntl(fd, F_DUPFD, 10);
3893                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3894                         close(ofd);
3895                 if (fd < 0)
3896                         goto out; /* F_DUPFD failed */
3897                 close_on_exec_on(fd);
3898                 while (1) { /* while we are in the background */
3899                         pgrp = tcgetpgrp(fd);
3900                         if (pgrp < 0) {
3901  out:
3902                                 ash_msg("can't access tty; job control turned off");
3903                                 mflag = on = 0;
3904                                 goto close;
3905                         }
3906                         if (pgrp == getpgrp())
3907                                 break;
3908                         killpg(0, SIGTTIN);
3909                 }
3910                 initialpgrp = pgrp;
3911
3912                 setsignal(SIGTSTP);
3913                 setsignal(SIGTTOU);
3914                 setsignal(SIGTTIN);
3915                 pgrp = rootpid;
3916                 setpgid(0, pgrp);
3917                 xtcsetpgrp(fd, pgrp);
3918         } else {
3919                 /* turning job control off */
3920                 fd = ttyfd;
3921                 pgrp = initialpgrp;
3922                 /* was xtcsetpgrp, but this can make exiting ash
3923                  * loop forever if pty is already deleted */
3924                 tcsetpgrp(fd, pgrp);
3925                 setpgid(0, pgrp);
3926                 setsignal(SIGTSTP);
3927                 setsignal(SIGTTOU);
3928                 setsignal(SIGTTIN);
3929  close:
3930                 if (fd >= 0)
3931                         close(fd);
3932                 fd = -1;
3933         }
3934         ttyfd = fd;
3935         doing_jobctl = on;
3936 }
3937
3938 static int FAST_FUNC
3939 killcmd(int argc, char **argv)
3940 {
3941         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3942                 int i = 1;
3943                 do {
3944                         if (argv[i][0] == '%') {
3945                                 /*
3946                                  * "kill %N" - job kill
3947                                  * Converting to pgrp / pid kill
3948                                  */
3949                                 struct job *jp;
3950                                 char *dst;
3951                                 int j, n;
3952
3953                                 jp = getjob(argv[i], 0);
3954                                 /*
3955                                  * In jobs started under job control, we signal
3956                                  * entire process group by kill -PGRP_ID.
3957                                  * This happens, f.e., in interactive shell.
3958                                  *
3959                                  * Otherwise, we signal each child via
3960                                  * kill PID1 PID2 PID3.
3961                                  * Testcases:
3962                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3963                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3964                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3965                                  */
3966                                 n = jp->nprocs; /* can't be 0 (I hope) */
3967                                 if (jp->jobctl)
3968                                         n = 1;
3969                                 dst = alloca(n * sizeof(int)*4);
3970                                 argv[i] = dst;
3971                                 for (j = 0; j < n; j++) {
3972                                         struct procstat *ps = &jp->ps[j];
3973                                         /* Skip non-running and not-stopped members
3974                                          * (i.e. dead members) of the job
3975                                          */
3976                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3977                                                 continue;
3978                                         /*
3979                                          * kill_main has matching code to expect
3980                                          * leading space. Needed to not confuse
3981                                          * negative pids with "kill -SIGNAL_NO" syntax
3982                                          */
3983                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3984                                 }
3985                                 *dst = '\0';
3986                         }
3987                 } while (argv[++i]);
3988         }
3989         return kill_main(argc, argv);
3990 }
3991
3992 static void
3993 showpipe(struct job *jp /*, FILE *out*/)
3994 {
3995         struct procstat *ps;
3996         struct procstat *psend;
3997
3998         psend = jp->ps + jp->nprocs;
3999         for (ps = jp->ps + 1; ps < psend; ps++)
4000                 printf(" | %s", ps->ps_cmd);
4001         newline_and_flush(stdout);
4002         flush_stdout_stderr();
4003 }
4004
4005
4006 static int
4007 restartjob(struct job *jp, int mode)
4008 {
4009         struct procstat *ps;
4010         int i;
4011         int status;
4012         pid_t pgid;
4013
4014         INT_OFF;
4015         if (jp->state == JOBDONE)
4016                 goto out;
4017         jp->state = JOBRUNNING;
4018         pgid = jp->ps[0].ps_pid;
4019         if (mode == FORK_FG) {
4020                 get_tty_state();
4021                 xtcsetpgrp(ttyfd, pgid);
4022         }
4023         killpg(pgid, SIGCONT);
4024         ps = jp->ps;
4025         i = jp->nprocs;
4026         do {
4027                 if (WIFSTOPPED(ps->ps_status)) {
4028                         ps->ps_status = -1;
4029                 }
4030                 ps++;
4031         } while (--i);
4032  out:
4033         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4034         INT_ON;
4035         return status;
4036 }
4037
4038 static int FAST_FUNC
4039 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4040 {
4041         struct job *jp;
4042         int mode;
4043         int retval;
4044
4045         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4046         nextopt(nullstr);
4047         argv = argptr;
4048         do {
4049                 jp = getjob(*argv, 1);
4050                 if (mode == FORK_BG) {
4051                         set_curjob(jp, CUR_RUNNING);
4052                         printf("[%d] ", jobno(jp));
4053                 }
4054                 out1str(jp->ps[0].ps_cmd);
4055                 showpipe(jp /*, stdout*/);
4056                 retval = restartjob(jp, mode);
4057         } while (*argv && *++argv);
4058         return retval;
4059 }
4060 #endif
4061
4062 static int
4063 sprint_status48(char *s, int status, int sigonly)
4064 {
4065         int col;
4066         int st;
4067
4068         col = 0;
4069         if (!WIFEXITED(status)) {
4070 #if JOBS
4071                 if (WIFSTOPPED(status))
4072                         st = WSTOPSIG(status);
4073                 else
4074 #endif
4075                         st = WTERMSIG(status);
4076                 if (sigonly) {
4077                         if (st == SIGINT || st == SIGPIPE)
4078                                 goto out;
4079 #if JOBS
4080                         if (WIFSTOPPED(status))
4081                                 goto out;
4082 #endif
4083                 }
4084                 st &= 0x7f;
4085 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4086                 col = fmtstr(s, 32, strsignal(st));
4087                 if (WCOREDUMP(status)) {
4088                         strcpy(s + col, " (core dumped)");
4089                         col += sizeof(" (core dumped)")-1;
4090                 }
4091         } else if (!sigonly) {
4092                 st = WEXITSTATUS(status);
4093                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4094         }
4095  out:
4096         return col;
4097 }
4098
4099 static int
4100 wait_block_or_sig(int *status)
4101 {
4102         int pid;
4103
4104         do {
4105                 sigset_t mask;
4106
4107                 /* Poll all children for changes in their state */
4108                 got_sigchld = 0;
4109                 /* if job control is active, accept stopped processes too */
4110                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4111                 if (pid != 0)
4112                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4113
4114                 /* Children exist, but none are ready. Sleep until interesting signal */
4115 #if 1
4116                 sigfillset(&mask);
4117                 sigprocmask(SIG_SETMASK, &mask, &mask);
4118                 while (!got_sigchld && !pending_sig)
4119                         sigsuspend(&mask);
4120                 sigprocmask(SIG_SETMASK, &mask, NULL);
4121 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4122                 while (!got_sigchld && !pending_sig)
4123                         pause();
4124 #endif
4125
4126                 /* If it was SIGCHLD, poll children again */
4127         } while (got_sigchld);
4128
4129         return pid;
4130 }
4131
4132 #define DOWAIT_NONBLOCK 0
4133 #define DOWAIT_BLOCK    1
4134 #define DOWAIT_BLOCK_OR_SIG 2
4135
4136 static int
4137 dowait(int block, struct job *job)
4138 {
4139         int pid;
4140         int status;
4141         struct job *jp;
4142         struct job *thisjob = NULL;
4143
4144         TRACE(("dowait(0x%x) called\n", block));
4145
4146         /* It's wrong to call waitpid() outside of INT_OFF region:
4147          * signal can arrive just after syscall return and handler can
4148          * longjmp away, losing stop/exit notification processing.
4149          * Thus, for "jobs" builtin, and for waiting for a fg job,
4150          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4151          *
4152          * However, for "wait" builtin it is wrong to simply call waitpid()
4153          * in INT_OFF region: "wait" needs to wait for any running job
4154          * to change state, but should exit on any trap too.
4155          * In INT_OFF region, a signal just before syscall entry can set
4156          * pending_sig variables, but we can't check them, and we would
4157          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4158          *
4159          * Because of this, we run inside INT_OFF, but use a special routine
4160          * which combines waitpid() and sigsuspend().
4161          * This is the reason why we need to have a handler for SIGCHLD:
4162          * SIG_DFL handler does not wake sigsuspend().
4163          */
4164         INT_OFF;
4165         if (block == DOWAIT_BLOCK_OR_SIG) {
4166                 pid = wait_block_or_sig(&status);
4167         } else {
4168                 int wait_flags = 0;
4169                 if (block == DOWAIT_NONBLOCK)
4170                         wait_flags = WNOHANG;
4171                 /* if job control is active, accept stopped processes too */
4172                 if (doing_jobctl)
4173                         wait_flags |= WUNTRACED;
4174                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4175                 pid = waitpid(-1, &status, wait_flags);
4176         }
4177         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4178                                 pid, status, errno, strerror(errno)));
4179         if (pid <= 0)
4180                 goto out;
4181
4182         thisjob = NULL;
4183         for (jp = curjob; jp; jp = jp->prev_job) {
4184                 int jobstate;
4185                 struct procstat *ps;
4186                 struct procstat *psend;
4187                 if (jp->state == JOBDONE)
4188                         continue;
4189                 jobstate = JOBDONE;
4190                 ps = jp->ps;
4191                 psend = ps + jp->nprocs;
4192                 do {
4193                         if (ps->ps_pid == pid) {
4194                                 TRACE(("Job %d: changing status of proc %d "
4195                                         "from 0x%x to 0x%x\n",
4196                                         jobno(jp), pid, ps->ps_status, status));
4197                                 ps->ps_status = status;
4198                                 thisjob = jp;
4199                         }
4200                         if (ps->ps_status == -1)
4201                                 jobstate = JOBRUNNING;
4202 #if JOBS
4203                         if (jobstate == JOBRUNNING)
4204                                 continue;
4205                         if (WIFSTOPPED(ps->ps_status)) {
4206                                 jp->stopstatus = ps->ps_status;
4207                                 jobstate = JOBSTOPPED;
4208                         }
4209 #endif
4210                 } while (++ps < psend);
4211                 if (!thisjob)
4212                         continue;
4213
4214                 /* Found the job where one of its processes changed its state.
4215                  * Is there at least one live and running process in this job? */
4216                 if (jobstate != JOBRUNNING) {
4217                         /* No. All live processes in the job are stopped
4218                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4219                          */
4220                         thisjob->changed = 1;
4221                         if (thisjob->state != jobstate) {
4222                                 TRACE(("Job %d: changing state from %d to %d\n",
4223                                         jobno(thisjob), thisjob->state, jobstate));
4224                                 thisjob->state = jobstate;
4225 #if JOBS
4226                                 if (jobstate == JOBSTOPPED)
4227                                         set_curjob(thisjob, CUR_STOPPED);
4228 #endif
4229                         }
4230                 }
4231                 goto out;
4232         }
4233         /* The process wasn't found in job list */
4234 #if JOBS
4235         if (!WIFSTOPPED(status))
4236                 jobless--;
4237 #endif
4238  out:
4239         INT_ON;
4240
4241         if (thisjob && thisjob == job) {
4242                 char s[48 + 1];
4243                 int len;
4244
4245                 len = sprint_status48(s, status, 1);
4246                 if (len) {
4247                         s[len] = '\n';
4248                         s[len + 1] = '\0';
4249                         out2str(s);
4250                 }
4251         }
4252         return pid;
4253 }
4254
4255 #if JOBS
4256 static void
4257 showjob(struct job *jp, int mode)
4258 {
4259         struct procstat *ps;
4260         struct procstat *psend;
4261         int col;
4262         int indent_col;
4263         char s[16 + 16 + 48];
4264         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4265
4266         ps = jp->ps;
4267
4268         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4269                 /* just output process (group) id of pipeline */
4270                 fprintf(out, "%d\n", ps->ps_pid);
4271                 return;
4272         }
4273
4274         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4275         indent_col = col;
4276
4277         if (jp == curjob)
4278                 s[col - 3] = '+';
4279         else if (curjob && jp == curjob->prev_job)
4280                 s[col - 3] = '-';
4281
4282         if (mode & SHOW_PIDS)
4283                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4284
4285         psend = ps + jp->nprocs;
4286
4287         if (jp->state == JOBRUNNING) {
4288                 strcpy(s + col, "Running");
4289                 col += sizeof("Running") - 1;
4290         } else {
4291                 int status = psend[-1].ps_status;
4292                 if (jp->state == JOBSTOPPED)
4293                         status = jp->stopstatus;
4294                 col += sprint_status48(s + col, status, 0);
4295         }
4296         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4297
4298         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4299          * or prints several "PID             | <cmdN>" lines,
4300          * depending on SHOW_PIDS bit.
4301          * We do not print status of individual processes
4302          * between PID and <cmdN>. bash does it, but not very well:
4303          * first line shows overall job status, not process status,
4304          * making it impossible to know 1st process status.
4305          */
4306         goto start;
4307         do {
4308                 /* for each process */
4309                 s[0] = '\0';
4310                 col = 33;
4311                 if (mode & SHOW_PIDS)
4312                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4313  start:
4314                 fprintf(out, "%s%*c%s%s",
4315                                 s,
4316                                 33 - col >= 0 ? 33 - col : 0, ' ',
4317                                 ps == jp->ps ? "" : "| ",
4318                                 ps->ps_cmd
4319                 );
4320         } while (++ps != psend);
4321         newline_and_flush(out);
4322
4323         jp->changed = 0;
4324
4325         if (jp->state == JOBDONE) {
4326                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4327                 freejob(jp);
4328         }
4329 }
4330
4331 /*
4332  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4333  * statuses have changed since the last call to showjobs.
4334  */
4335 static void
4336 showjobs(int mode)
4337 {
4338         struct job *jp;
4339
4340         TRACE(("showjobs(0x%x) called\n", mode));
4341
4342         /* Handle all finished jobs */
4343         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4344                 continue;
4345
4346         for (jp = curjob; jp; jp = jp->prev_job) {
4347                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4348                         showjob(jp, mode);
4349                 }
4350         }
4351 }
4352
4353 static int FAST_FUNC
4354 jobscmd(int argc UNUSED_PARAM, char **argv)
4355 {
4356         int mode, m;
4357
4358         mode = 0;
4359         while ((m = nextopt("lp")) != '\0') {
4360                 if (m == 'l')
4361                         mode |= SHOW_PIDS;
4362                 else
4363                         mode |= SHOW_ONLY_PGID;
4364         }
4365
4366         argv = argptr;
4367         if (*argv) {
4368                 do
4369                         showjob(getjob(*argv, 0), mode);
4370                 while (*++argv);
4371         } else {
4372                 showjobs(mode);
4373         }
4374
4375         return 0;
4376 }
4377 #endif /* JOBS */
4378
4379 /* Called only on finished or stopped jobs (no members are running) */
4380 static int
4381 getstatus(struct job *job)
4382 {
4383         int status;
4384         int retval;
4385         struct procstat *ps;
4386
4387         /* Fetch last member's status */
4388         ps = job->ps + job->nprocs - 1;
4389         status = ps->ps_status;
4390         if (pipefail) {
4391                 /* "set -o pipefail" mode: use last _nonzero_ status */
4392                 while (status == 0 && --ps >= job->ps)
4393                         status = ps->ps_status;
4394         }
4395
4396         retval = WEXITSTATUS(status);
4397         if (!WIFEXITED(status)) {
4398 #if JOBS
4399                 retval = WSTOPSIG(status);
4400                 if (!WIFSTOPPED(status))
4401 #endif
4402                 {
4403                         /* XXX: limits number of signals */
4404                         retval = WTERMSIG(status);
4405 #if JOBS
4406                         if (retval == SIGINT)
4407                                 job->sigint = 1;
4408 #endif
4409                 }
4410                 retval += 128;
4411         }
4412         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4413                 jobno(job), job->nprocs, status, retval));
4414         return retval;
4415 }
4416
4417 static int FAST_FUNC
4418 waitcmd(int argc UNUSED_PARAM, char **argv)
4419 {
4420         struct job *job;
4421         int retval;
4422         struct job *jp;
4423
4424         nextopt(nullstr);
4425         retval = 0;
4426
4427         argv = argptr;
4428         if (!*argv) {
4429                 /* wait for all jobs */
4430                 for (;;) {
4431                         jp = curjob;
4432                         while (1) {
4433                                 if (!jp) /* no running procs */
4434                                         goto ret;
4435                                 if (jp->state == JOBRUNNING)
4436                                         break;
4437                                 jp->waited = 1;
4438                                 jp = jp->prev_job;
4439                         }
4440         /* man bash:
4441          * "When bash is waiting for an asynchronous command via
4442          * the wait builtin, the reception of a signal for which a trap
4443          * has been set will cause the wait builtin to return immediately
4444          * with an exit status greater than 128, immediately after which
4445          * the trap is executed."
4446          */
4447                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4448         /* if child sends us a signal *and immediately exits*,
4449          * dowait() returns pid > 0. Check this case,
4450          * not "if (dowait() < 0)"!
4451          */
4452                         if (pending_sig)
4453                                 goto sigout;
4454                 }
4455         }
4456
4457         retval = 127;
4458         do {
4459                 if (**argv != '%') {
4460                         pid_t pid = number(*argv);
4461                         job = curjob;
4462                         while (1) {
4463                                 if (!job)
4464                                         goto repeat;
4465                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4466                                         break;
4467                                 job = job->prev_job;
4468                         }
4469                 } else {
4470                         job = getjob(*argv, 0);
4471                 }
4472                 /* loop until process terminated or stopped */
4473                 while (job->state == JOBRUNNING) {
4474                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4475                         if (pending_sig)
4476                                 goto sigout;
4477                 }
4478                 job->waited = 1;
4479                 retval = getstatus(job);
4480  repeat: ;
4481         } while (*++argv);
4482
4483  ret:
4484         return retval;
4485  sigout:
4486         retval = 128 + pending_sig;
4487         return retval;
4488 }
4489
4490 static struct job *
4491 growjobtab(void)
4492 {
4493         size_t len;
4494         ptrdiff_t offset;
4495         struct job *jp, *jq;
4496
4497         len = njobs * sizeof(*jp);
4498         jq = jobtab;
4499         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4500
4501         offset = (char *)jp - (char *)jq;
4502         if (offset) {
4503                 /* Relocate pointers */
4504                 size_t l = len;
4505
4506                 jq = (struct job *)((char *)jq + l);
4507                 while (l) {
4508                         l -= sizeof(*jp);
4509                         jq--;
4510 #define joff(p) ((struct job *)((char *)(p) + l))
4511 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4512                         if (joff(jp)->ps == &jq->ps0)
4513                                 jmove(joff(jp)->ps);
4514                         if (joff(jp)->prev_job)
4515                                 jmove(joff(jp)->prev_job);
4516                 }
4517                 if (curjob)
4518                         jmove(curjob);
4519 #undef joff
4520 #undef jmove
4521         }
4522
4523         njobs += 4;
4524         jobtab = jp;
4525         jp = (struct job *)((char *)jp + len);
4526         jq = jp + 3;
4527         do {
4528                 jq->used = 0;
4529         } while (--jq >= jp);
4530         return jp;
4531 }
4532
4533 /*
4534  * Return a new job structure.
4535  * Called with interrupts off.
4536  */
4537 static struct job *
4538 makejob(/*union node *node,*/ int nprocs)
4539 {
4540         int i;
4541         struct job *jp;
4542
4543         for (i = njobs, jp = jobtab; ; jp++) {
4544                 if (--i < 0) {
4545                         jp = growjobtab();
4546                         break;
4547                 }
4548                 if (jp->used == 0)
4549                         break;
4550                 if (jp->state != JOBDONE || !jp->waited)
4551                         continue;
4552 #if JOBS
4553                 if (doing_jobctl)
4554                         continue;
4555 #endif
4556                 freejob(jp);
4557                 break;
4558         }
4559         memset(jp, 0, sizeof(*jp));
4560 #if JOBS
4561         /* jp->jobctl is a bitfield.
4562          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4563         if (doing_jobctl)
4564                 jp->jobctl = 1;
4565 #endif
4566         jp->prev_job = curjob;
4567         curjob = jp;
4568         jp->used = 1;
4569         jp->ps = &jp->ps0;
4570         if (nprocs > 1) {
4571                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4572         }
4573         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4574                                 jobno(jp)));
4575         return jp;
4576 }
4577
4578 #if JOBS
4579 /*
4580  * Return a string identifying a command (to be printed by the
4581  * jobs command).
4582  */
4583 static char *cmdnextc;
4584
4585 static void
4586 cmdputs(const char *s)
4587 {
4588         static const char vstype[VSTYPE + 1][3] = {
4589                 "", "}", "-", "+", "?", "=",
4590                 "%", "%%", "#", "##"
4591                 IF_BASH_SUBSTR(, ":")
4592                 IF_BASH_PATTERN_SUBST(, "/", "//")
4593         };
4594
4595         const char *p, *str;
4596         char cc[2];
4597         char *nextc;
4598         unsigned char c;
4599         unsigned char subtype = 0;
4600         int quoted = 0;
4601
4602         cc[1] = '\0';
4603         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4604         p = s;
4605         while ((c = *p++) != '\0') {
4606                 str = NULL;
4607                 switch (c) {
4608                 case CTLESC:
4609                         c = *p++;
4610                         break;
4611                 case CTLVAR:
4612                         subtype = *p++;
4613                         if ((subtype & VSTYPE) == VSLENGTH)
4614                                 str = "${#";
4615                         else
4616                                 str = "${";
4617                         goto dostr;
4618                 case CTLENDVAR:
4619                         str = "\"}" + !(quoted & 1);
4620                         quoted >>= 1;
4621                         subtype = 0;
4622                         goto dostr;
4623                 case CTLBACKQ:
4624                         str = "$(...)";
4625                         goto dostr;
4626 #if ENABLE_FEATURE_SH_MATH
4627                 case CTLARI:
4628                         str = "$((";
4629                         goto dostr;
4630                 case CTLENDARI:
4631                         str = "))";
4632                         goto dostr;
4633 #endif
4634                 case CTLQUOTEMARK:
4635                         quoted ^= 1;
4636                         c = '"';
4637                         break;
4638                 case '=':
4639                         if (subtype == 0)
4640                                 break;
4641                         if ((subtype & VSTYPE) != VSNORMAL)
4642                                 quoted <<= 1;
4643                         str = vstype[subtype & VSTYPE];
4644                         if (subtype & VSNUL)
4645                                 c = ':';
4646                         else
4647                                 goto checkstr;
4648                         break;
4649                 case '\'':
4650                 case '\\':
4651                 case '"':
4652                 case '$':
4653                         /* These can only happen inside quotes */
4654                         cc[0] = c;
4655                         str = cc;
4656 //FIXME:
4657 // $ true $$ &
4658 // $ <cr>
4659 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4660                         c = '\\';
4661                         break;
4662                 default:
4663                         break;
4664                 }
4665                 USTPUTC(c, nextc);
4666  checkstr:
4667                 if (!str)
4668                         continue;
4669  dostr:
4670                 while ((c = *str++) != '\0') {
4671                         USTPUTC(c, nextc);
4672                 }
4673         } /* while *p++ not NUL */
4674
4675         if (quoted & 1) {
4676                 USTPUTC('"', nextc);
4677         }
4678         *nextc = 0;
4679         cmdnextc = nextc;
4680 }
4681
4682 /* cmdtxt() and cmdlist() call each other */
4683 static void cmdtxt(union node *n);
4684
4685 static void
4686 cmdlist(union node *np, int sep)
4687 {
4688         for (; np; np = np->narg.next) {
4689                 if (!sep)
4690                         cmdputs(" ");
4691                 cmdtxt(np);
4692                 if (sep && np->narg.next)
4693                         cmdputs(" ");
4694         }
4695 }
4696
4697 static void
4698 cmdtxt(union node *n)
4699 {
4700         union node *np;
4701         struct nodelist *lp;
4702         const char *p;
4703
4704         if (!n)
4705                 return;
4706         switch (n->type) {
4707         default:
4708 #if DEBUG
4709                 abort();
4710 #endif
4711         case NPIPE:
4712                 lp = n->npipe.cmdlist;
4713                 for (;;) {
4714                         cmdtxt(lp->n);
4715                         lp = lp->next;
4716                         if (!lp)
4717                                 break;
4718                         cmdputs(" | ");
4719                 }
4720                 break;
4721         case NSEMI:
4722                 p = "; ";
4723                 goto binop;
4724         case NAND:
4725                 p = " && ";
4726                 goto binop;
4727         case NOR:
4728                 p = " || ";
4729  binop:
4730                 cmdtxt(n->nbinary.ch1);
4731                 cmdputs(p);
4732                 n = n->nbinary.ch2;
4733                 goto donode;
4734         case NREDIR:
4735         case NBACKGND:
4736                 n = n->nredir.n;
4737                 goto donode;
4738         case NNOT:
4739                 cmdputs("!");
4740                 n = n->nnot.com;
4741  donode:
4742                 cmdtxt(n);
4743                 break;
4744         case NIF:
4745                 cmdputs("if ");
4746                 cmdtxt(n->nif.test);
4747                 cmdputs("; then ");
4748                 if (n->nif.elsepart) {
4749                         cmdtxt(n->nif.ifpart);
4750                         cmdputs("; else ");
4751                         n = n->nif.elsepart;
4752                 } else {
4753                         n = n->nif.ifpart;
4754                 }
4755                 p = "; fi";
4756                 goto dotail;
4757         case NSUBSHELL:
4758                 cmdputs("(");
4759                 n = n->nredir.n;
4760                 p = ")";
4761                 goto dotail;
4762         case NWHILE:
4763                 p = "while ";
4764                 goto until;
4765         case NUNTIL:
4766                 p = "until ";
4767  until:
4768                 cmdputs(p);
4769                 cmdtxt(n->nbinary.ch1);
4770                 n = n->nbinary.ch2;
4771                 p = "; done";
4772  dodo:
4773                 cmdputs("; do ");
4774  dotail:
4775                 cmdtxt(n);
4776                 goto dotail2;
4777         case NFOR:
4778                 cmdputs("for ");
4779                 cmdputs(n->nfor.var);
4780                 cmdputs(" in ");
4781                 cmdlist(n->nfor.args, 1);
4782                 n = n->nfor.body;
4783                 p = "; done";
4784                 goto dodo;
4785         case NDEFUN:
4786                 cmdputs(n->narg.text);
4787                 p = "() { ... }";
4788                 goto dotail2;
4789         case NCMD:
4790                 cmdlist(n->ncmd.args, 1);
4791                 cmdlist(n->ncmd.redirect, 0);
4792                 break;
4793         case NARG:
4794                 p = n->narg.text;
4795  dotail2:
4796                 cmdputs(p);
4797                 break;
4798         case NHERE:
4799         case NXHERE:
4800                 p = "<<...";
4801                 goto dotail2;
4802         case NCASE:
4803                 cmdputs("case ");
4804                 cmdputs(n->ncase.expr->narg.text);
4805                 cmdputs(" in ");
4806                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4807                         cmdtxt(np->nclist.pattern);
4808                         cmdputs(") ");
4809                         cmdtxt(np->nclist.body);
4810                         cmdputs(";; ");
4811                 }
4812                 p = "esac";
4813                 goto dotail2;
4814         case NTO:
4815                 p = ">";
4816                 goto redir;
4817         case NCLOBBER:
4818                 p = ">|";
4819                 goto redir;
4820         case NAPPEND:
4821                 p = ">>";
4822                 goto redir;
4823 #if BASH_REDIR_OUTPUT
4824         case NTO2:
4825 #endif
4826         case NTOFD:
4827                 p = ">&";
4828                 goto redir;
4829         case NFROM:
4830                 p = "<";
4831                 goto redir;
4832         case NFROMFD:
4833                 p = "<&";
4834                 goto redir;
4835         case NFROMTO:
4836                 p = "<>";
4837  redir:
4838                 cmdputs(utoa(n->nfile.fd));
4839                 cmdputs(p);
4840                 if (n->type == NTOFD || n->type == NFROMFD) {
4841                         if (n->ndup.dupfd >= 0)
4842                                 cmdputs(utoa(n->ndup.dupfd));
4843                         else
4844                                 cmdputs("-");
4845                         break;
4846                 }
4847                 n = n->nfile.fname;
4848                 goto donode;
4849         }
4850 }
4851
4852 static char *
4853 commandtext(union node *n)
4854 {
4855         char *name;
4856
4857         STARTSTACKSTR(cmdnextc);
4858         cmdtxt(n);
4859         name = stackblock();
4860         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4861         return ckstrdup(name);
4862 }
4863 #endif /* JOBS */
4864
4865 /*
4866  * Fork off a subshell.  If we are doing job control, give the subshell its
4867  * own process group.  Jp is a job structure that the job is to be added to.
4868  * N is the command that will be evaluated by the child.  Both jp and n may
4869  * be NULL.  The mode parameter can be one of the following:
4870  *      FORK_FG - Fork off a foreground process.
4871  *      FORK_BG - Fork off a background process.
4872  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4873  *                   process group even if job control is on.
4874  *
4875  * When job control is turned off, background processes have their standard
4876  * input redirected to /dev/null (except for the second and later processes
4877  * in a pipeline).
4878  *
4879  * Called with interrupts off.
4880  */
4881 /*
4882  * Clear traps on a fork.
4883  */
4884 static void
4885 clear_traps(void)
4886 {
4887         char **tp;
4888
4889         INT_OFF;
4890         for (tp = trap; tp < &trap[NSIG]; tp++) {
4891                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4892                         if (trap_ptr == trap)
4893                                 free(*tp);
4894                         /* else: it "belongs" to trap_ptr vector, don't free */
4895                         *tp = NULL;
4896                         if ((tp - trap) != 0)
4897                                 setsignal(tp - trap);
4898                 }
4899         }
4900         may_have_traps = 0;
4901         INT_ON;
4902 }
4903
4904 /* Lives far away from here, needed for forkchild */
4905 static void closescript(void);
4906
4907 /* Called after fork(), in child */
4908 /* jp and n are NULL when called by openhere() for heredoc support */
4909 static NOINLINE void
4910 forkchild(struct job *jp, union node *n, int mode)
4911 {
4912         int oldlvl;
4913
4914         TRACE(("Child shell %d\n", getpid()));
4915         oldlvl = shlvl;
4916         shlvl++;
4917
4918         /* man bash: "Non-builtin commands run by bash have signal handlers
4919          * set to the values inherited by the shell from its parent".
4920          * Do we do it correctly? */
4921
4922         closescript();
4923
4924         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4925          && n && n->type == NCMD        /* is it single cmd? */
4926         /* && n->ncmd.args->type == NARG - always true? */
4927          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4928          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4929         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4930         ) {
4931                 TRACE(("Trap hack\n"));
4932                 /* Awful hack for `trap` or $(trap).
4933                  *
4934                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4935                  * contains an example where "trap" is executed in a subshell:
4936                  *
4937                  * save_traps=$(trap)
4938                  * ...
4939                  * eval "$save_traps"
4940                  *
4941                  * Standard does not say that "trap" in subshell shall print
4942                  * parent shell's traps. It only says that its output
4943                  * must have suitable form, but then, in the above example
4944                  * (which is not supposed to be normative), it implies that.
4945                  *
4946                  * bash (and probably other shell) does implement it
4947                  * (traps are reset to defaults, but "trap" still shows them),
4948                  * but as a result, "trap" logic is hopelessly messed up:
4949                  *
4950                  * # trap
4951                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4952                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4953                  * # true | trap   <--- trap is in subshell - no output (ditto)
4954                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4955                  * trap -- 'echo Ho' SIGWINCH
4956                  * # echo `(trap)`         <--- in subshell in subshell - output
4957                  * trap -- 'echo Ho' SIGWINCH
4958                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4959                  * trap -- 'echo Ho' SIGWINCH
4960                  *
4961                  * The rules when to forget and when to not forget traps
4962                  * get really complex and nonsensical.
4963                  *
4964                  * Our solution: ONLY bare $(trap) or `trap` is special.
4965                  */
4966                 /* Save trap handler strings for trap builtin to print */
4967                 trap_ptr = xmemdup(trap, sizeof(trap));
4968                 /* Fall through into clearing traps */
4969         }
4970         clear_traps();
4971 #if JOBS
4972         /* do job control only in root shell */
4973         doing_jobctl = 0;
4974         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4975                 pid_t pgrp;
4976
4977                 if (jp->nprocs == 0)
4978                         pgrp = getpid();
4979                 else
4980                         pgrp = jp->ps[0].ps_pid;
4981                 /* this can fail because we are doing it in the parent also */
4982                 setpgid(0, pgrp);
4983                 if (mode == FORK_FG)
4984                         xtcsetpgrp(ttyfd, pgrp);
4985                 setsignal(SIGTSTP);
4986                 setsignal(SIGTTOU);
4987         } else
4988 #endif
4989         if (mode == FORK_BG) {
4990                 /* man bash: "When job control is not in effect,
4991                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4992                 ignoresig(SIGINT);
4993                 ignoresig(SIGQUIT);
4994                 if (jp->nprocs == 0) {
4995                         close(0);
4996                         if (open(bb_dev_null, O_RDONLY) != 0)
4997                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4998                 }
4999         }
5000         if (oldlvl == 0) {
5001                 if (iflag) { /* why if iflag only? */
5002                         setsignal(SIGINT);
5003                         setsignal(SIGTERM);
5004                 }
5005                 /* man bash:
5006                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5007                  * commands run by bash have signal handlers
5008                  * set to the values inherited by the shell
5009                  * from its parent".
5010                  * Take care of the second rule: */
5011                 setsignal(SIGQUIT);
5012         }
5013 #if JOBS
5014         if (n && n->type == NCMD
5015          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5016         ) {
5017                 TRACE(("Job hack\n"));
5018                 /* "jobs": we do not want to clear job list for it,
5019                  * instead we remove only _its_ own_ job from job list.
5020                  * This makes "jobs .... | cat" more useful.
5021                  */
5022                 freejob(curjob);
5023                 return;
5024         }
5025 #endif
5026         for (jp = curjob; jp; jp = jp->prev_job)
5027                 freejob(jp);
5028         jobless = 0;
5029 }
5030
5031 /* Called after fork(), in parent */
5032 #if !JOBS
5033 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5034 #endif
5035 static void
5036 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5037 {
5038         TRACE(("In parent shell: child = %d\n", pid));
5039         if (!jp) {
5040                 /* jp is NULL when called by openhere() for heredoc support */
5041                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5042                         continue;
5043                 jobless++;
5044                 return;
5045         }
5046 #if JOBS
5047         if (mode != FORK_NOJOB && jp->jobctl) {
5048                 int pgrp;
5049
5050                 if (jp->nprocs == 0)
5051                         pgrp = pid;
5052                 else
5053                         pgrp = jp->ps[0].ps_pid;
5054                 /* This can fail because we are doing it in the child also */
5055                 setpgid(pid, pgrp);
5056         }
5057 #endif
5058         if (mode == FORK_BG) {
5059                 backgndpid = pid;               /* set $! */
5060                 set_curjob(jp, CUR_RUNNING);
5061         }
5062         if (jp) {
5063                 struct procstat *ps = &jp->ps[jp->nprocs++];
5064                 ps->ps_pid = pid;
5065                 ps->ps_status = -1;
5066                 ps->ps_cmd = nullstr;
5067 #if JOBS
5068                 if (doing_jobctl && n)
5069                         ps->ps_cmd = commandtext(n);
5070 #endif
5071         }
5072 }
5073
5074 /* jp and n are NULL when called by openhere() for heredoc support */
5075 static int
5076 forkshell(struct job *jp, union node *n, int mode)
5077 {
5078         int pid;
5079
5080         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5081         pid = fork();
5082         if (pid < 0) {
5083                 TRACE(("Fork failed, errno=%d", errno));
5084                 if (jp)
5085                         freejob(jp);
5086                 ash_msg_and_raise_error("can't fork");
5087         }
5088         if (pid == 0) {
5089                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5090                 forkchild(jp, n, mode);
5091         } else {
5092                 forkparent(jp, n, mode, pid);
5093         }
5094         return pid;
5095 }
5096
5097 /*
5098  * Wait for job to finish.
5099  *
5100  * Under job control we have the problem that while a child process
5101  * is running interrupts generated by the user are sent to the child
5102  * but not to the shell.  This means that an infinite loop started by
5103  * an interactive user may be hard to kill.  With job control turned off,
5104  * an interactive user may place an interactive program inside a loop.
5105  * If the interactive program catches interrupts, the user doesn't want
5106  * these interrupts to also abort the loop.  The approach we take here
5107  * is to have the shell ignore interrupt signals while waiting for a
5108  * foreground process to terminate, and then send itself an interrupt
5109  * signal if the child process was terminated by an interrupt signal.
5110  * Unfortunately, some programs want to do a bit of cleanup and then
5111  * exit on interrupt; unless these processes terminate themselves by
5112  * sending a signal to themselves (instead of calling exit) they will
5113  * confuse this approach.
5114  *
5115  * Called with interrupts off.
5116  */
5117 static int
5118 waitforjob(struct job *jp)
5119 {
5120         int st;
5121
5122         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5123
5124         INT_OFF;
5125         while (jp->state == JOBRUNNING) {
5126                 /* In non-interactive shells, we _can_ get
5127                  * a keyboard signal here and be EINTRed,
5128                  * but we just loop back, waiting for command to complete.
5129                  *
5130                  * man bash:
5131                  * "If bash is waiting for a command to complete and receives
5132                  * a signal for which a trap has been set, the trap
5133                  * will not be executed until the command completes."
5134                  *
5135                  * Reality is that even if trap is not set, bash
5136                  * will not act on the signal until command completes.
5137                  * Try this. sleep5intoff.c:
5138                  * #include <signal.h>
5139                  * #include <unistd.h>
5140                  * int main() {
5141                  *         sigset_t set;
5142                  *         sigemptyset(&set);
5143                  *         sigaddset(&set, SIGINT);
5144                  *         sigaddset(&set, SIGQUIT);
5145                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5146                  *         sleep(5);
5147                  *         return 0;
5148                  * }
5149                  * $ bash -c './sleep5intoff; echo hi'
5150                  * ^C^C^C^C <--- pressing ^C once a second
5151                  * $ _
5152                  * $ bash -c './sleep5intoff; echo hi'
5153                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5154                  * $ _
5155                  */
5156                 dowait(DOWAIT_BLOCK, jp);
5157         }
5158         INT_ON;
5159
5160         st = getstatus(jp);
5161 #if JOBS
5162         if (jp->jobctl) {
5163                 xtcsetpgrp(ttyfd, rootpid);
5164                 restore_tty_if_stopped_or_signaled(jp);
5165
5166                 /*
5167                  * This is truly gross.
5168                  * If we're doing job control, then we did a TIOCSPGRP which
5169                  * caused us (the shell) to no longer be in the controlling
5170                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5171                  * intuit from the subprocess exit status whether a SIGINT
5172                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5173                  */
5174                 if (jp->sigint) /* TODO: do the same with all signals */
5175                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5176         }
5177         if (jp->state == JOBDONE)
5178 #endif
5179                 freejob(jp);
5180         return st;
5181 }
5182
5183 /*
5184  * return 1 if there are stopped jobs, otherwise 0
5185  */
5186 static int
5187 stoppedjobs(void)
5188 {
5189         struct job *jp;
5190         int retval;
5191
5192         retval = 0;
5193         if (job_warning)
5194                 goto out;
5195         jp = curjob;
5196         if (jp && jp->state == JOBSTOPPED) {
5197                 out2str("You have stopped jobs.\n");
5198                 job_warning = 2;
5199                 retval++;
5200         }
5201  out:
5202         return retval;
5203 }
5204
5205
5206 /*
5207  * Code for dealing with input/output redirection.
5208  */
5209
5210 #undef EMPTY
5211 #undef CLOSED
5212 #define EMPTY -2                /* marks an unused slot in redirtab */
5213 #define CLOSED -1               /* marks a slot of previously-closed fd */
5214
5215 /*
5216  * Handle here documents.  Normally we fork off a process to write the
5217  * data to a pipe.  If the document is short, we can stuff the data in
5218  * the pipe without forking.
5219  */
5220 /* openhere needs this forward reference */
5221 static void expandhere(union node *arg, int fd);
5222 static int
5223 openhere(union node *redir)
5224 {
5225         int pip[2];
5226         size_t len = 0;
5227
5228         if (pipe(pip) < 0)
5229                 ash_msg_and_raise_error("pipe call failed");
5230         if (redir->type == NHERE) {
5231                 len = strlen(redir->nhere.doc->narg.text);
5232                 if (len <= PIPE_BUF) {
5233                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5234                         goto out;
5235                 }
5236         }
5237         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5238                 /* child */
5239                 close(pip[0]);
5240                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5241                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5242                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5243                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5244                 signal(SIGPIPE, SIG_DFL);
5245                 if (redir->type == NHERE)
5246                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5247                 else /* NXHERE */
5248                         expandhere(redir->nhere.doc, pip[1]);
5249                 _exit(EXIT_SUCCESS);
5250         }
5251  out:
5252         close(pip[1]);
5253         return pip[0];
5254 }
5255
5256 static int
5257 openredirect(union node *redir)
5258 {
5259         struct stat sb;
5260         char *fname;
5261         int f;
5262
5263         switch (redir->nfile.type) {
5264 /* Can't happen, our single caller does this itself */
5265 //      case NTOFD:
5266 //      case NFROMFD:
5267 //              return -1;
5268         case NHERE:
5269         case NXHERE:
5270                 return openhere(redir);
5271         }
5272
5273         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5274          * allocated space. Do it only when we know it is safe.
5275          */
5276         fname = redir->nfile.expfname;
5277
5278         switch (redir->nfile.type) {
5279         default:
5280 #if DEBUG
5281                 abort();
5282 #endif
5283         case NFROM:
5284                 f = open(fname, O_RDONLY);
5285                 if (f < 0)
5286                         goto eopen;
5287                 break;
5288         case NFROMTO:
5289                 f = open(fname, O_RDWR|O_CREAT, 0666);
5290                 if (f < 0)
5291                         goto ecreate;
5292                 break;
5293         case NTO:
5294 #if BASH_REDIR_OUTPUT
5295         case NTO2:
5296 #endif
5297                 /* Take care of noclobber mode. */
5298                 if (Cflag) {
5299                         if (stat(fname, &sb) < 0) {
5300                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5301                                 if (f < 0)
5302                                         goto ecreate;
5303                         } else if (!S_ISREG(sb.st_mode)) {
5304                                 f = open(fname, O_WRONLY, 0666);
5305                                 if (f < 0)
5306                                         goto ecreate;
5307                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5308                                         close(f);
5309                                         errno = EEXIST;
5310                                         goto ecreate;
5311                                 }
5312                         } else {
5313                                 errno = EEXIST;
5314                                 goto ecreate;
5315                         }
5316                         break;
5317                 }
5318                 /* FALLTHROUGH */
5319         case NCLOBBER:
5320                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5321                 if (f < 0)
5322                         goto ecreate;
5323                 break;
5324         case NAPPEND:
5325                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5326                 if (f < 0)
5327                         goto ecreate;
5328                 break;
5329         }
5330
5331         return f;
5332  ecreate:
5333         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5334  eopen:
5335         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5336 }
5337
5338 /*
5339  * Copy a file descriptor to be >= 10. Throws exception on error.
5340  */
5341 static int
5342 savefd(int from)
5343 {
5344         int newfd;
5345         int err;
5346
5347         newfd = fcntl(from, F_DUPFD, 10);
5348         err = newfd < 0 ? errno : 0;
5349         if (err != EBADF) {
5350                 if (err)
5351                         ash_msg_and_raise_perror("%d", from);
5352                 close(from);
5353                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5354         }
5355
5356         return newfd;
5357 }
5358 static int
5359 dup2_or_raise(int from, int to)
5360 {
5361         int newfd;
5362
5363         newfd = (from != to) ? dup2(from, to) : to;
5364         if (newfd < 0) {
5365                 /* Happens when source fd is not open: try "echo >&99" */
5366                 ash_msg_and_raise_perror("%d", from);
5367         }
5368         return newfd;
5369 }
5370 static int
5371 fcntl_F_DUPFD(int fd, int avoid_fd)
5372 {
5373         int newfd;
5374  repeat:
5375         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5376         if (newfd < 0) {
5377                 if (errno == EBUSY)
5378                         goto repeat;
5379                 if (errno == EINTR)
5380                         goto repeat;
5381         }
5382         return newfd;
5383 }
5384 static int
5385 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5386 {
5387         int newfd;
5388  repeat:
5389         newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
5390         if (newfd < 0) {
5391                 if (errno == EBUSY)
5392                         goto repeat;
5393                 if (errno == EINTR)
5394                         goto repeat;
5395                 /* fd was not open? */
5396                 if (errno == EBADF)
5397                         return fd;
5398                 ash_msg_and_raise_perror("%d", newfd);
5399         }
5400         fcntl(newfd, F_SETFD, FD_CLOEXEC);
5401         close(fd);
5402         return newfd;
5403 }
5404
5405 /* Struct def and variable are moved down to the first usage site */
5406 struct squirrel {
5407         int orig_fd;
5408         int moved_to;
5409 };
5410 struct redirtab {
5411         struct redirtab *next;
5412         int pair_count;
5413         struct squirrel two_fd[];
5414 };
5415 #define redirlist (G_var.redirlist)
5416
5417 static void
5418 add_squirrel_closed(struct redirtab *sq, int fd)
5419 {
5420         int i;
5421
5422         if (!sq)
5423                 return;
5424
5425         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5426                 /* If we collide with an already moved fd... */
5427                 if (fd == sq->two_fd[i].orig_fd) {
5428                         /* Examples:
5429                          * "echo 3>FILE 3>&- 3>FILE"
5430                          * "echo 3>&- 3>FILE"
5431                          * No need for last redirect to insert
5432                          * another "need to close 3" indicator.
5433                          */
5434                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5435                         return;
5436                 }
5437         }
5438         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5439         sq->two_fd[i].orig_fd = fd;
5440         sq->two_fd[i].moved_to = CLOSED;
5441 }
5442
5443 static int
5444 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5445 {
5446         int i, new_fd;
5447
5448         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5449                 avoid_fd = 9;
5450
5451 #if JOBS
5452         if (fd == ttyfd) {
5453                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5454                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5455                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5456                 return 1; /* "we closed fd" */
5457         }
5458 #endif
5459         /* Are we called from redirect(0)? E.g. redirect
5460          * in a forked child. No need to save fds,
5461          * we aren't going to use them anymore, ok to trash.
5462          */
5463         if (!sq)
5464                 return 0;
5465
5466         /* If this one of script's fds? */
5467         if (fd != 0) {
5468                 struct parsefile *pf = g_parsefile;
5469                 while (pf) {
5470                         /* We skip fd == 0 case because of the following:
5471                          * $ ash  # running ash interactively
5472                          * $ . ./script.sh
5473                          * and in script.sh: "exec 9>&0".
5474                          * Even though top-level pf_fd _is_ 0,
5475                          * it's still ok to use it: "read" builtin uses it,
5476                          * why should we cripple "exec" builtin?
5477                          */
5478                         if (fd == pf->pf_fd) {
5479                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5480                                 return 1; /* "we closed fd" */
5481                         }
5482                         pf = pf->prev;
5483                 }
5484         }
5485
5486         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5487
5488         /* First: do we collide with some already moved fds? */
5489         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5490                 /* If we collide with an already moved fd... */
5491                 if (fd == sq->two_fd[i].moved_to) {
5492                         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5493                         sq->two_fd[i].moved_to = new_fd;
5494                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5495                         if (new_fd < 0) /* what? */
5496                                 xfunc_die();
5497                         return 0; /* "we did not close fd" */
5498                 }
5499                 if (fd == sq->two_fd[i].orig_fd) {
5500                         /* Example: echo Hello >/dev/null 1>&2 */
5501                         TRACE(("redirect_fd %d: already moved\n", fd));
5502                         return 0; /* "we did not close fd" */
5503                 }
5504         }
5505
5506         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5507         new_fd = fcntl_F_DUPFD(fd, avoid_fd);
5508         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5509         if (new_fd < 0) {
5510                 if (errno != EBADF)
5511                         xfunc_die();
5512                 /* new_fd = CLOSED; - already is -1 */
5513         }
5514         sq->two_fd[i].moved_to = new_fd;
5515         sq->two_fd[i].orig_fd = fd;
5516
5517         /* if we move stderr, let "set -x" code know */
5518         if (fd == preverrout_fd)
5519                 preverrout_fd = new_fd;
5520
5521         return 0; /* "we did not close fd" */
5522 }
5523
5524 static int
5525 internally_opened_fd(int fd, struct redirtab *sq)
5526 {
5527         int i;
5528 #if JOBS
5529         if (fd == ttyfd)
5530                 return 1;
5531 #endif
5532         /* If this one of script's fds? */
5533         if (fd != 0) {
5534                 struct parsefile *pf = g_parsefile;
5535                 while (pf) {
5536                         if (fd == pf->pf_fd)
5537                                 return 1;
5538                         pf = pf->prev;
5539                 }
5540         }
5541
5542         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5543                 if (fd == sq->two_fd[i].moved_to)
5544                         return 1;
5545         }
5546         return 0;
5547 }
5548
5549 /*
5550  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5551  * old file descriptors are stashed away so that the redirection can be
5552  * undone by calling popredir.
5553  */
5554 /* flags passed to redirect */
5555 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5556 static void
5557 redirect(union node *redir, int flags)
5558 {
5559         struct redirtab *sv;
5560
5561         if (!redir)
5562                 return;
5563
5564         sv = NULL;
5565         INT_OFF;
5566         if (flags & REDIR_PUSH)
5567                 sv = redirlist;
5568         do {
5569                 int fd;
5570                 int newfd;
5571                 int close_fd;
5572                 int closed;
5573
5574                 fd = redir->nfile.fd;
5575                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5576                         //bb_error_msg("doing %d > %d", fd, newfd);
5577                         newfd = redir->ndup.dupfd;
5578                         close_fd = -1;
5579                 } else {
5580                         newfd = openredirect(redir); /* always >= 0 */
5581                         if (fd == newfd) {
5582                                 /* open() gave us precisely the fd we wanted.
5583                                  * This means that this fd was not busy
5584                                  * (not opened to anywhere).
5585                                  * Remember to close it on restore:
5586                                  */
5587                                 add_squirrel_closed(sv, fd);
5588                                 continue;
5589                         }
5590                         close_fd = newfd;
5591                 }
5592
5593                 if (fd == newfd)
5594                         continue;
5595
5596                 /* if "N>FILE": move newfd to fd */
5597                 /* if "N>&M": dup newfd to fd */
5598                 /* if "N>&-": close fd (newfd is -1) */
5599
5600  IF_BASH_REDIR_OUTPUT(redirect_more:)
5601
5602                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5603                 if (newfd == -1) {
5604                         /* "N>&-" means "close me" */
5605                         if (!closed) {
5606                                 /* ^^^ optimization: saving may already
5607                                  * have closed it. If not... */
5608                                 close(fd);
5609                         }
5610                 } else {
5611                         /* if newfd is a script fd or saved fd, simulate EBADF */
5612                         if (internally_opened_fd(newfd, sv)) {
5613                                 errno = EBADF;
5614                                 ash_msg_and_raise_perror("%d", newfd);
5615                         }
5616                         dup2_or_raise(newfd, fd);
5617                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5618                                 close(close_fd);
5619 #if BASH_REDIR_OUTPUT
5620                         if (redir->nfile.type == NTO2 && fd == 1) {
5621                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5622                                 fd = 2;
5623                                 newfd = 1;
5624                                 close_fd = -1;
5625                                 goto redirect_more;
5626                         }
5627 #endif
5628                 }
5629         } while ((redir = redir->nfile.next) != NULL);
5630         INT_ON;
5631
5632 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5633 #define REDIR_SAVEFD2 0
5634         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5635         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5636         // not only for calls with flags containing REDIR_SAVEFD2.
5637         // We do this unconditionally (see save_fd_on_redirect()).
5638         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5639         //      preverrout_fd = copied_fd2;
5640 }
5641
5642 static int
5643 redirectsafe(union node *redir, int flags)
5644 {
5645         int err;
5646         volatile int saveint;
5647         struct jmploc *volatile savehandler = exception_handler;
5648         struct jmploc jmploc;
5649
5650         SAVE_INT(saveint);
5651         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5652         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5653         if (!err) {
5654                 exception_handler = &jmploc;
5655                 redirect(redir, flags);
5656         }
5657         exception_handler = savehandler;
5658         if (err && exception_type != EXERROR)
5659                 longjmp(exception_handler->loc, 1);
5660         RESTORE_INT(saveint);
5661         return err;
5662 }
5663
5664 static struct redirtab*
5665 pushredir(union node *redir)
5666 {
5667         struct redirtab *sv;
5668         int i;
5669
5670         if (!redir)
5671                 return redirlist;
5672
5673         i = 0;
5674         do {
5675                 i++;
5676 #if BASH_REDIR_OUTPUT
5677                 if (redir->nfile.type == NTO2)
5678                         i++;
5679 #endif
5680                 redir = redir->nfile.next;
5681         } while (redir);
5682
5683         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5684         sv->pair_count = i;
5685         while (--i >= 0)
5686                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5687         sv->next = redirlist;
5688         redirlist = sv;
5689         return sv->next;
5690 }
5691
5692 /*
5693  * Undo the effects of the last redirection.
5694  */
5695 static void
5696 popredir(int drop)
5697 {
5698         struct redirtab *rp;
5699         int i;
5700
5701         if (redirlist == NULL)
5702                 return;
5703         INT_OFF;
5704         rp = redirlist;
5705         for (i = 0; i < rp->pair_count; i++) {
5706                 int fd = rp->two_fd[i].orig_fd;
5707                 int copy = rp->two_fd[i].moved_to;
5708                 if (copy == CLOSED) {
5709                         if (!drop)
5710                                 close(fd);
5711                         continue;
5712                 }
5713                 if (copy != EMPTY) {
5714                         if (!drop) {
5715                                 /*close(fd);*/
5716                                 dup2_or_raise(copy, fd);
5717                         }
5718                         close(copy);
5719                 }
5720         }
5721         redirlist = rp->next;
5722         free(rp);
5723         INT_ON;
5724 }
5725
5726 static void
5727 unwindredir(struct redirtab *stop)
5728 {
5729         while (redirlist != stop)
5730                 popredir(/*drop:*/ 0);
5731 }
5732
5733
5734 /* ============ Routines to expand arguments to commands
5735  *
5736  * We have to deal with backquotes, shell variables, and file metacharacters.
5737  */
5738
5739 #if ENABLE_FEATURE_SH_MATH
5740 static arith_t
5741 ash_arith(const char *s)
5742 {
5743         arith_state_t math_state;
5744         arith_t result;
5745
5746         math_state.lookupvar = lookupvar;
5747         math_state.setvar    = setvar0;
5748         //math_state.endofname = endofname;
5749
5750         INT_OFF;
5751         result = arith(&math_state, s);
5752         if (math_state.errmsg)
5753                 ash_msg_and_raise_error(math_state.errmsg);
5754         INT_ON;
5755
5756         return result;
5757 }
5758 #endif
5759
5760 /*
5761  * expandarg flags
5762  */
5763 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5764 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5765 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5766 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5767 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5768  * POSIX says for this case:
5769  *  Pathname expansion shall not be performed on the word by a
5770  *  non-interactive shell; an interactive shell may perform it, but shall
5771  *  do so only when the expansion would result in one word.
5772  * Currently, our code complies to the above rule by never globbing
5773  * redirection filenames.
5774  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5775  * (this means that on a typical Linux distro, bash almost always
5776  * performs globbing, and thus diverges from what we do).
5777  */
5778 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5779 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5780 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5781 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5782 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5783 /*
5784  * rmescape() flags
5785  */
5786 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5787 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5788 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5789 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5790 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5791
5792 /* Add CTLESC when necessary. */
5793 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5794 /* Do not skip NUL characters. */
5795 #define QUOTES_KEEPNUL EXP_TILDE
5796
5797 /*
5798  * Structure specifying which parts of the string should be searched
5799  * for IFS characters.
5800  */
5801 struct ifsregion {
5802         struct ifsregion *next; /* next region in list */
5803         int begoff;             /* offset of start of region */
5804         int endoff;             /* offset of end of region */
5805         int nulonly;            /* search for nul bytes only */
5806 };
5807
5808 struct arglist {
5809         struct strlist *list;
5810         struct strlist **lastp;
5811 };
5812
5813 /* output of current string */
5814 static char *expdest;
5815 /* list of back quote expressions */
5816 static struct nodelist *argbackq;
5817 /* first struct in list of ifs regions */
5818 static struct ifsregion ifsfirst;
5819 /* last struct in list */
5820 static struct ifsregion *ifslastp;
5821 /* holds expanded arg list */
5822 static struct arglist exparg;
5823
5824 /*
5825  * Our own itoa().
5826  * cvtnum() is used even if math support is off (to prepare $? values and such).
5827  */
5828 static int
5829 cvtnum(arith_t num)
5830 {
5831         int len;
5832
5833         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5834         len = sizeof(arith_t) * 3;
5835         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5836         if (sizeof(arith_t) < 4) len += 2;
5837
5838         expdest = makestrspace(len, expdest);
5839         len = fmtstr(expdest, len, ARITH_FMT, num);
5840         STADJUST(len, expdest);
5841         return len;
5842 }
5843
5844 /*
5845  * Break the argument string into pieces based upon IFS and add the
5846  * strings to the argument list.  The regions of the string to be
5847  * searched for IFS characters have been stored by recordregion.
5848  */
5849 static void
5850 ifsbreakup(char *string, struct arglist *arglist)
5851 {
5852         struct ifsregion *ifsp;
5853         struct strlist *sp;
5854         char *start;
5855         char *p;
5856         char *q;
5857         const char *ifs, *realifs;
5858         int ifsspc;
5859         int nulonly;
5860
5861         start = string;
5862         if (ifslastp != NULL) {
5863                 ifsspc = 0;
5864                 nulonly = 0;
5865                 realifs = ifsset() ? ifsval() : defifs;
5866                 ifsp = &ifsfirst;
5867                 do {
5868                         p = string + ifsp->begoff;
5869                         nulonly = ifsp->nulonly;
5870                         ifs = nulonly ? nullstr : realifs;
5871                         ifsspc = 0;
5872                         while (p < string + ifsp->endoff) {
5873                                 q = p;
5874                                 if ((unsigned char)*p == CTLESC)
5875                                         p++;
5876                                 if (!strchr(ifs, *p)) {
5877                                         p++;
5878                                         continue;
5879                                 }
5880                                 if (!nulonly)
5881                                         ifsspc = (strchr(defifs, *p) != NULL);
5882                                 /* Ignore IFS whitespace at start */
5883                                 if (q == start && ifsspc) {
5884                                         p++;
5885                                         start = p;
5886                                         continue;
5887                                 }
5888                                 *q = '\0';
5889                                 sp = stzalloc(sizeof(*sp));
5890                                 sp->text = start;
5891                                 *arglist->lastp = sp;
5892                                 arglist->lastp = &sp->next;
5893                                 p++;
5894                                 if (!nulonly) {
5895                                         for (;;) {
5896                                                 if (p >= string + ifsp->endoff) {
5897                                                         break;
5898                                                 }
5899                                                 q = p;
5900                                                 if ((unsigned char)*p == CTLESC)
5901                                                         p++;
5902                                                 if (strchr(ifs, *p) == NULL) {
5903                                                         p = q;
5904                                                         break;
5905                                                 }
5906                                                 if (strchr(defifs, *p) == NULL) {
5907                                                         if (ifsspc) {
5908                                                                 p++;
5909                                                                 ifsspc = 0;
5910                                                         } else {
5911                                                                 p = q;
5912                                                                 break;
5913                                                         }
5914                                                 } else
5915                                                         p++;
5916                                         }
5917                                 }
5918                                 start = p;
5919                         } /* while */
5920                         ifsp = ifsp->next;
5921                 } while (ifsp != NULL);
5922                 if (nulonly)
5923                         goto add;
5924         }
5925
5926         if (!*start)
5927                 return;
5928
5929  add:
5930         sp = stzalloc(sizeof(*sp));
5931         sp->text = start;
5932         *arglist->lastp = sp;
5933         arglist->lastp = &sp->next;
5934 }
5935
5936 static void
5937 ifsfree(void)
5938 {
5939         struct ifsregion *p = ifsfirst.next;
5940
5941         if (!p)
5942                 goto out;
5943
5944         INT_OFF;
5945         do {
5946                 struct ifsregion *ifsp;
5947                 ifsp = p->next;
5948                 free(p);
5949                 p = ifsp;
5950         } while (p);
5951         ifsfirst.next = NULL;
5952         INT_ON;
5953  out:
5954         ifslastp = NULL;
5955 }
5956
5957 static size_t
5958 esclen(const char *start, const char *p)
5959 {
5960         size_t esc = 0;
5961
5962         while (p > start && (unsigned char)*--p == CTLESC) {
5963                 esc++;
5964         }
5965         return esc;
5966 }
5967
5968 /*
5969  * Remove any CTLESC characters from a string.
5970  */
5971 static char *
5972 rmescapes(char *str, int flag)
5973 {
5974         static const char qchars[] ALIGN1 = {
5975                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5976
5977         char *p, *q, *r;
5978         unsigned inquotes;
5979         unsigned protect_against_glob;
5980         unsigned globbing;
5981         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5982
5983         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5984         if (!p)
5985                 return str;
5986
5987         q = p;
5988         r = str;
5989         if (flag & RMESCAPE_ALLOC) {
5990                 size_t len = p - str;
5991                 size_t fulllen = len + strlen(p) + 1;
5992
5993                 if (flag & RMESCAPE_GROW) {
5994                         int strloc = str - (char *)stackblock();
5995                         r = makestrspace(fulllen, expdest);
5996                         /* p and str may be invalidated by makestrspace */
5997                         str = (char *)stackblock() + strloc;
5998                         p = str + len;
5999                 } else if (flag & RMESCAPE_HEAP) {
6000                         r = ckmalloc(fulllen);
6001                 } else {
6002                         r = stalloc(fulllen);
6003                 }
6004                 q = r;
6005                 if (len > 0) {
6006                         q = (char *)mempcpy(q, str, len);
6007                 }
6008         }
6009
6010         inquotes = 0;
6011         globbing = flag & RMESCAPE_GLOB;
6012         protect_against_glob = globbing;
6013         while (*p) {
6014                 if ((unsigned char)*p == CTLQUOTEMARK) {
6015 // Note: both inquotes and protect_against_glob only affect whether
6016 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6017                         inquotes = ~inquotes;
6018                         p++;
6019                         protect_against_glob = globbing;
6020                         continue;
6021                 }
6022                 if ((unsigned char)*p == CTLESC) {
6023                         p++;
6024 #if DEBUG
6025                         if (*p == '\0')
6026                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6027 #endif
6028                         if (protect_against_glob) {
6029                                 /*
6030                                  * We used to trust glob() and fnmatch() to eat
6031                                  * superfluous escapes (\z where z has no
6032                                  * special meaning anyway). But this causes
6033                                  * bugs such as string of one greek letter rho
6034                                  * (unicode-encoded as two bytes "cf,81")
6035                                  * getting encoded as "cf,CTLESC,81"
6036                                  * and here, converted to "cf,\,81" -
6037                                  * which does not go well with some flavors
6038                                  * of fnmatch() in unicode locales
6039                                  * (for example, glibc <= 2.22).
6040                                  *
6041                                  * Lets add "\" only on the chars which need it.
6042                                  * Testcases for less obvious chars are shown.
6043                                  */
6044                                 if (*p == '*'
6045                                  || *p == '?'
6046                                  || *p == '['
6047                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6048                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6049                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6050                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6051                                 /* Some libc support [^negate], that's why "^" also needs love */
6052                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6053                                 ) {
6054                                         *q++ = '\\';
6055                                 }
6056                         }
6057                 } else if (*p == '\\' && !inquotes) {
6058                         /* naked back slash */
6059                         protect_against_glob = 0;
6060                         goto copy;
6061                 }
6062 #if BASH_PATTERN_SUBST
6063                 else if (*p == '/' && slash) {
6064                         /* stop handling globbing and mark location of slash */
6065                         globbing = slash = 0;
6066                         *p = CTLESC;
6067                 }
6068 #endif
6069                 protect_against_glob = globbing;
6070  copy:
6071                 *q++ = *p++;
6072         }
6073         *q = '\0';
6074         if (flag & RMESCAPE_GROW) {
6075                 expdest = r;
6076                 STADJUST(q - r + 1, expdest);
6077         }
6078         return r;
6079 }
6080 #define pmatch(a, b) !fnmatch((a), (b), 0)
6081
6082 /*
6083  * Prepare a pattern for a expmeta (internal glob(3)) call.
6084  *
6085  * Returns an stalloced string.
6086  */
6087 static char *
6088 preglob(const char *pattern, int flag)
6089 {
6090         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6091 }
6092
6093 /*
6094  * Put a string on the stack.
6095  */
6096 static void
6097 memtodest(const char *p, size_t len, int syntax, int quotes)
6098 {
6099         char *q;
6100
6101         if (!len)
6102                 return;
6103
6104         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6105
6106         do {
6107                 unsigned char c = *p++;
6108                 if (c) {
6109                         if (quotes & QUOTES_ESC) {
6110                                 int n = SIT(c, syntax);
6111                                 if (n == CCTL
6112                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6113                                      && n == CBACK
6114                                     )
6115                                 ) {
6116                                         USTPUTC(CTLESC, q);
6117                                 }
6118                         }
6119                 } else if (!(quotes & QUOTES_KEEPNUL))
6120                         continue;
6121                 USTPUTC(c, q);
6122         } while (--len);
6123
6124         expdest = q;
6125 }
6126
6127 static size_t
6128 strtodest(const char *p, int syntax, int quotes)
6129 {
6130         size_t len = strlen(p);
6131         memtodest(p, len, syntax, quotes);
6132         return len;
6133 }
6134
6135 /*
6136  * Record the fact that we have to scan this region of the
6137  * string for IFS characters.
6138  */
6139 static void
6140 recordregion(int start, int end, int nulonly)
6141 {
6142         struct ifsregion *ifsp;
6143
6144         if (ifslastp == NULL) {
6145                 ifsp = &ifsfirst;
6146         } else {
6147                 INT_OFF;
6148                 ifsp = ckzalloc(sizeof(*ifsp));
6149                 /*ifsp->next = NULL; - ckzalloc did it */
6150                 ifslastp->next = ifsp;
6151                 INT_ON;
6152         }
6153         ifslastp = ifsp;
6154         ifslastp->begoff = start;
6155         ifslastp->endoff = end;
6156         ifslastp->nulonly = nulonly;
6157 }
6158
6159 static void
6160 removerecordregions(int endoff)
6161 {
6162         if (ifslastp == NULL)
6163                 return;
6164
6165         if (ifsfirst.endoff > endoff) {
6166                 while (ifsfirst.next) {
6167                         struct ifsregion *ifsp;
6168                         INT_OFF;
6169                         ifsp = ifsfirst.next->next;
6170                         free(ifsfirst.next);
6171                         ifsfirst.next = ifsp;
6172                         INT_ON;
6173                 }
6174                 if (ifsfirst.begoff > endoff) {
6175                         ifslastp = NULL;
6176                 } else {
6177                         ifslastp = &ifsfirst;
6178                         ifsfirst.endoff = endoff;
6179                 }
6180                 return;
6181         }
6182
6183         ifslastp = &ifsfirst;
6184         while (ifslastp->next && ifslastp->next->begoff < endoff)
6185                 ifslastp = ifslastp->next;
6186         while (ifslastp->next) {
6187                 struct ifsregion *ifsp;
6188                 INT_OFF;
6189                 ifsp = ifslastp->next->next;
6190                 free(ifslastp->next);
6191                 ifslastp->next = ifsp;
6192                 INT_ON;
6193         }
6194         if (ifslastp->endoff > endoff)
6195                 ifslastp->endoff = endoff;
6196 }
6197
6198 static char *
6199 exptilde(char *startp, char *p, int flags)
6200 {
6201         unsigned char c;
6202         char *name;
6203         struct passwd *pw;
6204         const char *home;
6205         int quotes = flags & QUOTES_ESC;
6206
6207         name = p + 1;
6208
6209         while ((c = *++p) != '\0') {
6210                 switch (c) {
6211                 case CTLESC:
6212                         return startp;
6213                 case CTLQUOTEMARK:
6214                         return startp;
6215                 case ':':
6216                         if (flags & EXP_VARTILDE)
6217                                 goto done;
6218                         break;
6219                 case '/':
6220                 case CTLENDVAR:
6221                         goto done;
6222                 }
6223         }
6224  done:
6225         *p = '\0';
6226         if (*name == '\0') {
6227                 home = lookupvar("HOME");
6228         } else {
6229                 pw = getpwnam(name);
6230                 if (pw == NULL)
6231                         goto lose;
6232                 home = pw->pw_dir;
6233         }
6234         if (!home || !*home)
6235                 goto lose;
6236         *p = c;
6237         strtodest(home, SQSYNTAX, quotes);
6238         return p;
6239  lose:
6240         *p = c;
6241         return startp;
6242 }
6243
6244 /*
6245  * Execute a command inside back quotes.  If it's a builtin command, we
6246  * want to save its output in a block obtained from malloc.  Otherwise
6247  * we fork off a subprocess and get the output of the command via a pipe.
6248  * Should be called with interrupts off.
6249  */
6250 struct backcmd {                /* result of evalbackcmd */
6251         int fd;                 /* file descriptor to read from */
6252         int nleft;              /* number of chars in buffer */
6253         char *buf;              /* buffer */
6254         struct job *jp;         /* job structure for command */
6255 };
6256
6257 /* These forward decls are needed to use "eval" code for backticks handling: */
6258 /* flags in argument to evaltree */
6259 #define EV_EXIT    01           /* exit after evaluating tree */
6260 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6261 static int evaltree(union node *, int);
6262
6263 /* An evaltree() which is known to never return.
6264  * Used to use an alias:
6265  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6266  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6267  */
6268 static ALWAYS_INLINE NORETURN void
6269 evaltreenr(union node *n, int flags)
6270 {
6271         evaltree(n, flags);
6272         bb_unreachable(abort());
6273         /* NOTREACHED */
6274 }
6275
6276 static void FAST_FUNC
6277 evalbackcmd(union node *n, struct backcmd *result)
6278 {
6279         int pip[2];
6280         struct job *jp;
6281
6282         result->fd = -1;
6283         result->buf = NULL;
6284         result->nleft = 0;
6285         result->jp = NULL;
6286         if (n == NULL) {
6287                 goto out;
6288         }
6289
6290         if (pipe(pip) < 0)
6291                 ash_msg_and_raise_error("pipe call failed");
6292         jp = makejob(/*n,*/ 1);
6293         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6294                 /* child */
6295                 FORCE_INT_ON;
6296                 close(pip[0]);
6297                 if (pip[1] != 1) {
6298                         /*close(1);*/
6299                         dup2_or_raise(pip[1], 1);
6300                         close(pip[1]);
6301                 }
6302 /* TODO: eflag clearing makes the following not abort:
6303  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6304  * which is what bash does (unless it is in POSIX mode).
6305  * dash deleted "eflag = 0" line in the commit
6306  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6307  *  [EVAL] Don't clear eflag in evalbackcmd
6308  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6309  */
6310                 eflag = 0;
6311                 ifsfree();
6312                 evaltreenr(n, EV_EXIT);
6313                 /* NOTREACHED */
6314         }
6315         /* parent */
6316         close(pip[1]);
6317         result->fd = pip[0];
6318         result->jp = jp;
6319
6320  out:
6321         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6322                 result->fd, result->buf, result->nleft, result->jp));
6323 }
6324
6325 /*
6326  * Expand stuff in backwards quotes.
6327  */
6328 static void
6329 expbackq(union node *cmd, int flag)
6330 {
6331         struct backcmd in;
6332         int i;
6333         char buf[128];
6334         char *p;
6335         char *dest;
6336         int startloc;
6337         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6338         struct stackmark smark;
6339
6340         INT_OFF;
6341         startloc = expdest - (char *)stackblock();
6342         pushstackmark(&smark, startloc);
6343         evalbackcmd(cmd, &in);
6344         popstackmark(&smark);
6345
6346         p = in.buf;
6347         i = in.nleft;
6348         if (i == 0)
6349                 goto read;
6350         for (;;) {
6351                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6352  read:
6353                 if (in.fd < 0)
6354                         break;
6355                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6356                 TRACE(("expbackq: read returns %d\n", i));
6357                 if (i <= 0)
6358                         break;
6359                 p = buf;
6360         }
6361
6362         free(in.buf);
6363         if (in.fd >= 0) {
6364                 close(in.fd);
6365                 back_exitstatus = waitforjob(in.jp);
6366         }
6367         INT_ON;
6368
6369         /* Eat all trailing newlines */
6370         dest = expdest;
6371         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6372                 STUNPUTC(dest);
6373         expdest = dest;
6374
6375         if (!(flag & EXP_QUOTED))
6376                 recordregion(startloc, dest - (char *)stackblock(), 0);
6377         TRACE(("evalbackq: size:%d:'%.*s'\n",
6378                 (int)((dest - (char *)stackblock()) - startloc),
6379                 (int)((dest - (char *)stackblock()) - startloc),
6380                 stackblock() + startloc));
6381 }
6382
6383 #if ENABLE_FEATURE_SH_MATH
6384 /*
6385  * Expand arithmetic expression.  Backup to start of expression,
6386  * evaluate, place result in (backed up) result, adjust string position.
6387  */
6388 static void
6389 expari(int flag)
6390 {
6391         char *p, *start;
6392         int begoff;
6393         int len;
6394
6395         /* ifsfree(); */
6396
6397         /*
6398          * This routine is slightly over-complicated for
6399          * efficiency.  Next we scan backwards looking for the
6400          * start of arithmetic.
6401          */
6402         start = stackblock();
6403         p = expdest - 1;
6404         *p = '\0';
6405         p--;
6406         while (1) {
6407                 int esc;
6408
6409                 while ((unsigned char)*p != CTLARI) {
6410                         p--;
6411 #if DEBUG
6412                         if (p < start) {
6413                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6414                         }
6415 #endif
6416                 }
6417
6418                 esc = esclen(start, p);
6419                 if (!(esc % 2)) {
6420                         break;
6421                 }
6422
6423                 p -= esc + 1;
6424         }
6425
6426         begoff = p - start;
6427
6428         removerecordregions(begoff);
6429
6430         expdest = p;
6431
6432         if (flag & QUOTES_ESC)
6433                 rmescapes(p + 1, 0);
6434
6435         len = cvtnum(ash_arith(p + 1));
6436
6437         if (!(flag & EXP_QUOTED))
6438                 recordregion(begoff, begoff + len, 0);
6439 }
6440 #endif
6441
6442 /* argstr needs it */
6443 static char *evalvar(char *p, int flags);
6444
6445 /*
6446  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6447  * characters to allow for further processing.  Otherwise treat
6448  * $@ like $* since no splitting will be performed.
6449  */
6450 static void
6451 argstr(char *p, int flags)
6452 {
6453         static const char spclchars[] ALIGN1 = {
6454                 '=',
6455                 ':',
6456                 CTLQUOTEMARK,
6457                 CTLENDVAR,
6458                 CTLESC,
6459                 CTLVAR,
6460                 CTLBACKQ,
6461 #if ENABLE_FEATURE_SH_MATH
6462                 CTLENDARI,
6463 #endif
6464                 '\0'
6465         };
6466         const char *reject = spclchars;
6467         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6468         int inquotes;
6469         size_t length;
6470         int startloc;
6471
6472         if (!(flags & EXP_VARTILDE)) {
6473                 reject += 2;
6474         } else if (flags & EXP_VARTILDE2) {
6475                 reject++;
6476         }
6477         inquotes = 0;
6478         length = 0;
6479         if (flags & EXP_TILDE) {
6480                 char *q;
6481
6482                 flags &= ~EXP_TILDE;
6483  tilde:
6484                 q = p;
6485                 if (*q == '~')
6486                         p = exptilde(p, q, flags);
6487         }
6488  start:
6489         startloc = expdest - (char *)stackblock();
6490         for (;;) {
6491                 unsigned char c;
6492
6493                 length += strcspn(p + length, reject);
6494                 c = p[length];
6495                 if (c) {
6496                         if (!(c & 0x80)
6497                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6498                         ) {
6499                                 /* c == '=' || c == ':' || c == CTLENDARI */
6500                                 length++;
6501                         }
6502                 }
6503                 if (length > 0) {
6504                         int newloc;
6505                         expdest = stack_nputstr(p, length, expdest);
6506                         newloc = expdest - (char *)stackblock();
6507                         if (breakall && !inquotes && newloc > startloc) {
6508                                 recordregion(startloc, newloc, 0);
6509                         }
6510                         startloc = newloc;
6511                 }
6512                 p += length + 1;
6513                 length = 0;
6514
6515                 switch (c) {
6516                 case '\0':
6517                         goto breakloop;
6518                 case '=':
6519                         if (flags & EXP_VARTILDE2) {
6520                                 p--;
6521                                 continue;
6522                         }
6523                         flags |= EXP_VARTILDE2;
6524                         reject++;
6525                         /* fall through */
6526                 case ':':
6527                         /*
6528                          * sort of a hack - expand tildes in variable
6529                          * assignments (after the first '=' and after ':'s).
6530                          */
6531                         if (*--p == '~') {
6532                                 goto tilde;
6533                         }
6534                         continue;
6535                 }
6536
6537                 switch (c) {
6538                 case CTLENDVAR: /* ??? */
6539                         goto breakloop;
6540                 case CTLQUOTEMARK:
6541                         inquotes ^= EXP_QUOTED;
6542                         /* "$@" syntax adherence hack */
6543                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6544                                 p = evalvar(p + 1, flags | inquotes) + 1;
6545                                 goto start;
6546                         }
6547  addquote:
6548                         if (flags & QUOTES_ESC) {
6549                                 p--;
6550                                 length++;
6551                                 startloc++;
6552                         }
6553                         break;
6554                 case CTLESC:
6555                         startloc++;
6556                         length++;
6557
6558                         /*
6559                          * Quoted parameter expansion pattern: remove quote
6560                          * unless inside inner quotes or we have a literal
6561                          * backslash.
6562                          */
6563                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6564                             EXP_QPAT && *p != '\\')
6565                                 break;
6566
6567                         goto addquote;
6568                 case CTLVAR:
6569                         TRACE(("argstr: evalvar('%s')\n", p));
6570                         p = evalvar(p, flags | inquotes);
6571                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6572                         goto start;
6573                 case CTLBACKQ:
6574                         expbackq(argbackq->n, flags | inquotes);
6575                         argbackq = argbackq->next;
6576                         goto start;
6577 #if ENABLE_FEATURE_SH_MATH
6578                 case CTLENDARI:
6579                         p--;
6580                         expari(flags | inquotes);
6581                         goto start;
6582 #endif
6583                 }
6584         }
6585  breakloop: ;
6586 }
6587
6588 static char *
6589 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6590                 char *pattern, int quotes, int zero)
6591 {
6592         char *loc, *loc2;
6593         char c;
6594
6595         loc = startp;
6596         loc2 = rmesc;
6597         do {
6598                 int match;
6599                 const char *s = loc2;
6600
6601                 c = *loc2;
6602                 if (zero) {
6603                         *loc2 = '\0';
6604                         s = rmesc;
6605                 }
6606                 match = pmatch(pattern, s);
6607
6608                 *loc2 = c;
6609                 if (match)
6610                         return loc;
6611                 if (quotes && (unsigned char)*loc == CTLESC)
6612                         loc++;
6613                 loc++;
6614                 loc2++;
6615         } while (c);
6616         return NULL;
6617 }
6618
6619 static char *
6620 scanright(char *startp, char *rmesc, char *rmescend,
6621                 char *pattern, int quotes, int match_at_start)
6622 {
6623 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6624         int try2optimize = match_at_start;
6625 #endif
6626         int esc = 0;
6627         char *loc;
6628         char *loc2;
6629
6630         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6631          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6632          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6633          * Logic:
6634          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6635          * and on each iteration they go back two/one char until they reach the beginning.
6636          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6637          */
6638         /* TODO: document in what other circumstances we are called. */
6639
6640         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6641                 int match;
6642                 char c = *loc2;
6643                 const char *s = loc2;
6644                 if (match_at_start) {
6645                         *loc2 = '\0';
6646                         s = rmesc;
6647                 }
6648                 match = pmatch(pattern, s);
6649                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6650                 *loc2 = c;
6651                 if (match)
6652                         return loc;
6653 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6654                 if (try2optimize) {
6655                         /* Maybe we can optimize this:
6656                          * if pattern ends with unescaped *, we can avoid checking
6657                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6658                          * it won't match truncated "raw_value_of_" strings too.
6659                          */
6660                         unsigned plen = strlen(pattern);
6661                         /* Does it end with "*"? */
6662                         if (plen != 0 && pattern[--plen] == '*') {
6663                                 /* "xxxx*" is not escaped */
6664                                 /* "xxx\*" is escaped */
6665                                 /* "xx\\*" is not escaped */
6666                                 /* "x\\\*" is escaped */
6667                                 int slashes = 0;
6668                                 while (plen != 0 && pattern[--plen] == '\\')
6669                                         slashes++;
6670                                 if (!(slashes & 1))
6671                                         break; /* ends with unescaped "*" */
6672                         }
6673                         try2optimize = 0;
6674                 }
6675 #endif
6676                 loc--;
6677                 if (quotes) {
6678                         if (--esc < 0) {
6679                                 esc = esclen(startp, loc);
6680                         }
6681                         if (esc % 2) {
6682                                 esc--;
6683                                 loc--;
6684                         }
6685                 }
6686         }
6687         return NULL;
6688 }
6689
6690 static void varunset(const char *, const char *, const char *, int) NORETURN;
6691 static void
6692 varunset(const char *end, const char *var, const char *umsg, int varflags)
6693 {
6694         const char *msg;
6695         const char *tail;
6696
6697         tail = nullstr;
6698         msg = "parameter not set";
6699         if (umsg) {
6700                 if ((unsigned char)*end == CTLENDVAR) {
6701                         if (varflags & VSNUL)
6702                                 tail = " or null";
6703                 } else {
6704                         msg = umsg;
6705                 }
6706         }
6707         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6708 }
6709
6710 static const char *
6711 subevalvar(char *p, char *varname, int strloc, int subtype,
6712                 int startloc, int varflags, int flag)
6713 {
6714         struct nodelist *saveargbackq = argbackq;
6715         int quotes = flag & QUOTES_ESC;
6716         char *startp;
6717         char *loc;
6718         char *rmesc, *rmescend;
6719         char *str;
6720         int amount, resetloc;
6721         IF_BASH_PATTERN_SUBST(int workloc;)
6722         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6723         int zero;
6724         char *(*scan)(char*, char*, char*, char*, int, int);
6725
6726         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6727         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6728
6729         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6730                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6731         );
6732         STPUTC('\0', expdest);
6733         argbackq = saveargbackq;
6734         startp = (char *)stackblock() + startloc;
6735
6736         switch (subtype) {
6737         case VSASSIGN:
6738                 setvar0(varname, startp);
6739                 amount = startp - expdest;
6740                 STADJUST(amount, expdest);
6741                 return startp;
6742
6743         case VSQUESTION:
6744                 varunset(p, varname, startp, varflags);
6745                 /* NOTREACHED */
6746
6747 #if BASH_SUBSTR
6748         case VSSUBSTR: {
6749                 int pos, len, orig_len;
6750                 char *colon;
6751
6752                 loc = str = stackblock() + strloc;
6753
6754 # if !ENABLE_FEATURE_SH_MATH
6755 #  define ash_arith number
6756 # endif
6757                 /* Read POS in ${var:POS:LEN} */
6758                 colon = strchr(loc, ':');
6759                 if (colon) *colon = '\0';
6760                 pos = ash_arith(loc);
6761                 if (colon) *colon = ':';
6762
6763                 /* Read LEN in ${var:POS:LEN} */
6764                 len = str - startp - 1;
6765                 /* *loc != '\0', guaranteed by parser */
6766                 if (quotes) {
6767                         char *ptr;
6768
6769                         /* Adjust the length by the number of escapes */
6770                         for (ptr = startp; ptr < (str - 1); ptr++) {
6771                                 if ((unsigned char)*ptr == CTLESC) {
6772                                         len--;
6773                                         ptr++;
6774                                 }
6775                         }
6776                 }
6777                 orig_len = len;
6778                 if (*loc++ == ':') {
6779                         /* ${var::LEN} */
6780                         len = ash_arith(loc);
6781                 } else {
6782                         /* Skip POS in ${var:POS:LEN} */
6783                         len = orig_len;
6784                         while (*loc && *loc != ':') {
6785                                 loc++;
6786                         }
6787                         if (*loc++ == ':') {
6788                                 len = ash_arith(loc);
6789                         }
6790                 }
6791 #  undef ash_arith
6792
6793                 if (pos < 0) {
6794                         /* ${VAR:$((-n)):l} starts n chars from the end */
6795                         pos = orig_len + pos;
6796                 }
6797                 if ((unsigned)pos >= orig_len) {
6798                         /* apart from obvious ${VAR:999999:l},
6799                          * covers ${VAR:$((-9999999)):l} - result is ""
6800                          * (bash compat)
6801                          */
6802                         pos = 0;
6803                         len = 0;
6804                 }
6805                 if (len < 0) {
6806                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6807                         len = (orig_len - pos) + len;
6808                 }
6809                 if ((unsigned)len > (orig_len - pos))
6810                         len = orig_len - pos;
6811
6812                 for (str = startp; pos; str++, pos--) {
6813                         if (quotes && (unsigned char)*str == CTLESC)
6814                                 str++;
6815                 }
6816                 for (loc = startp; len; len--) {
6817                         if (quotes && (unsigned char)*str == CTLESC)
6818                                 *loc++ = *str++;
6819                         *loc++ = *str++;
6820                 }
6821                 *loc = '\0';
6822                 amount = loc - expdest;
6823                 STADJUST(amount, expdest);
6824                 return loc;
6825         }
6826 #endif /* BASH_SUBSTR */
6827         }
6828
6829         resetloc = expdest - (char *)stackblock();
6830
6831 #if BASH_PATTERN_SUBST
6832         /* We'll comeback here if we grow the stack while handling
6833          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6834          * stack will need rebasing, and we'll need to remove our work
6835          * areas each time
6836          */
6837  restart:
6838 #endif
6839
6840         amount = expdest - ((char *)stackblock() + resetloc);
6841         STADJUST(-amount, expdest);
6842         startp = (char *)stackblock() + startloc;
6843
6844         rmesc = startp;
6845         rmescend = (char *)stackblock() + strloc;
6846         if (quotes) {
6847                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6848                 if (rmesc != startp) {
6849                         rmescend = expdest;
6850                         startp = (char *)stackblock() + startloc;
6851                 }
6852         }
6853         rmescend--;
6854         str = (char *)stackblock() + strloc;
6855         /*
6856          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6857          * The result is a_\_z_c (not a\_\_z_c)!
6858          *
6859          * The search pattern and replace string treat backslashes differently!
6860          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6861          * and string.  It's only used on the first call.
6862          */
6863         preglob(str, IF_BASH_PATTERN_SUBST(
6864                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6865                         RMESCAPE_SLASH : ) 0);
6866
6867 #if BASH_PATTERN_SUBST
6868         workloc = expdest - (char *)stackblock();
6869         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6870                 int len;
6871                 char *idx, *end;
6872
6873                 if (!repl) {
6874                         repl = strchr(str, CTLESC);
6875                         if (repl)
6876                                 *repl++ = '\0';
6877                         else
6878                                 repl = nullstr;
6879                 }
6880                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6881
6882                 /* If there's no pattern to match, return the expansion unmolested */
6883                 if (str[0] == '\0')
6884                         return NULL;
6885
6886                 len = 0;
6887                 idx = startp;
6888                 end = str - 1;
6889                 while (idx < end) {
6890  try_to_match:
6891                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6892                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6893                         if (!loc) {
6894                                 /* No match, advance */
6895                                 char *restart_detect = stackblock();
6896  skip_matching:
6897                                 STPUTC(*idx, expdest);
6898                                 if (quotes && (unsigned char)*idx == CTLESC) {
6899                                         idx++;
6900                                         len++;
6901                                         STPUTC(*idx, expdest);
6902                                 }
6903                                 if (stackblock() != restart_detect)
6904                                         goto restart;
6905                                 idx++;
6906                                 len++;
6907                                 rmesc++;
6908                                 /* continue; - prone to quadratic behavior, smarter code: */
6909                                 if (idx >= end)
6910                                         break;
6911                                 if (str[0] == '*') {
6912                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6913                                          * it would never match "ong_string" etc, no point in trying.
6914                                          */
6915                                         goto skip_matching;
6916                                 }
6917                                 goto try_to_match;
6918                         }
6919
6920                         if (subtype == VSREPLACEALL) {
6921                                 while (idx < loc) {
6922                                         if (quotes && (unsigned char)*idx == CTLESC)
6923                                                 idx++;
6924                                         idx++;
6925                                         rmesc++;
6926                                 }
6927                         } else {
6928                                 idx = loc;
6929                         }
6930
6931                         //bb_error_msg("repl:'%s'", repl);
6932                         for (loc = (char*)repl; *loc; loc++) {
6933                                 char *restart_detect = stackblock();
6934                                 if (quotes && *loc == '\\') {
6935                                         STPUTC(CTLESC, expdest);
6936                                         len++;
6937                                 }
6938                                 STPUTC(*loc, expdest);
6939                                 if (stackblock() != restart_detect)
6940                                         goto restart;
6941                                 len++;
6942                         }
6943
6944                         if (subtype == VSREPLACE) {
6945                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6946                                 while (*idx) {
6947                                         char *restart_detect = stackblock();
6948                                         STPUTC(*idx, expdest);
6949                                         if (stackblock() != restart_detect)
6950                                                 goto restart;
6951                                         len++;
6952                                         idx++;
6953                                 }
6954                                 break;
6955                         }
6956                 }
6957
6958                 /* We've put the replaced text into a buffer at workloc, now
6959                  * move it to the right place and adjust the stack.
6960                  */
6961                 STPUTC('\0', expdest);
6962                 startp = (char *)stackblock() + startloc;
6963                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6964                 //bb_error_msg("startp:'%s'", startp);
6965                 amount = expdest - (startp + len);
6966                 STADJUST(-amount, expdest);
6967                 return startp;
6968         }
6969 #endif /* BASH_PATTERN_SUBST */
6970
6971         subtype -= VSTRIMRIGHT;
6972 #if DEBUG
6973         if (subtype < 0 || subtype > 7)
6974                 abort();
6975 #endif
6976         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6977         zero = subtype >> 1;
6978         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6979         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6980
6981         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6982         if (loc) {
6983                 if (zero) {
6984                         memmove(startp, loc, str - loc);
6985                         loc = startp + (str - loc) - 1;
6986                 }
6987                 *loc = '\0';
6988                 amount = loc - expdest;
6989                 STADJUST(amount, expdest);
6990         }
6991         return loc;
6992 }
6993
6994 /*
6995  * Add the value of a specialized variable to the stack string.
6996  * name parameter (examples):
6997  * ash -c 'echo $1'      name:'1='
6998  * ash -c 'echo $qwe'    name:'qwe='
6999  * ash -c 'echo $$'      name:'$='
7000  * ash -c 'echo ${$}'    name:'$='
7001  * ash -c 'echo ${$##q}' name:'$=q'
7002  * ash -c 'echo ${#$}'   name:'$='
7003  * note: examples with bad shell syntax:
7004  * ash -c 'echo ${#$1}'  name:'$=1'
7005  * ash -c 'echo ${#1#}'  name:'1=#'
7006  */
7007 static NOINLINE ssize_t
7008 varvalue(char *name, int varflags, int flags, int *quotedp)
7009 {
7010         const char *p;
7011         int num;
7012         int i;
7013         ssize_t len = 0;
7014         int sep;
7015         int quoted = *quotedp;
7016         int subtype = varflags & VSTYPE;
7017         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7018         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7019         int syntax;
7020
7021         sep = (flags & EXP_FULL) << CHAR_BIT;
7022         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7023
7024         switch (*name) {
7025         case '$':
7026                 num = rootpid;
7027                 goto numvar;
7028         case '?':
7029                 num = exitstatus;
7030                 goto numvar;
7031         case '#':
7032                 num = shellparam.nparam;
7033                 goto numvar;
7034         case '!':
7035                 num = backgndpid;
7036                 if (num == 0)
7037                         return -1;
7038  numvar:
7039                 len = cvtnum(num);
7040                 goto check_1char_name;
7041         case '-':
7042                 expdest = makestrspace(NOPTS, expdest);
7043                 for (i = NOPTS - 1; i >= 0; i--) {
7044                         if (optlist[i]) {
7045                                 USTPUTC(optletters(i), expdest);
7046                                 len++;
7047                         }
7048                 }
7049  check_1char_name:
7050 #if 0
7051                 /* handles cases similar to ${#$1} */
7052                 if (name[2] != '\0')
7053                         raise_error_syntax("bad substitution");
7054 #endif
7055                 break;
7056         case '@':
7057                 if (quoted && sep)
7058                         goto param;
7059                 /* fall through */
7060         case '*': {
7061                 char **ap;
7062                 char sepc;
7063
7064                 if (quoted)
7065                         sep = 0;
7066                 sep |= ifsset() ? ifsval()[0] : ' ';
7067  param:
7068                 sepc = sep;
7069                 *quotedp = !sepc;
7070                 ap = shellparam.p;
7071                 if (!ap)
7072                         return -1;
7073                 while ((p = *ap++) != NULL) {
7074                         len += strtodest(p, syntax, quotes);
7075
7076                         if (*ap && sep) {
7077                                 len++;
7078                                 memtodest(&sepc, 1, syntax, quotes);
7079                         }
7080                 }
7081                 break;
7082         } /* case '*' */
7083         case '0':
7084         case '1':
7085         case '2':
7086         case '3':
7087         case '4':
7088         case '5':
7089         case '6':
7090         case '7':
7091         case '8':
7092         case '9':
7093                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7094                 if (num < 0 || num > shellparam.nparam)
7095                         return -1;
7096                 p = num ? shellparam.p[num - 1] : arg0;
7097                 goto value;
7098         default:
7099                 /* NB: name has form "VAR=..." */
7100                 p = lookupvar(name);
7101  value:
7102                 if (!p)
7103                         return -1;
7104
7105                 len = strtodest(p, syntax, quotes);
7106 #if ENABLE_UNICODE_SUPPORT
7107                 if (subtype == VSLENGTH && len > 0) {
7108                         reinit_unicode_for_ash();
7109                         if (unicode_status == UNICODE_ON) {
7110                                 STADJUST(-len, expdest);
7111                                 discard = 0;
7112                                 len = unicode_strlen(p);
7113                         }
7114                 }
7115 #endif
7116                 break;
7117         }
7118
7119         if (discard)
7120                 STADJUST(-len, expdest);
7121         return len;
7122 }
7123
7124 /*
7125  * Expand a variable, and return a pointer to the next character in the
7126  * input string.
7127  */
7128 static char *
7129 evalvar(char *p, int flag)
7130 {
7131         char varflags;
7132         char subtype;
7133         int quoted;
7134         char easy;
7135         char *var;
7136         int patloc;
7137         int startloc;
7138         ssize_t varlen;
7139
7140         varflags = (unsigned char) *p++;
7141         subtype = varflags & VSTYPE;
7142
7143         if (!subtype)
7144                 raise_error_syntax("bad substitution");
7145
7146         quoted = flag & EXP_QUOTED;
7147         var = p;
7148         easy = (!quoted || (*var == '@' && shellparam.nparam));
7149         startloc = expdest - (char *)stackblock();
7150         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7151
7152  again:
7153         varlen = varvalue(var, varflags, flag, &quoted);
7154         if (varflags & VSNUL)
7155                 varlen--;
7156
7157         if (subtype == VSPLUS) {
7158                 varlen = -1 - varlen;
7159                 goto vsplus;
7160         }
7161
7162         if (subtype == VSMINUS) {
7163  vsplus:
7164                 if (varlen < 0) {
7165                         argstr(
7166                                 p,
7167                                 flag | EXP_TILDE | EXP_WORD
7168                         );
7169                         goto end;
7170                 }
7171                 goto record;
7172         }
7173
7174         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7175                 if (varlen >= 0)
7176                         goto record;
7177
7178                 subevalvar(p, var, 0, subtype, startloc, varflags,
7179                            flag & ~QUOTES_ESC);
7180                 varflags &= ~VSNUL;
7181                 /*
7182                  * Remove any recorded regions beyond
7183                  * start of variable
7184                  */
7185                 removerecordregions(startloc);
7186                 goto again;
7187         }
7188
7189         if (varlen < 0 && uflag)
7190                 varunset(p, var, 0, 0);
7191
7192         if (subtype == VSLENGTH) {
7193                 cvtnum(varlen > 0 ? varlen : 0);
7194                 goto record;
7195         }
7196
7197         if (subtype == VSNORMAL) {
7198  record:
7199                 if (!easy)
7200                         goto end;
7201                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7202                 goto end;
7203         }
7204
7205 #if DEBUG
7206         switch (subtype) {
7207         case VSTRIMLEFT:
7208         case VSTRIMLEFTMAX:
7209         case VSTRIMRIGHT:
7210         case VSTRIMRIGHTMAX:
7211 #if BASH_SUBSTR
7212         case VSSUBSTR:
7213 #endif
7214 #if BASH_PATTERN_SUBST
7215         case VSREPLACE:
7216         case VSREPLACEALL:
7217 #endif
7218                 break;
7219         default:
7220                 abort();
7221         }
7222 #endif
7223
7224         if (varlen >= 0) {
7225                 /*
7226                  * Terminate the string and start recording the pattern
7227                  * right after it
7228                  */
7229                 STPUTC('\0', expdest);
7230                 patloc = expdest - (char *)stackblock();
7231                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7232                                 startloc, varflags, flag)) {
7233                         int amount = expdest - (
7234                                 (char *)stackblock() + patloc - 1
7235                         );
7236                         STADJUST(-amount, expdest);
7237                 }
7238                 /* Remove any recorded regions beyond start of variable */
7239                 removerecordregions(startloc);
7240                 goto record;
7241         }
7242
7243  end:
7244         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7245                 int nesting = 1;
7246                 for (;;) {
7247                         unsigned char c = *p++;
7248                         if (c == CTLESC)
7249                                 p++;
7250                         else if (c == CTLBACKQ) {
7251                                 if (varlen >= 0)
7252                                         argbackq = argbackq->next;
7253                         } else if (c == CTLVAR) {
7254                                 if ((*p++ & VSTYPE) != VSNORMAL)
7255                                         nesting++;
7256                         } else if (c == CTLENDVAR) {
7257                                 if (--nesting == 0)
7258                                         break;
7259                         }
7260                 }
7261         }
7262         return p;
7263 }
7264
7265 /*
7266  * Add a file name to the list.
7267  */
7268 static void
7269 addfname(const char *name)
7270 {
7271         struct strlist *sp;
7272
7273         sp = stzalloc(sizeof(*sp));
7274         sp->text = sstrdup(name);
7275         *exparg.lastp = sp;
7276         exparg.lastp = &sp->next;
7277 }
7278
7279 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7280 static int
7281 hasmeta(const char *p)
7282 {
7283         static const char chars[] ALIGN1 = {
7284                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7285         };
7286
7287         for (;;) {
7288                 p = strpbrk(p, chars);
7289                 if (!p)
7290                         break;
7291                 switch ((unsigned char) *p) {
7292                 case CTLQUOTEMARK:
7293                         for (;;) {
7294                                 p++;
7295                                 if (*p == CTLQUOTEMARK)
7296                                         break;
7297                                 if (*p == CTLESC)
7298                                         p++;
7299                                 if (*p == '\0') /* huh? */
7300                                         return 0;
7301                         }
7302                         break;
7303                 case '\\':
7304                 case CTLESC:
7305                         p++;
7306                         if (*p == '\0')
7307                                 return 0;
7308                         break;
7309                 case '[':
7310                         if (!strchr(p + 1, ']')) {
7311                                 /* It's not a properly closed [] pattern,
7312                                  * but other metas may follow. Continue checking.
7313                                  * my[file* _is_ globbed by bash
7314                                  * and matches filenames like "my[file1".
7315                                  */
7316                                 break;
7317                         }
7318                         /* fallthrough */
7319                 default:
7320                 /* case '*': */
7321                 /* case '?': */
7322                         return 1;
7323                 }
7324                 p++;
7325         }
7326
7327         return 0;
7328 }
7329
7330 /* If we want to use glob() from libc... */
7331 #if !ENABLE_ASH_INTERNAL_GLOB
7332
7333 /* Add the result of glob() to the list */
7334 static void
7335 addglob(const glob_t *pglob)
7336 {
7337         char **p = pglob->gl_pathv;
7338
7339         do {
7340                 addfname(*p);
7341         } while (*++p);
7342 }
7343 static void
7344 expandmeta(struct strlist *str /*, int flag*/)
7345 {
7346         /* TODO - EXP_REDIR */
7347
7348         while (str) {
7349                 char *p;
7350                 glob_t pglob;
7351                 int i;
7352
7353                 if (fflag)
7354                         goto nometa;
7355
7356                 if (!hasmeta(str->text))
7357                         goto nometa;
7358
7359                 INT_OFF;
7360                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7361 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7362 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7363 //
7364 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7365 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7366 // Which means you need to unescape the string, right? Not so fast:
7367 // if there _is_ a file named "file\?" (with backslash), it is returned
7368 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7369 // You DON'T KNOW by looking at the result whether you need to unescape it.
7370 //
7371 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7372 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7373 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7374 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7375 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7376 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7377                 i = glob(p, 0, NULL, &pglob);
7378                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7379                 if (p != str->text)
7380                         free(p);
7381                 switch (i) {
7382                 case 0:
7383 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7384                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7385                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7386                                 goto nometa2;
7387 #endif
7388                         addglob(&pglob);
7389                         globfree(&pglob);
7390                         INT_ON;
7391                         break;
7392                 case GLOB_NOMATCH:
7393  //nometa2:
7394                         globfree(&pglob);
7395                         INT_ON;
7396  nometa:
7397                         *exparg.lastp = str;
7398                         rmescapes(str->text, 0);
7399                         exparg.lastp = &str->next;
7400                         break;
7401                 default:        /* GLOB_NOSPACE */
7402                         globfree(&pglob);
7403                         INT_ON;
7404                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7405                 }
7406                 str = str->next;
7407         }
7408 }
7409
7410 #else
7411 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7412
7413 /*
7414  * Do metacharacter (i.e. *, ?, [...]) expansion.
7415  */
7416 static void
7417 expmeta(char *expdir, char *enddir, char *name)
7418 {
7419         char *p;
7420         const char *cp;
7421         char *start;
7422         char *endname;
7423         int metaflag;
7424         struct stat statb;
7425         DIR *dirp;
7426         struct dirent *dp;
7427         int atend;
7428         int matchdot;
7429         int esc;
7430
7431         metaflag = 0;
7432         start = name;
7433         for (p = name; esc = 0, *p; p += esc + 1) {
7434                 if (*p == '*' || *p == '?')
7435                         metaflag = 1;
7436                 else if (*p == '[') {
7437                         char *q = p + 1;
7438                         if (*q == '!')
7439                                 q++;
7440                         for (;;) {
7441                                 if (*q == '\\')
7442                                         q++;
7443                                 if (*q == '/' || *q == '\0')
7444                                         break;
7445                                 if (*++q == ']') {
7446                                         metaflag = 1;
7447                                         break;
7448                                 }
7449                         }
7450                 } else {
7451                         if (*p == '\\')
7452                                 esc++;
7453                         if (p[esc] == '/') {
7454                                 if (metaflag)
7455                                         break;
7456                                 start = p + esc + 1;
7457                         }
7458                 }
7459         }
7460         if (metaflag == 0) {    /* we've reached the end of the file name */
7461                 if (enddir != expdir)
7462                         metaflag++;
7463                 p = name;
7464                 do {
7465                         if (*p == '\\')
7466                                 p++;
7467                         *enddir++ = *p;
7468                 } while (*p++);
7469                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7470                         addfname(expdir);
7471                 return;
7472         }
7473         endname = p;
7474         if (name < start) {
7475                 p = name;
7476                 do {
7477                         if (*p == '\\')
7478                                 p++;
7479                         *enddir++ = *p++;
7480                 } while (p < start);
7481         }
7482         if (enddir == expdir) {
7483                 cp = ".";
7484         } else if (enddir == expdir + 1 && *expdir == '/') {
7485                 cp = "/";
7486         } else {
7487                 cp = expdir;
7488                 enddir[-1] = '\0';
7489         }
7490         dirp = opendir(cp);
7491         if (dirp == NULL)
7492                 return;
7493         if (enddir != expdir)
7494                 enddir[-1] = '/';
7495         if (*endname == 0) {
7496                 atend = 1;
7497         } else {
7498                 atend = 0;
7499                 *endname = '\0';
7500                 endname += esc + 1;
7501         }
7502         matchdot = 0;
7503         p = start;
7504         if (*p == '\\')
7505                 p++;
7506         if (*p == '.')
7507                 matchdot++;
7508         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7509                 if (dp->d_name[0] == '.' && !matchdot)
7510                         continue;
7511                 if (pmatch(start, dp->d_name)) {
7512                         if (atend) {
7513                                 strcpy(enddir, dp->d_name);
7514                                 addfname(expdir);
7515                         } else {
7516                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7517                                         continue;
7518                                 p[-1] = '/';
7519                                 expmeta(expdir, p, endname);
7520                         }
7521                 }
7522         }
7523         closedir(dirp);
7524         if (!atend)
7525                 endname[-esc - 1] = esc ? '\\' : '/';
7526 }
7527
7528 static struct strlist *
7529 msort(struct strlist *list, int len)
7530 {
7531         struct strlist *p, *q = NULL;
7532         struct strlist **lpp;
7533         int half;
7534         int n;
7535
7536         if (len <= 1)
7537                 return list;
7538         half = len >> 1;
7539         p = list;
7540         for (n = half; --n >= 0;) {
7541                 q = p;
7542                 p = p->next;
7543         }
7544         q->next = NULL;                 /* terminate first half of list */
7545         q = msort(list, half);          /* sort first half of list */
7546         p = msort(p, len - half);               /* sort second half */
7547         lpp = &list;
7548         for (;;) {
7549 #if ENABLE_LOCALE_SUPPORT
7550                 if (strcoll(p->text, q->text) < 0)
7551 #else
7552                 if (strcmp(p->text, q->text) < 0)
7553 #endif
7554                                                 {
7555                         *lpp = p;
7556                         lpp = &p->next;
7557                         p = *lpp;
7558                         if (p == NULL) {
7559                                 *lpp = q;
7560                                 break;
7561                         }
7562                 } else {
7563                         *lpp = q;
7564                         lpp = &q->next;
7565                         q = *lpp;
7566                         if (q == NULL) {
7567                                 *lpp = p;
7568                                 break;
7569                         }
7570                 }
7571         }
7572         return list;
7573 }
7574
7575 /*
7576  * Sort the results of file name expansion.  It calculates the number of
7577  * strings to sort and then calls msort (short for merge sort) to do the
7578  * work.
7579  */
7580 static struct strlist *
7581 expsort(struct strlist *str)
7582 {
7583         int len;
7584         struct strlist *sp;
7585
7586         len = 0;
7587         for (sp = str; sp; sp = sp->next)
7588                 len++;
7589         return msort(str, len);
7590 }
7591
7592 static void
7593 expandmeta(struct strlist *str /*, int flag*/)
7594 {
7595         /* TODO - EXP_REDIR */
7596
7597         while (str) {
7598                 char *expdir;
7599                 struct strlist **savelastp;
7600                 struct strlist *sp;
7601                 char *p;
7602
7603                 if (fflag)
7604                         goto nometa;
7605                 if (!hasmeta(str->text))
7606                         goto nometa;
7607                 savelastp = exparg.lastp;
7608
7609                 INT_OFF;
7610                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7611                 {
7612                         int i = strlen(str->text);
7613 //BUGGY estimation of how long expanded name can be
7614                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7615                 }
7616                 expmeta(expdir, expdir, p);
7617                 free(expdir);
7618                 if (p != str->text)
7619                         free(p);
7620                 INT_ON;
7621                 if (exparg.lastp == savelastp) {
7622                         /*
7623                          * no matches
7624                          */
7625  nometa:
7626                         *exparg.lastp = str;
7627                         rmescapes(str->text, 0);
7628                         exparg.lastp = &str->next;
7629                 } else {
7630                         *exparg.lastp = NULL;
7631                         *savelastp = sp = expsort(*savelastp);
7632                         while (sp->next != NULL)
7633                                 sp = sp->next;
7634                         exparg.lastp = &sp->next;
7635                 }
7636                 str = str->next;
7637         }
7638 }
7639 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7640
7641 /*
7642  * Perform variable substitution and command substitution on an argument,
7643  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7644  * perform splitting and file name expansion.  When arglist is NULL, perform
7645  * here document expansion.
7646  */
7647 static void
7648 expandarg(union node *arg, struct arglist *arglist, int flag)
7649 {
7650         struct strlist *sp;
7651         char *p;
7652
7653         argbackq = arg->narg.backquote;
7654         STARTSTACKSTR(expdest);
7655         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7656         argstr(arg->narg.text, flag);
7657         p = _STPUTC('\0', expdest);
7658         expdest = p - 1;
7659         if (arglist == NULL) {
7660                 /* here document expanded */
7661                 goto out;
7662         }
7663         p = grabstackstr(p);
7664         TRACE(("expandarg: p:'%s'\n", p));
7665         exparg.lastp = &exparg.list;
7666         /*
7667          * TODO - EXP_REDIR
7668          */
7669         if (flag & EXP_FULL) {
7670                 ifsbreakup(p, &exparg);
7671                 *exparg.lastp = NULL;
7672                 exparg.lastp = &exparg.list;
7673                 expandmeta(exparg.list /*, flag*/);
7674         } else {
7675                 sp = stzalloc(sizeof(*sp));
7676                 sp->text = p;
7677                 *exparg.lastp = sp;
7678                 exparg.lastp = &sp->next;
7679         }
7680         *exparg.lastp = NULL;
7681         if (exparg.list) {
7682                 *arglist->lastp = exparg.list;
7683                 arglist->lastp = exparg.lastp;
7684         }
7685
7686  out:
7687         ifsfree();
7688 }
7689
7690 /*
7691  * Expand shell variables and backquotes inside a here document.
7692  */
7693 static void
7694 expandhere(union node *arg, int fd)
7695 {
7696         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7697         full_write(fd, stackblock(), expdest - (char *)stackblock());
7698 }
7699
7700 /*
7701  * Returns true if the pattern matches the string.
7702  */
7703 static int
7704 patmatch(char *pattern, const char *string)
7705 {
7706         char *p = preglob(pattern, 0);
7707         int r = pmatch(p, string);
7708         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7709         return r;
7710 }
7711
7712 /*
7713  * See if a pattern matches in a case statement.
7714  */
7715 static int
7716 casematch(union node *pattern, char *val)
7717 {
7718         struct stackmark smark;
7719         int result;
7720
7721         setstackmark(&smark);
7722         argbackq = pattern->narg.backquote;
7723         STARTSTACKSTR(expdest);
7724         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7725         STACKSTRNUL(expdest);
7726         ifsfree();
7727         result = patmatch(stackblock(), val);
7728         popstackmark(&smark);
7729         return result;
7730 }
7731
7732
7733 /* ============ find_command */
7734
7735 struct builtincmd {
7736         const char *name;
7737         int (*builtin)(int, char **) FAST_FUNC;
7738         /* unsigned flags; */
7739 };
7740 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7741 /* "regular" builtins always take precedence over commands,
7742  * regardless of PATH=....%builtin... position */
7743 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7744 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7745
7746 struct cmdentry {
7747         smallint cmdtype;       /* CMDxxx */
7748         union param {
7749                 int index;
7750                 /* index >= 0 for commands without path (slashes) */
7751                 /* (TODO: what exactly does the value mean? PATH position?) */
7752                 /* index == -1 for commands with slashes */
7753                 /* index == (-2 - applet_no) for NOFORK applets */
7754                 const struct builtincmd *cmd;
7755                 struct funcnode *func;
7756         } u;
7757 };
7758 /* values of cmdtype */
7759 #define CMDUNKNOWN      -1      /* no entry in table for command */
7760 #define CMDNORMAL       0       /* command is an executable program */
7761 #define CMDFUNCTION     1       /* command is a shell function */
7762 #define CMDBUILTIN      2       /* command is a shell builtin */
7763
7764 /* action to find_command() */
7765 #define DO_ERR          0x01    /* prints errors */
7766 #define DO_ABS          0x02    /* checks absolute paths */
7767 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7768 #define DO_ALTPATH      0x08    /* using alternate path */
7769 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7770
7771 static void find_command(char *, struct cmdentry *, int, const char *);
7772
7773
7774 /* ============ Hashing commands */
7775
7776 /*
7777  * When commands are first encountered, they are entered in a hash table.
7778  * This ensures that a full path search will not have to be done for them
7779  * on each invocation.
7780  *
7781  * We should investigate converting to a linear search, even though that
7782  * would make the command name "hash" a misnomer.
7783  */
7784
7785 struct tblentry {
7786         struct tblentry *next;  /* next entry in hash chain */
7787         union param param;      /* definition of builtin function */
7788         smallint cmdtype;       /* CMDxxx */
7789         char rehash;            /* if set, cd done since entry created */
7790         char cmdname[1];        /* name of command */
7791 };
7792
7793 static struct tblentry **cmdtable;
7794 #define INIT_G_cmdtable() do { \
7795         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7796 } while (0)
7797
7798 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7799
7800
7801 static void
7802 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7803 {
7804 #if ENABLE_FEATURE_SH_STANDALONE
7805         if (applet_no >= 0) {
7806                 if (APPLET_IS_NOEXEC(applet_no)) {
7807                         clearenv();
7808                         while (*envp)
7809                                 putenv(*envp++);
7810                         popredir(/*drop:*/ 1);
7811                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7812                 }
7813                 /* re-exec ourselves with the new arguments */
7814                 execve(bb_busybox_exec_path, argv, envp);
7815                 /* If they called chroot or otherwise made the binary no longer
7816                  * executable, fall through */
7817         }
7818 #endif
7819
7820  repeat:
7821 #ifdef SYSV
7822         do {
7823                 execve(cmd, argv, envp);
7824         } while (errno == EINTR);
7825 #else
7826         execve(cmd, argv, envp);
7827 #endif
7828         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7829                 /* Run "cmd" as a shell script:
7830                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7831                  * "If the execve() function fails with ENOEXEC, the shell
7832                  * shall execute a command equivalent to having a shell invoked
7833                  * with the command name as its first operand,
7834                  * with any remaining arguments passed to the new shell"
7835                  *
7836                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7837                  * just call ourselves.
7838                  *
7839                  * Note that bash reads ~80 chars of the file, and if it sees
7840                  * a zero byte before it sees newline, it doesn't try to
7841                  * interpret it, but fails with "cannot execute binary file"
7842                  * message and exit code 126. For one, this prevents attempts
7843                  * to interpret foreign ELF binaries as shell scripts.
7844                  */
7845                 argv[0] = (char*) cmd;
7846                 cmd = bb_busybox_exec_path;
7847                 /* NB: this is only possible because all callers of shellexec()
7848                  * ensure that the argv[-1] slot exists!
7849                  */
7850                 argv--;
7851                 argv[0] = (char*) "ash";
7852                 goto repeat;
7853         }
7854 }
7855
7856 /*
7857  * Exec a program.  Never returns.  If you change this routine, you may
7858  * have to change the find_command routine as well.
7859  * argv[-1] must exist and be writable! See tryexec() for why.
7860  */
7861 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7862 static void shellexec(char *prog, char **argv, const char *path, int idx)
7863 {
7864         char *cmdname;
7865         int e;
7866         char **envp;
7867         int exerrno;
7868         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7869
7870         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7871         if (strchr(prog, '/') != NULL
7872 #if ENABLE_FEATURE_SH_STANDALONE
7873          || (applet_no = find_applet_by_name(prog)) >= 0
7874 #endif
7875         ) {
7876                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7877                 if (applet_no >= 0) {
7878                         /* We tried execing ourself, but it didn't work.
7879                          * Maybe /proc/self/exe doesn't exist?
7880                          * Try $PATH search.
7881                          */
7882                         goto try_PATH;
7883                 }
7884                 e = errno;
7885         } else {
7886  try_PATH:
7887                 e = ENOENT;
7888                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7889                         if (--idx < 0 && pathopt == NULL) {
7890                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7891                                 if (errno != ENOENT && errno != ENOTDIR)
7892                                         e = errno;
7893                         }
7894                         stunalloc(cmdname);
7895                 }
7896         }
7897
7898         /* Map to POSIX errors */
7899         switch (e) {
7900         case EACCES:
7901                 exerrno = 126;
7902                 break;
7903         case ENOENT:
7904                 exerrno = 127;
7905                 break;
7906         default:
7907                 exerrno = 2;
7908                 break;
7909         }
7910         exitstatus = exerrno;
7911         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7912                 prog, e, suppress_int));
7913         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7914         /* NOTREACHED */
7915 }
7916
7917 static void
7918 printentry(struct tblentry *cmdp)
7919 {
7920         int idx;
7921         const char *path;
7922         char *name;
7923
7924         idx = cmdp->param.index;
7925         path = pathval();
7926         do {
7927                 name = path_advance(&path, cmdp->cmdname);
7928                 stunalloc(name);
7929         } while (--idx >= 0);
7930         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7931 }
7932
7933 /*
7934  * Clear out command entries.  The argument specifies the first entry in
7935  * PATH which has changed.
7936  */
7937 static void
7938 clearcmdentry(int firstchange)
7939 {
7940         struct tblentry **tblp;
7941         struct tblentry **pp;
7942         struct tblentry *cmdp;
7943
7944         INT_OFF;
7945         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7946                 pp = tblp;
7947                 while ((cmdp = *pp) != NULL) {
7948                         if ((cmdp->cmdtype == CMDNORMAL &&
7949                              cmdp->param.index >= firstchange)
7950                          || (cmdp->cmdtype == CMDBUILTIN &&
7951                              builtinloc >= firstchange)
7952                         ) {
7953                                 *pp = cmdp->next;
7954                                 free(cmdp);
7955                         } else {
7956                                 pp = &cmdp->next;
7957                         }
7958                 }
7959         }
7960         INT_ON;
7961 }
7962
7963 /*
7964  * Locate a command in the command hash table.  If "add" is nonzero,
7965  * add the command to the table if it is not already present.  The
7966  * variable "lastcmdentry" is set to point to the address of the link
7967  * pointing to the entry, so that delete_cmd_entry can delete the
7968  * entry.
7969  *
7970  * Interrupts must be off if called with add != 0.
7971  */
7972 static struct tblentry **lastcmdentry;
7973
7974 static struct tblentry *
7975 cmdlookup(const char *name, int add)
7976 {
7977         unsigned int hashval;
7978         const char *p;
7979         struct tblentry *cmdp;
7980         struct tblentry **pp;
7981
7982         p = name;
7983         hashval = (unsigned char)*p << 4;
7984         while (*p)
7985                 hashval += (unsigned char)*p++;
7986         hashval &= 0x7FFF;
7987         pp = &cmdtable[hashval % CMDTABLESIZE];
7988         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7989                 if (strcmp(cmdp->cmdname, name) == 0)
7990                         break;
7991                 pp = &cmdp->next;
7992         }
7993         if (add && cmdp == NULL) {
7994                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7995                                 + strlen(name)
7996                                 /* + 1 - already done because
7997                                  * tblentry::cmdname is char[1] */);
7998                 /*cmdp->next = NULL; - ckzalloc did it */
7999                 cmdp->cmdtype = CMDUNKNOWN;
8000                 strcpy(cmdp->cmdname, name);
8001         }
8002         lastcmdentry = pp;
8003         return cmdp;
8004 }
8005
8006 /*
8007  * Delete the command entry returned on the last lookup.
8008  */
8009 static void
8010 delete_cmd_entry(void)
8011 {
8012         struct tblentry *cmdp;
8013
8014         INT_OFF;
8015         cmdp = *lastcmdentry;
8016         *lastcmdentry = cmdp->next;
8017         if (cmdp->cmdtype == CMDFUNCTION)
8018                 freefunc(cmdp->param.func);
8019         free(cmdp);
8020         INT_ON;
8021 }
8022
8023 /*
8024  * Add a new command entry, replacing any existing command entry for
8025  * the same name - except special builtins.
8026  */
8027 static void
8028 addcmdentry(char *name, struct cmdentry *entry)
8029 {
8030         struct tblentry *cmdp;
8031
8032         cmdp = cmdlookup(name, 1);
8033         if (cmdp->cmdtype == CMDFUNCTION) {
8034                 freefunc(cmdp->param.func);
8035         }
8036         cmdp->cmdtype = entry->cmdtype;
8037         cmdp->param = entry->u;
8038         cmdp->rehash = 0;
8039 }
8040
8041 static int FAST_FUNC
8042 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8043 {
8044         struct tblentry **pp;
8045         struct tblentry *cmdp;
8046         int c;
8047         struct cmdentry entry;
8048         char *name;
8049
8050         if (nextopt("r") != '\0') {
8051                 clearcmdentry(0);
8052                 return 0;
8053         }
8054
8055         if (*argptr == NULL) {
8056                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8057                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8058                                 if (cmdp->cmdtype == CMDNORMAL)
8059                                         printentry(cmdp);
8060                         }
8061                 }
8062                 return 0;
8063         }
8064
8065         c = 0;
8066         while ((name = *argptr) != NULL) {
8067                 cmdp = cmdlookup(name, 0);
8068                 if (cmdp != NULL
8069                  && (cmdp->cmdtype == CMDNORMAL
8070                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8071                 ) {
8072                         delete_cmd_entry();
8073                 }
8074                 find_command(name, &entry, DO_ERR, pathval());
8075                 if (entry.cmdtype == CMDUNKNOWN)
8076                         c = 1;
8077                 argptr++;
8078         }
8079         return c;
8080 }
8081
8082 /*
8083  * Called when a cd is done.  Marks all commands so the next time they
8084  * are executed they will be rehashed.
8085  */
8086 static void
8087 hashcd(void)
8088 {
8089         struct tblentry **pp;
8090         struct tblentry *cmdp;
8091
8092         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8093                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8094                         if (cmdp->cmdtype == CMDNORMAL
8095                          || (cmdp->cmdtype == CMDBUILTIN
8096                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8097                              && builtinloc > 0)
8098                         ) {
8099                                 cmdp->rehash = 1;
8100                         }
8101                 }
8102         }
8103 }
8104
8105 /*
8106  * Fix command hash table when PATH changed.
8107  * Called before PATH is changed.  The argument is the new value of PATH;
8108  * pathval() still returns the old value at this point.
8109  * Called with interrupts off.
8110  */
8111 static void FAST_FUNC
8112 changepath(const char *new)
8113 {
8114         const char *old;
8115         int firstchange;
8116         int idx;
8117         int idx_bltin;
8118
8119         old = pathval();
8120         firstchange = 9999;     /* assume no change */
8121         idx = 0;
8122         idx_bltin = -1;
8123         for (;;) {
8124                 if (*old != *new) {
8125                         firstchange = idx;
8126                         if ((*old == '\0' && *new == ':')
8127                          || (*old == ':' && *new == '\0')
8128                         ) {
8129                                 firstchange++;
8130                         }
8131                         old = new;      /* ignore subsequent differences */
8132                 }
8133                 if (*new == '\0')
8134                         break;
8135                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8136                         idx_bltin = idx;
8137                 if (*new == ':')
8138                         idx++;
8139                 new++;
8140                 old++;
8141         }
8142         if (builtinloc < 0 && idx_bltin >= 0)
8143                 builtinloc = idx_bltin;             /* zap builtins */
8144         if (builtinloc >= 0 && idx_bltin < 0)
8145                 firstchange = 0;
8146         clearcmdentry(firstchange);
8147         builtinloc = idx_bltin;
8148 }
8149 enum {
8150         TEOF,
8151         TNL,
8152         TREDIR,
8153         TWORD,
8154         TSEMI,
8155         TBACKGND,
8156         TAND,
8157         TOR,
8158         TPIPE,
8159         TLP,
8160         TRP,
8161         TENDCASE,
8162         TENDBQUOTE,
8163         TNOT,
8164         TCASE,
8165         TDO,
8166         TDONE,
8167         TELIF,
8168         TELSE,
8169         TESAC,
8170         TFI,
8171         TFOR,
8172 #if BASH_FUNCTION
8173         TFUNCTION,
8174 #endif
8175         TIF,
8176         TIN,
8177         TTHEN,
8178         TUNTIL,
8179         TWHILE,
8180         TBEGIN,
8181         TEND
8182 };
8183 typedef smallint token_id_t;
8184
8185 /* Nth bit indicates if token marks the end of a list */
8186 enum {
8187         tokendlist = 0
8188         /*  0 */ | (1u << TEOF)
8189         /*  1 */ | (0u << TNL)
8190         /*  2 */ | (0u << TREDIR)
8191         /*  3 */ | (0u << TWORD)
8192         /*  4 */ | (0u << TSEMI)
8193         /*  5 */ | (0u << TBACKGND)
8194         /*  6 */ | (0u << TAND)
8195         /*  7 */ | (0u << TOR)
8196         /*  8 */ | (0u << TPIPE)
8197         /*  9 */ | (0u << TLP)
8198         /* 10 */ | (1u << TRP)
8199         /* 11 */ | (1u << TENDCASE)
8200         /* 12 */ | (1u << TENDBQUOTE)
8201         /* 13 */ | (0u << TNOT)
8202         /* 14 */ | (0u << TCASE)
8203         /* 15 */ | (1u << TDO)
8204         /* 16 */ | (1u << TDONE)
8205         /* 17 */ | (1u << TELIF)
8206         /* 18 */ | (1u << TELSE)
8207         /* 19 */ | (1u << TESAC)
8208         /* 20 */ | (1u << TFI)
8209         /* 21 */ | (0u << TFOR)
8210 #if BASH_FUNCTION
8211         /* 22 */ | (0u << TFUNCTION)
8212 #endif
8213         /* 23 */ | (0u << TIF)
8214         /* 24 */ | (0u << TIN)
8215         /* 25 */ | (1u << TTHEN)
8216         /* 26 */ | (0u << TUNTIL)
8217         /* 27 */ | (0u << TWHILE)
8218         /* 28 */ | (0u << TBEGIN)
8219         /* 29 */ | (1u << TEND)
8220         , /* thus far 29 bits used */
8221 };
8222
8223 static const char *const tokname_array[] = {
8224         "end of file",
8225         "newline",
8226         "redirection",
8227         "word",
8228         ";",
8229         "&",
8230         "&&",
8231         "||",
8232         "|",
8233         "(",
8234         ")",
8235         ";;",
8236         "`",
8237 #define KWDOFFSET 13
8238         /* the following are keywords */
8239         "!",
8240         "case",
8241         "do",
8242         "done",
8243         "elif",
8244         "else",
8245         "esac",
8246         "fi",
8247         "for",
8248 #if BASH_FUNCTION
8249         "function",
8250 #endif
8251         "if",
8252         "in",
8253         "then",
8254         "until",
8255         "while",
8256         "{",
8257         "}",
8258 };
8259
8260 /* Wrapper around strcmp for qsort/bsearch/... */
8261 static int
8262 pstrcmp(const void *a, const void *b)
8263 {
8264         return strcmp((char*)a, *(char**)b);
8265 }
8266
8267 static const char *const *
8268 findkwd(const char *s)
8269 {
8270         return bsearch(s, tokname_array + KWDOFFSET,
8271                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8272                         sizeof(tokname_array[0]), pstrcmp);
8273 }
8274
8275 /*
8276  * Locate and print what a word is...
8277  */
8278 static int
8279 describe_command(char *command, const char *path, int describe_command_verbose)
8280 {
8281         struct cmdentry entry;
8282 #if ENABLE_ASH_ALIAS
8283         const struct alias *ap;
8284 #endif
8285
8286         path = path ? path : pathval();
8287
8288         if (describe_command_verbose) {
8289                 out1str(command);
8290         }
8291
8292         /* First look at the keywords */
8293         if (findkwd(command)) {
8294                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8295                 goto out;
8296         }
8297
8298 #if ENABLE_ASH_ALIAS
8299         /* Then look at the aliases */
8300         ap = lookupalias(command, 0);
8301         if (ap != NULL) {
8302                 if (!describe_command_verbose) {
8303                         out1str("alias ");
8304                         printalias(ap);
8305                         return 0;
8306                 }
8307                 out1fmt(" is an alias for %s", ap->val);
8308                 goto out;
8309         }
8310 #endif
8311         /* Brute force */
8312         find_command(command, &entry, DO_ABS, path);
8313
8314         switch (entry.cmdtype) {
8315         case CMDNORMAL: {
8316                 int j = entry.u.index;
8317                 char *p;
8318                 if (j < 0) {
8319                         p = command;
8320                 } else {
8321                         do {
8322                                 p = path_advance(&path, command);
8323                                 stunalloc(p);
8324                         } while (--j >= 0);
8325                 }
8326                 if (describe_command_verbose) {
8327                         out1fmt(" is %s", p);
8328                 } else {
8329                         out1str(p);
8330                 }
8331                 break;
8332         }
8333
8334         case CMDFUNCTION:
8335                 if (describe_command_verbose) {
8336                         out1str(" is a shell function");
8337                 } else {
8338                         out1str(command);
8339                 }
8340                 break;
8341
8342         case CMDBUILTIN:
8343                 if (describe_command_verbose) {
8344                         out1fmt(" is a %sshell builtin",
8345                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8346                                         "special " : nullstr
8347                         );
8348                 } else {
8349                         out1str(command);
8350                 }
8351                 break;
8352
8353         default:
8354                 if (describe_command_verbose) {
8355                         out1str(": not found\n");
8356                 }
8357                 return 127;
8358         }
8359  out:
8360         out1str("\n");
8361         return 0;
8362 }
8363
8364 static int FAST_FUNC
8365 typecmd(int argc UNUSED_PARAM, char **argv)
8366 {
8367         int i = 1;
8368         int err = 0;
8369         int verbose = 1;
8370
8371         /* type -p ... ? (we don't bother checking for 'p') */
8372         if (argv[1] && argv[1][0] == '-') {
8373                 i++;
8374                 verbose = 0;
8375         }
8376         while (argv[i]) {
8377                 err |= describe_command(argv[i++], NULL, verbose);
8378         }
8379         return err;
8380 }
8381
8382 #if ENABLE_ASH_CMDCMD
8383 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8384 static char **
8385 parse_command_args(char **argv, const char **path)
8386 {
8387         char *cp, c;
8388
8389         for (;;) {
8390                 cp = *++argv;
8391                 if (!cp)
8392                         return NULL;
8393                 if (*cp++ != '-')
8394                         break;
8395                 c = *cp++;
8396                 if (!c)
8397                         break;
8398                 if (c == '-' && !*cp) {
8399                         if (!*++argv)
8400                                 return NULL;
8401                         break;
8402                 }
8403                 do {
8404                         switch (c) {
8405                         case 'p':
8406                                 *path = bb_default_path;
8407                                 break;
8408                         default:
8409                                 /* run 'typecmd' for other options */
8410                                 return NULL;
8411                         }
8412                         c = *cp++;
8413                 } while (c);
8414         }
8415         return argv;
8416 }
8417
8418 static int FAST_FUNC
8419 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8420 {
8421         char *cmd;
8422         int c;
8423         enum {
8424                 VERIFY_BRIEF = 1,
8425                 VERIFY_VERBOSE = 2,
8426         } verify = 0;
8427         const char *path = NULL;
8428
8429         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8430          * never reaches this function.
8431          */
8432
8433         while ((c = nextopt("pvV")) != '\0')
8434                 if (c == 'V')
8435                         verify |= VERIFY_VERBOSE;
8436                 else if (c == 'v')
8437                         /*verify |= VERIFY_BRIEF*/;
8438 #if DEBUG
8439                 else if (c != 'p')
8440                         abort();
8441 #endif
8442                 else
8443                         path = bb_default_path;
8444
8445         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8446         cmd = *argptr;
8447         if (/*verify && */ cmd)
8448                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8449
8450         return 0;
8451 }
8452 #endif
8453
8454
8455 /*static int funcblocksize;     // size of structures in function */
8456 /*static int funcstringsize;    // size of strings in node */
8457 static void *funcblock;         /* block to allocate function from */
8458 static char *funcstring_end;    /* end of block to allocate strings from */
8459
8460 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8461         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8462         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8463         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8464         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8465         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8466         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8467         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8468         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8469         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8470         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8471         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8472         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8473         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8474         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8475         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8476         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8477         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8478 #if BASH_REDIR_OUTPUT
8479         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8480 #endif
8481         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8482         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8483         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8484         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8485         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8486         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8487         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8488         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8489         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8490 };
8491
8492 static int calcsize(int funcblocksize, union node *n);
8493
8494 static int
8495 sizenodelist(int funcblocksize, struct nodelist *lp)
8496 {
8497         while (lp) {
8498                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8499                 funcblocksize = calcsize(funcblocksize, lp->n);
8500                 lp = lp->next;
8501         }
8502         return funcblocksize;
8503 }
8504
8505 static int
8506 calcsize(int funcblocksize, union node *n)
8507 {
8508         if (n == NULL)
8509                 return funcblocksize;
8510         funcblocksize += nodesize[n->type];
8511         switch (n->type) {
8512         case NCMD:
8513                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8514                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8515                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8516                 break;
8517         case NPIPE:
8518                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8519                 break;
8520         case NREDIR:
8521         case NBACKGND:
8522         case NSUBSHELL:
8523                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8524                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8525                 break;
8526         case NAND:
8527         case NOR:
8528         case NSEMI:
8529         case NWHILE:
8530         case NUNTIL:
8531                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8532                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8533                 break;
8534         case NIF:
8535                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8536                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8537                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8538                 break;
8539         case NFOR:
8540                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8541                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8542                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8543                 break;
8544         case NCASE:
8545                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8546                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8547                 break;
8548         case NCLIST:
8549                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8550                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8551                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8552                 break;
8553         case NDEFUN:
8554         case NARG:
8555                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8556                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8557                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8558                 break;
8559         case NTO:
8560 #if BASH_REDIR_OUTPUT
8561         case NTO2:
8562 #endif
8563         case NCLOBBER:
8564         case NFROM:
8565         case NFROMTO:
8566         case NAPPEND:
8567                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8568                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8569                 break;
8570         case NTOFD:
8571         case NFROMFD:
8572                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8573                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8574         break;
8575         case NHERE:
8576         case NXHERE:
8577                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8578                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8579                 break;
8580         case NNOT:
8581                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8582                 break;
8583         };
8584         return funcblocksize;
8585 }
8586
8587 static char *
8588 nodeckstrdup(char *s)
8589 {
8590         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8591         return strcpy(funcstring_end, s);
8592 }
8593
8594 static union node *copynode(union node *);
8595
8596 static struct nodelist *
8597 copynodelist(struct nodelist *lp)
8598 {
8599         struct nodelist *start;
8600         struct nodelist **lpp;
8601
8602         lpp = &start;
8603         while (lp) {
8604                 *lpp = funcblock;
8605                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8606                 (*lpp)->n = copynode(lp->n);
8607                 lp = lp->next;
8608                 lpp = &(*lpp)->next;
8609         }
8610         *lpp = NULL;
8611         return start;
8612 }
8613
8614 static union node *
8615 copynode(union node *n)
8616 {
8617         union node *new;
8618
8619         if (n == NULL)
8620                 return NULL;
8621         new = funcblock;
8622         funcblock = (char *) funcblock + nodesize[n->type];
8623
8624         switch (n->type) {
8625         case NCMD:
8626                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8627                 new->ncmd.args = copynode(n->ncmd.args);
8628                 new->ncmd.assign = copynode(n->ncmd.assign);
8629                 break;
8630         case NPIPE:
8631                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8632                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8633                 break;
8634         case NREDIR:
8635         case NBACKGND:
8636         case NSUBSHELL:
8637                 new->nredir.redirect = copynode(n->nredir.redirect);
8638                 new->nredir.n = copynode(n->nredir.n);
8639                 break;
8640         case NAND:
8641         case NOR:
8642         case NSEMI:
8643         case NWHILE:
8644         case NUNTIL:
8645                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8646                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8647                 break;
8648         case NIF:
8649                 new->nif.elsepart = copynode(n->nif.elsepart);
8650                 new->nif.ifpart = copynode(n->nif.ifpart);
8651                 new->nif.test = copynode(n->nif.test);
8652                 break;
8653         case NFOR:
8654                 new->nfor.var = nodeckstrdup(n->nfor.var);
8655                 new->nfor.body = copynode(n->nfor.body);
8656                 new->nfor.args = copynode(n->nfor.args);
8657                 break;
8658         case NCASE:
8659                 new->ncase.cases = copynode(n->ncase.cases);
8660                 new->ncase.expr = copynode(n->ncase.expr);
8661                 break;
8662         case NCLIST:
8663                 new->nclist.body = copynode(n->nclist.body);
8664                 new->nclist.pattern = copynode(n->nclist.pattern);
8665                 new->nclist.next = copynode(n->nclist.next);
8666                 break;
8667         case NDEFUN:
8668         case NARG:
8669                 new->narg.backquote = copynodelist(n->narg.backquote);
8670                 new->narg.text = nodeckstrdup(n->narg.text);
8671                 new->narg.next = copynode(n->narg.next);
8672                 break;
8673         case NTO:
8674 #if BASH_REDIR_OUTPUT
8675         case NTO2:
8676 #endif
8677         case NCLOBBER:
8678         case NFROM:
8679         case NFROMTO:
8680         case NAPPEND:
8681                 new->nfile.fname = copynode(n->nfile.fname);
8682                 new->nfile.fd = n->nfile.fd;
8683                 new->nfile.next = copynode(n->nfile.next);
8684                 break;
8685         case NTOFD:
8686         case NFROMFD:
8687                 new->ndup.vname = copynode(n->ndup.vname);
8688                 new->ndup.dupfd = n->ndup.dupfd;
8689                 new->ndup.fd = n->ndup.fd;
8690                 new->ndup.next = copynode(n->ndup.next);
8691                 break;
8692         case NHERE:
8693         case NXHERE:
8694                 new->nhere.doc = copynode(n->nhere.doc);
8695                 new->nhere.fd = n->nhere.fd;
8696                 new->nhere.next = copynode(n->nhere.next);
8697                 break;
8698         case NNOT:
8699                 new->nnot.com = copynode(n->nnot.com);
8700                 break;
8701         };
8702         new->type = n->type;
8703         return new;
8704 }
8705
8706 /*
8707  * Make a copy of a parse tree.
8708  */
8709 static struct funcnode *
8710 copyfunc(union node *n)
8711 {
8712         struct funcnode *f;
8713         size_t blocksize;
8714
8715         /*funcstringsize = 0;*/
8716         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8717         f = ckzalloc(blocksize /* + funcstringsize */);
8718         funcblock = (char *) f + offsetof(struct funcnode, n);
8719         funcstring_end = (char *) f + blocksize;
8720         copynode(n);
8721         /* f->count = 0; - ckzalloc did it */
8722         return f;
8723 }
8724
8725 /*
8726  * Define a shell function.
8727  */
8728 static void
8729 defun(union node *func)
8730 {
8731         struct cmdentry entry;
8732
8733         INT_OFF;
8734         entry.cmdtype = CMDFUNCTION;
8735         entry.u.func = copyfunc(func);
8736         addcmdentry(func->narg.text, &entry);
8737         INT_ON;
8738 }
8739
8740 /* Reasons for skipping commands (see comment on breakcmd routine) */
8741 #define SKIPBREAK      (1 << 0)
8742 #define SKIPCONT       (1 << 1)
8743 #define SKIPFUNC       (1 << 2)
8744 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8745 static int skipcount;           /* number of levels to skip */
8746 static int funcnest;            /* depth of function calls */
8747 static int loopnest;            /* current loop nesting level */
8748
8749 /* Forward decl way out to parsing code - dotrap needs it */
8750 static int evalstring(char *s, int flags);
8751
8752 /* Called to execute a trap.
8753  * Single callsite - at the end of evaltree().
8754  * If we return non-zero, evaltree raises EXEXIT exception.
8755  *
8756  * Perhaps we should avoid entering new trap handlers
8757  * while we are executing a trap handler. [is it a TODO?]
8758  */
8759 static void
8760 dotrap(void)
8761 {
8762         uint8_t *g;
8763         int sig;
8764         uint8_t last_status;
8765
8766         if (!pending_sig)
8767                 return;
8768
8769         last_status = exitstatus;
8770         pending_sig = 0;
8771         barrier();
8772
8773         TRACE(("dotrap entered\n"));
8774         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8775                 char *p;
8776
8777                 if (!*g)
8778                         continue;
8779
8780                 if (evalskip) {
8781                         pending_sig = sig;
8782                         break;
8783                 }
8784
8785                 p = trap[sig];
8786                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8787                  * don't upset it by resetting gotsig[SIGINT-1] */
8788                 if (sig == SIGINT && !p)
8789                         continue;
8790
8791                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8792                 *g = 0;
8793                 if (!p)
8794                         continue;
8795                 evalstring(p, 0);
8796         }
8797         exitstatus = last_status;
8798         TRACE(("dotrap returns\n"));
8799 }
8800
8801 /* forward declarations - evaluation is fairly recursive business... */
8802 static int evalloop(union node *, int);
8803 static int evalfor(union node *, int);
8804 static int evalcase(union node *, int);
8805 static int evalsubshell(union node *, int);
8806 static void expredir(union node *);
8807 static int evalpipe(union node *, int);
8808 static int evalcommand(union node *, int);
8809 static int evalbltin(const struct builtincmd *, int, char **, int);
8810 static void prehash(union node *);
8811
8812 /*
8813  * Evaluate a parse tree.  The value is left in the global variable
8814  * exitstatus.
8815  */
8816 static int
8817 evaltree(union node *n, int flags)
8818 {
8819         int checkexit = 0;
8820         int (*evalfn)(union node *, int);
8821         int status = 0;
8822
8823         if (n == NULL) {
8824                 TRACE(("evaltree(NULL) called\n"));
8825                 goto out;
8826         }
8827         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8828
8829         dotrap();
8830
8831         switch (n->type) {
8832         default:
8833 #if DEBUG
8834                 out1fmt("Node type = %d\n", n->type);
8835                 fflush_all();
8836                 break;
8837 #endif
8838         case NNOT:
8839                 status = !evaltree(n->nnot.com, EV_TESTED);
8840                 goto setstatus;
8841         case NREDIR:
8842                 expredir(n->nredir.redirect);
8843                 pushredir(n->nredir.redirect);
8844                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8845                 if (!status) {
8846                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8847                 }
8848                 if (n->nredir.redirect)
8849                         popredir(/*drop:*/ 0);
8850                 goto setstatus;
8851         case NCMD:
8852                 evalfn = evalcommand;
8853  checkexit:
8854                 if (eflag && !(flags & EV_TESTED))
8855                         checkexit = ~0;
8856                 goto calleval;
8857         case NFOR:
8858                 evalfn = evalfor;
8859                 goto calleval;
8860         case NWHILE:
8861         case NUNTIL:
8862                 evalfn = evalloop;
8863                 goto calleval;
8864         case NSUBSHELL:
8865         case NBACKGND:
8866                 evalfn = evalsubshell;
8867                 goto checkexit;
8868         case NPIPE:
8869                 evalfn = evalpipe;
8870                 goto checkexit;
8871         case NCASE:
8872                 evalfn = evalcase;
8873                 goto calleval;
8874         case NAND:
8875         case NOR:
8876         case NSEMI: {
8877
8878 #if NAND + 1 != NOR
8879 #error NAND + 1 != NOR
8880 #endif
8881 #if NOR + 1 != NSEMI
8882 #error NOR + 1 != NSEMI
8883 #endif
8884                 unsigned is_or = n->type - NAND;
8885                 status = evaltree(
8886                         n->nbinary.ch1,
8887                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8888                 );
8889                 if ((!status) == is_or || evalskip)
8890                         break;
8891                 n = n->nbinary.ch2;
8892  evaln:
8893                 evalfn = evaltree;
8894  calleval:
8895                 status = evalfn(n, flags);
8896                 goto setstatus;
8897         }
8898         case NIF:
8899                 status = evaltree(n->nif.test, EV_TESTED);
8900                 if (evalskip)
8901                         break;
8902                 if (!status) {
8903                         n = n->nif.ifpart;
8904                         goto evaln;
8905                 }
8906                 if (n->nif.elsepart) {
8907                         n = n->nif.elsepart;
8908                         goto evaln;
8909                 }
8910                 status = 0;
8911                 goto setstatus;
8912         case NDEFUN:
8913                 defun(n);
8914                 /* Not necessary. To test it:
8915                  * "false; f() { qwerty; }; echo $?" should print 0.
8916                  */
8917                 /* status = 0; */
8918  setstatus:
8919                 exitstatus = status;
8920                 break;
8921         }
8922  out:
8923         /* Order of checks below is important:
8924          * signal handlers trigger before exit caused by "set -e".
8925          */
8926         dotrap();
8927
8928         if (checkexit & status)
8929                 raise_exception(EXEXIT);
8930         if (flags & EV_EXIT)
8931                 raise_exception(EXEXIT);
8932
8933         TRACE(("leaving evaltree (no interrupts)\n"));
8934         return exitstatus;
8935 }
8936
8937 static int
8938 skiploop(void)
8939 {
8940         int skip = evalskip;
8941
8942         switch (skip) {
8943         case 0:
8944                 break;
8945         case SKIPBREAK:
8946         case SKIPCONT:
8947                 if (--skipcount <= 0) {
8948                         evalskip = 0;
8949                         break;
8950                 }
8951                 skip = SKIPBREAK;
8952                 break;
8953         }
8954         return skip;
8955 }
8956
8957 static int
8958 evalloop(union node *n, int flags)
8959 {
8960         int skip;
8961         int status;
8962
8963         loopnest++;
8964         status = 0;
8965         flags &= EV_TESTED;
8966         do {
8967                 int i;
8968
8969                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8970                 skip = skiploop();
8971                 if (skip == SKIPFUNC)
8972                         status = i;
8973                 if (skip)
8974                         continue;
8975                 if (n->type != NWHILE)
8976                         i = !i;
8977                 if (i != 0)
8978                         break;
8979                 status = evaltree(n->nbinary.ch2, flags);
8980                 skip = skiploop();
8981         } while (!(skip & ~SKIPCONT));
8982         loopnest--;
8983
8984         return status;
8985 }
8986
8987 static int
8988 evalfor(union node *n, int flags)
8989 {
8990         struct arglist arglist;
8991         union node *argp;
8992         struct strlist *sp;
8993         struct stackmark smark;
8994         int status = 0;
8995
8996         setstackmark(&smark);
8997         arglist.list = NULL;
8998         arglist.lastp = &arglist.list;
8999         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9000                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9001         }
9002         *arglist.lastp = NULL;
9003
9004         loopnest++;
9005         flags &= EV_TESTED;
9006         for (sp = arglist.list; sp; sp = sp->next) {
9007                 setvar0(n->nfor.var, sp->text);
9008                 status = evaltree(n->nfor.body, flags);
9009                 if (skiploop() & ~SKIPCONT)
9010                         break;
9011         }
9012         loopnest--;
9013         popstackmark(&smark);
9014
9015         return status;
9016 }
9017
9018 static int
9019 evalcase(union node *n, int flags)
9020 {
9021         union node *cp;
9022         union node *patp;
9023         struct arglist arglist;
9024         struct stackmark smark;
9025         int status = 0;
9026
9027         setstackmark(&smark);
9028         arglist.list = NULL;
9029         arglist.lastp = &arglist.list;
9030         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9031         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9032                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9033                         if (casematch(patp, arglist.list->text)) {
9034                                 /* Ensure body is non-empty as otherwise
9035                                  * EV_EXIT may prevent us from setting the
9036                                  * exit status.
9037                                  */
9038                                 if (evalskip == 0 && cp->nclist.body) {
9039                                         status = evaltree(cp->nclist.body, flags);
9040                                 }
9041                                 goto out;
9042                         }
9043                 }
9044         }
9045  out:
9046         popstackmark(&smark);
9047
9048         return status;
9049 }
9050
9051 /*
9052  * Kick off a subshell to evaluate a tree.
9053  */
9054 static int
9055 evalsubshell(union node *n, int flags)
9056 {
9057         struct job *jp;
9058         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9059         int status;
9060
9061         expredir(n->nredir.redirect);
9062         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9063                 goto nofork;
9064         INT_OFF;
9065         if (backgnd == FORK_FG)
9066                 get_tty_state();
9067         jp = makejob(/*n,*/ 1);
9068         if (forkshell(jp, n, backgnd) == 0) {
9069                 /* child */
9070                 INT_ON;
9071                 flags |= EV_EXIT;
9072                 if (backgnd)
9073                         flags &= ~EV_TESTED;
9074  nofork:
9075                 redirect(n->nredir.redirect, 0);
9076                 evaltreenr(n->nredir.n, flags);
9077                 /* never returns */
9078         }
9079         /* parent */
9080         status = 0;
9081         if (backgnd == FORK_FG)
9082                 status = waitforjob(jp);
9083         INT_ON;
9084         return status;
9085 }
9086
9087 /*
9088  * Compute the names of the files in a redirection list.
9089  */
9090 static void fixredir(union node *, const char *, int);
9091 static void
9092 expredir(union node *n)
9093 {
9094         union node *redir;
9095
9096         for (redir = n; redir; redir = redir->nfile.next) {
9097                 struct arglist fn;
9098
9099                 fn.list = NULL;
9100                 fn.lastp = &fn.list;
9101                 switch (redir->type) {
9102                 case NFROMTO:
9103                 case NFROM:
9104                 case NTO:
9105 #if BASH_REDIR_OUTPUT
9106                 case NTO2:
9107 #endif
9108                 case NCLOBBER:
9109                 case NAPPEND:
9110                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9111                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9112 #if BASH_REDIR_OUTPUT
9113  store_expfname:
9114 #endif
9115 #if 0
9116 // By the design of stack allocator, the loop of this kind:
9117 //      while true; do while true; do break; done </dev/null; done
9118 // will look like a memory leak: ash plans to free expfname's
9119 // of "/dev/null" as soon as it finishes running the loop
9120 // (in this case, never).
9121 // This "fix" is wrong:
9122                         if (redir->nfile.expfname)
9123                                 stunalloc(redir->nfile.expfname);
9124 // It results in corrupted state of stacked allocations.
9125 #endif
9126                         redir->nfile.expfname = fn.list->text;
9127                         break;
9128                 case NFROMFD:
9129                 case NTOFD: /* >& */
9130                         if (redir->ndup.vname) {
9131                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9132                                 if (fn.list == NULL)
9133                                         ash_msg_and_raise_error("redir error");
9134 #if BASH_REDIR_OUTPUT
9135 //FIXME: we used expandarg with different args!
9136                                 if (!isdigit_str9(fn.list->text)) {
9137                                         /* >&file, not >&fd */
9138                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9139                                                 ash_msg_and_raise_error("redir error");
9140                                         redir->type = NTO2;
9141                                         goto store_expfname;
9142                                 }
9143 #endif
9144                                 fixredir(redir, fn.list->text, 1);
9145                         }
9146                         break;
9147                 }
9148         }
9149 }
9150
9151 /*
9152  * Evaluate a pipeline.  All the processes in the pipeline are children
9153  * of the process creating the pipeline.  (This differs from some versions
9154  * of the shell, which make the last process in a pipeline the parent
9155  * of all the rest.)
9156  */
9157 static int
9158 evalpipe(union node *n, int flags)
9159 {
9160         struct job *jp;
9161         struct nodelist *lp;
9162         int pipelen;
9163         int prevfd;
9164         int pip[2];
9165         int status = 0;
9166
9167         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9168         pipelen = 0;
9169         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9170                 pipelen++;
9171         flags |= EV_EXIT;
9172         INT_OFF;
9173         if (n->npipe.pipe_backgnd == 0)
9174                 get_tty_state();
9175         jp = makejob(/*n,*/ pipelen);
9176         prevfd = -1;
9177         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9178                 prehash(lp->n);
9179                 pip[1] = -1;
9180                 if (lp->next) {
9181                         if (pipe(pip) < 0) {
9182                                 close(prevfd);
9183                                 ash_msg_and_raise_error("pipe call failed");
9184                         }
9185                 }
9186                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9187                         /* child */
9188                         INT_ON;
9189                         if (pip[1] >= 0) {
9190                                 close(pip[0]);
9191                         }
9192                         if (prevfd > 0) {
9193                                 dup2(prevfd, 0);
9194                                 close(prevfd);
9195                         }
9196                         if (pip[1] > 1) {
9197                                 dup2(pip[1], 1);
9198                                 close(pip[1]);
9199                         }
9200                         evaltreenr(lp->n, flags);
9201                         /* never returns */
9202                 }
9203                 /* parent */
9204                 if (prevfd >= 0)
9205                         close(prevfd);
9206                 prevfd = pip[0];
9207                 /* Don't want to trigger debugging */
9208                 if (pip[1] != -1)
9209                         close(pip[1]);
9210         }
9211         if (n->npipe.pipe_backgnd == 0) {
9212                 status = waitforjob(jp);
9213                 TRACE(("evalpipe:  job done exit status %d\n", status));
9214         }
9215         INT_ON;
9216
9217         return status;
9218 }
9219
9220 /*
9221  * Controls whether the shell is interactive or not.
9222  */
9223 static void
9224 setinteractive(int on)
9225 {
9226         static smallint is_interactive;
9227
9228         if (++on == is_interactive)
9229                 return;
9230         is_interactive = on;
9231         setsignal(SIGINT);
9232         setsignal(SIGQUIT);
9233         setsignal(SIGTERM);
9234 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9235         if (is_interactive > 1) {
9236                 /* Looks like they want an interactive shell */
9237                 static smallint did_banner;
9238
9239                 if (!did_banner) {
9240                         /* note: ash and hush share this string */
9241                         out1fmt("\n\n%s %s\n"
9242                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9243                                 "\n",
9244                                 bb_banner,
9245                                 "built-in shell (ash)"
9246                         );
9247                         did_banner = 1;
9248                 }
9249         }
9250 #endif
9251 }
9252
9253 static void
9254 optschanged(void)
9255 {
9256 #if DEBUG
9257         opentrace();
9258 #endif
9259         setinteractive(iflag);
9260         setjobctl(mflag);
9261 #if ENABLE_FEATURE_EDITING_VI
9262         if (viflag)
9263                 line_input_state->flags |= VI_MODE;
9264         else
9265                 line_input_state->flags &= ~VI_MODE;
9266 #else
9267         viflag = 0; /* forcibly keep the option off */
9268 #endif
9269 }
9270
9271 struct localvar_list {
9272         struct localvar_list *next;
9273         struct localvar *lv;
9274 };
9275
9276 static struct localvar_list *localvar_stack;
9277
9278 /*
9279  * Called after a function returns.
9280  * Interrupts must be off.
9281  */
9282 static void
9283 poplocalvars(int keep)
9284 {
9285         struct localvar_list *ll;
9286         struct localvar *lvp, *next;
9287         struct var *vp;
9288
9289         INT_OFF;
9290         ll = localvar_stack;
9291         localvar_stack = ll->next;
9292
9293         next = ll->lv;
9294         free(ll);
9295
9296         while ((lvp = next) != NULL) {
9297                 next = lvp->next;
9298                 vp = lvp->vp;
9299                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9300                 if (keep) {
9301                         int bits = VSTRFIXED;
9302
9303                         if (lvp->flags != VUNSET) {
9304                                 if (vp->var_text == lvp->text)
9305                                         bits |= VTEXTFIXED;
9306                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9307                                         free((char*)lvp->text);
9308                         }
9309
9310                         vp->flags &= ~bits;
9311                         vp->flags |= (lvp->flags & bits);
9312
9313                         if ((vp->flags &
9314                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9315                                 unsetvar(vp->var_text);
9316                 } else if (vp == NULL) {        /* $- saved */
9317                         memcpy(optlist, lvp->text, sizeof(optlist));
9318                         free((char*)lvp->text);
9319                         optschanged();
9320                 } else if (lvp->flags == VUNSET) {
9321                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9322                         unsetvar(vp->var_text);
9323                 } else {
9324                         if (vp->var_func)
9325                                 vp->var_func(var_end(lvp->text));
9326                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9327                                 free((char*)vp->var_text);
9328                         vp->flags = lvp->flags;
9329                         vp->var_text = lvp->text;
9330                 }
9331                 free(lvp);
9332         }
9333         INT_ON;
9334 }
9335
9336 /*
9337  * Create a new localvar environment.
9338  */
9339 static struct localvar_list *
9340 pushlocalvars(void)
9341 {
9342         struct localvar_list *ll;
9343
9344         INT_OFF;
9345         ll = ckzalloc(sizeof(*ll));
9346         /*ll->lv = NULL; - zalloc did it */
9347         ll->next = localvar_stack;
9348         localvar_stack = ll;
9349         INT_ON;
9350
9351         return ll->next;
9352 }
9353
9354 static void
9355 unwindlocalvars(struct localvar_list *stop)
9356 {
9357         while (localvar_stack != stop)
9358                 poplocalvars(0);
9359 }
9360
9361 static int
9362 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9363 {
9364         volatile struct shparam saveparam;
9365         struct jmploc *volatile savehandler;
9366         struct jmploc jmploc;
9367         int e;
9368
9369         saveparam = shellparam;
9370         savehandler = exception_handler;
9371         e = setjmp(jmploc.loc);
9372         if (e) {
9373                 goto funcdone;
9374         }
9375         INT_OFF;
9376         exception_handler = &jmploc;
9377         shellparam.malloced = 0;
9378         func->count++;
9379         funcnest++;
9380         INT_ON;
9381         shellparam.nparam = argc - 1;
9382         shellparam.p = argv + 1;
9383 #if ENABLE_ASH_GETOPTS
9384         shellparam.optind = 1;
9385         shellparam.optoff = -1;
9386 #endif
9387         pushlocalvars();
9388         evaltree(func->n.narg.next, flags & EV_TESTED);
9389         poplocalvars(0);
9390  funcdone:
9391         INT_OFF;
9392         funcnest--;
9393         freefunc(func);
9394         freeparam(&shellparam);
9395         shellparam = saveparam;
9396         exception_handler = savehandler;
9397         INT_ON;
9398         evalskip &= ~SKIPFUNC;
9399         return e;
9400 }
9401
9402 /*
9403  * Make a variable a local variable.  When a variable is made local, it's
9404  * value and flags are saved in a localvar structure.  The saved values
9405  * will be restored when the shell function returns.  We handle the name
9406  * "-" as a special case: it makes changes to "set +-options" local
9407  * (options will be restored on return from the function).
9408  */
9409 static void
9410 mklocal(char *name)
9411 {
9412         struct localvar *lvp;
9413         struct var **vpp;
9414         struct var *vp;
9415         char *eq = strchr(name, '=');
9416
9417         INT_OFF;
9418         /* Cater for duplicate "local". Examples:
9419          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9420          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9421          */
9422         lvp = localvar_stack->lv;
9423         while (lvp) {
9424                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9425                         if (eq)
9426                                 setvareq(name, 0);
9427                         /* else:
9428                          * it's a duplicate "local VAR" declaration, do nothing
9429                          */
9430                         goto ret;
9431                 }
9432                 lvp = lvp->next;
9433         }
9434
9435         lvp = ckzalloc(sizeof(*lvp));
9436         if (LONE_DASH(name)) {
9437                 char *p;
9438                 p = ckmalloc(sizeof(optlist));
9439                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9440                 vp = NULL;
9441         } else {
9442                 vpp = hashvar(name);
9443                 vp = *findvar(vpp, name);
9444                 if (vp == NULL) {
9445                         /* variable did not exist yet */
9446                         if (eq)
9447                                 vp = setvareq(name, VSTRFIXED);
9448                         else
9449                                 vp = setvar(name, NULL, VSTRFIXED);
9450                         lvp->flags = VUNSET;
9451                 } else {
9452                         lvp->text = vp->var_text;
9453                         lvp->flags = vp->flags;
9454                         /* make sure neither "struct var" nor string gets freed
9455                          * during (un)setting:
9456                          */
9457                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9458                         if (eq)
9459                                 setvareq(name, 0);
9460                         else
9461                                 /* "local VAR" unsets VAR: */
9462                                 setvar0(name, NULL);
9463                 }
9464         }
9465         lvp->vp = vp;
9466         lvp->next = localvar_stack->lv;
9467         localvar_stack->lv = lvp;
9468  ret:
9469         INT_ON;
9470 }
9471
9472 /*
9473  * The "local" command.
9474  */
9475 static int FAST_FUNC
9476 localcmd(int argc UNUSED_PARAM, char **argv)
9477 {
9478         char *name;
9479
9480         if (!localvar_stack)
9481                 ash_msg_and_raise_error("not in a function");
9482
9483         argv = argptr;
9484         while ((name = *argv++) != NULL) {
9485                 mklocal(name);
9486         }
9487         return 0;
9488 }
9489
9490 static int FAST_FUNC
9491 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9492 {
9493         return 1;
9494 }
9495
9496 static int FAST_FUNC
9497 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9498 {
9499         return 0;
9500 }
9501
9502 static int FAST_FUNC
9503 execcmd(int argc UNUSED_PARAM, char **argv)
9504 {
9505         optionarg = NULL;
9506         while (nextopt("a:") != '\0')
9507                 /* nextopt() sets optionarg to "-a ARGV0" */;
9508
9509         argv = argptr;
9510         if (argv[0]) {
9511                 char *prog;
9512
9513                 iflag = 0;              /* exit on error */
9514                 mflag = 0;
9515                 optschanged();
9516                 /* We should set up signals for "exec CMD"
9517                  * the same way as for "CMD" without "exec".
9518                  * But optschanged->setinteractive->setsignal
9519                  * still thought we are a root shell. Therefore, for example,
9520                  * SIGQUIT is still set to IGN. Fix it:
9521                  */
9522                 shlvl++;
9523                 setsignal(SIGQUIT);
9524                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9525                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9526                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9527
9528                 prog = argv[0];
9529                 if (optionarg)
9530                         argv[0] = optionarg;
9531                 shellexec(prog, argv, pathval(), 0);
9532                 /* NOTREACHED */
9533         }
9534         return 0;
9535 }
9536
9537 /*
9538  * The return command.
9539  */
9540 static int FAST_FUNC
9541 returncmd(int argc UNUSED_PARAM, char **argv)
9542 {
9543         /*
9544          * If called outside a function, do what ksh does;
9545          * skip the rest of the file.
9546          */
9547         evalskip = SKIPFUNC;
9548         return argv[1] ? number(argv[1]) : exitstatus;
9549 }
9550
9551 /* Forward declarations for builtintab[] */
9552 static int breakcmd(int, char **) FAST_FUNC;
9553 static int dotcmd(int, char **) FAST_FUNC;
9554 static int evalcmd(int, char **, int) FAST_FUNC;
9555 static int exitcmd(int, char **) FAST_FUNC;
9556 static int exportcmd(int, char **) FAST_FUNC;
9557 #if ENABLE_ASH_GETOPTS
9558 static int getoptscmd(int, char **) FAST_FUNC;
9559 #endif
9560 #if ENABLE_ASH_HELP
9561 static int helpcmd(int, char **) FAST_FUNC;
9562 #endif
9563 #if MAX_HISTORY
9564 static int historycmd(int, char **) FAST_FUNC;
9565 #endif
9566 #if ENABLE_FEATURE_SH_MATH
9567 static int letcmd(int, char **) FAST_FUNC;
9568 #endif
9569 static int readcmd(int, char **) FAST_FUNC;
9570 static int setcmd(int, char **) FAST_FUNC;
9571 static int shiftcmd(int, char **) FAST_FUNC;
9572 static int timescmd(int, char **) FAST_FUNC;
9573 static int trapcmd(int, char **) FAST_FUNC;
9574 static int umaskcmd(int, char **) FAST_FUNC;
9575 static int unsetcmd(int, char **) FAST_FUNC;
9576 static int ulimitcmd(int, char **) FAST_FUNC;
9577
9578 #define BUILTIN_NOSPEC          "0"
9579 #define BUILTIN_SPECIAL         "1"
9580 #define BUILTIN_REGULAR         "2"
9581 #define BUILTIN_SPEC_REG        "3"
9582 #define BUILTIN_ASSIGN          "4"
9583 #define BUILTIN_SPEC_ASSG       "5"
9584 #define BUILTIN_REG_ASSG        "6"
9585 #define BUILTIN_SPEC_REG_ASSG   "7"
9586
9587 /* Stubs for calling non-FAST_FUNC's */
9588 #if ENABLE_ASH_ECHO
9589 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9590 #endif
9591 #if ENABLE_ASH_PRINTF
9592 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9593 #endif
9594 #if ENABLE_ASH_TEST || BASH_TEST2
9595 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9596 #endif
9597
9598 /* Keep these in proper order since it is searched via bsearch() */
9599 static const struct builtincmd builtintab[] = {
9600         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9601         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9602 #if ENABLE_ASH_TEST
9603         { BUILTIN_REGULAR       "["       , testcmd    },
9604 #endif
9605 #if BASH_TEST2
9606         { BUILTIN_REGULAR       "[["      , testcmd    },
9607 #endif
9608 #if ENABLE_ASH_ALIAS
9609         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9610 #endif
9611 #if JOBS
9612         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9613 #endif
9614         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9615         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9616         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9617 #if ENABLE_ASH_CMDCMD
9618         { BUILTIN_REGULAR       "command" , commandcmd },
9619 #endif
9620         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9621 #if ENABLE_ASH_ECHO
9622         { BUILTIN_REGULAR       "echo"    , echocmd    },
9623 #endif
9624         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9625         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9626         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9627         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9628         { BUILTIN_REGULAR       "false"   , falsecmd   },
9629 #if JOBS
9630         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9631 #endif
9632 #if ENABLE_ASH_GETOPTS
9633         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9634 #endif
9635         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9636 #if ENABLE_ASH_HELP
9637         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9638 #endif
9639 #if MAX_HISTORY
9640         { BUILTIN_NOSPEC        "history" , historycmd },
9641 #endif
9642 #if JOBS
9643         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9644         { BUILTIN_REGULAR       "kill"    , killcmd    },
9645 #endif
9646 #if ENABLE_FEATURE_SH_MATH
9647         { BUILTIN_NOSPEC        "let"     , letcmd     },
9648 #endif
9649         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9650 #if ENABLE_ASH_PRINTF
9651         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9652 #endif
9653         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9654         { BUILTIN_REGULAR       "read"    , readcmd    },
9655         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9656         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9657         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9658         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9659 #if BASH_SOURCE
9660         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9661 #endif
9662 #if ENABLE_ASH_TEST
9663         { BUILTIN_REGULAR       "test"    , testcmd    },
9664 #endif
9665         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9666         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9667         { BUILTIN_REGULAR       "true"    , truecmd    },
9668         { BUILTIN_NOSPEC        "type"    , typecmd    },
9669         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9670         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9671 #if ENABLE_ASH_ALIAS
9672         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9673 #endif
9674         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9675         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9676 };
9677
9678 /* Should match the above table! */
9679 #define COMMANDCMD (builtintab + \
9680         /* . : */       2 + \
9681         /* [ */         1 * ENABLE_ASH_TEST + \
9682         /* [[ */        1 * BASH_TEST2 + \
9683         /* alias */     1 * ENABLE_ASH_ALIAS + \
9684         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9685         /* break cd cddir  */   3)
9686 #define EVALCMD (COMMANDCMD + \
9687         /* command */   1 * ENABLE_ASH_CMDCMD + \
9688         /* continue */  1 + \
9689         /* echo */      1 * ENABLE_ASH_ECHO + \
9690         0)
9691 #define EXECCMD (EVALCMD + \
9692         /* eval */      1)
9693
9694 /*
9695  * Search the table of builtin commands.
9696  */
9697 static int
9698 pstrcmp1(const void *a, const void *b)
9699 {
9700         return strcmp((char*)a, *(char**)b + 1);
9701 }
9702 static struct builtincmd *
9703 find_builtin(const char *name)
9704 {
9705         struct builtincmd *bp;
9706
9707         bp = bsearch(
9708                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9709                 pstrcmp1
9710         );
9711         return bp;
9712 }
9713
9714 /*
9715  * Execute a simple command.
9716  */
9717 static int
9718 isassignment(const char *p)
9719 {
9720         const char *q = endofname(p);
9721         if (p == q)
9722                 return 0;
9723         return *q == '=';
9724 }
9725 static int FAST_FUNC
9726 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9727 {
9728         /* Preserve exitstatus of a previous possible redirection
9729          * as POSIX mandates */
9730         return back_exitstatus;
9731 }
9732 static int
9733 evalcommand(union node *cmd, int flags)
9734 {
9735         static const struct builtincmd null_bltin = {
9736                 "\0\0", bltincmd /* why three NULs? */
9737         };
9738         struct localvar_list *localvar_stop;
9739         struct redirtab *redir_stop;
9740         struct stackmark smark;
9741         union node *argp;
9742         struct arglist arglist;
9743         struct arglist varlist;
9744         char **argv;
9745         int argc;
9746         const struct strlist *sp;
9747         struct cmdentry cmdentry;
9748         struct job *jp;
9749         char *lastarg;
9750         const char *path;
9751         int spclbltin;
9752         int status;
9753         char **nargv;
9754         smallint cmd_is_exec;
9755
9756         /* First expand the arguments. */
9757         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9758         setstackmark(&smark);
9759         localvar_stop = pushlocalvars();
9760         back_exitstatus = 0;
9761
9762         cmdentry.cmdtype = CMDBUILTIN;
9763         cmdentry.u.cmd = &null_bltin;
9764         varlist.lastp = &varlist.list;
9765         *varlist.lastp = NULL;
9766         arglist.lastp = &arglist.list;
9767         *arglist.lastp = NULL;
9768
9769         argc = 0;
9770         if (cmd->ncmd.args) {
9771                 struct builtincmd *bcmd;
9772                 smallint pseudovarflag;
9773
9774                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9775                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9776
9777                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9778                         struct strlist **spp;
9779
9780                         spp = arglist.lastp;
9781                         if (pseudovarflag && isassignment(argp->narg.text))
9782                                 expandarg(argp, &arglist, EXP_VARTILDE);
9783                         else
9784                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9785
9786                         for (sp = *spp; sp; sp = sp->next)
9787                                 argc++;
9788                 }
9789         }
9790
9791         /* Reserve one extra spot at the front for shellexec. */
9792         nargv = stalloc(sizeof(char *) * (argc + 2));
9793         argv = ++nargv;
9794         for (sp = arglist.list; sp; sp = sp->next) {
9795                 TRACE(("evalcommand arg: %s\n", sp->text));
9796                 *nargv++ = sp->text;
9797         }
9798         *nargv = NULL;
9799
9800         lastarg = NULL;
9801         if (iflag && funcnest == 0 && argc > 0)
9802                 lastarg = nargv[-1];
9803
9804         expredir(cmd->ncmd.redirect);
9805         redir_stop = pushredir(cmd->ncmd.redirect);
9806         preverrout_fd = 2;
9807         if (BASH_XTRACEFD && xflag) {
9808                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
9809                  * we do not emulate this. We only use its value.
9810                  */
9811                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
9812                 if (xtracefd && is_number(xtracefd))
9813                         preverrout_fd = atoi(xtracefd);
9814
9815         }
9816         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9817
9818         path = vpath.var_text;
9819         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9820                 struct strlist **spp;
9821                 char *p;
9822
9823                 spp = varlist.lastp;
9824                 expandarg(argp, &varlist, EXP_VARTILDE);
9825
9826                 mklocal((*spp)->text);
9827
9828                 /*
9829                  * Modify the command lookup path, if a PATH= assignment
9830                  * is present
9831                  */
9832                 p = (*spp)->text;
9833                 if (varcmp(p, path) == 0)
9834                         path = p;
9835         }
9836
9837         /* Print the command if xflag is set. */
9838         if (xflag) {
9839                 const char *pfx = "";
9840
9841                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9842
9843                 sp = varlist.list;
9844                 while (sp) {
9845                         char *varval = sp->text;
9846                         char *eq = strchrnul(varval, '=');
9847                         if (*eq)
9848                                 eq++;
9849                         fdprintf(preverrout_fd, "%s%.*s%s",
9850                                 pfx,
9851                                 (int)(eq - varval), varval,
9852                                 maybe_single_quote(eq)
9853                         );
9854                         sp = sp->next;
9855                         pfx = " ";
9856                 }
9857
9858                 sp = arglist.list;
9859                 while (sp) {
9860                         fdprintf(preverrout_fd, "%s%s",
9861                                 pfx,
9862                                 /* always quote if matches reserved word: */
9863                                 findkwd(sp->text)
9864                                 ? single_quote(sp->text)
9865                                 : maybe_single_quote(sp->text)
9866                         );
9867                         sp = sp->next;
9868                         pfx = " ";
9869                 }
9870                 safe_write(preverrout_fd, "\n", 1);
9871         }
9872
9873         cmd_is_exec = 0;
9874         spclbltin = -1;
9875
9876         /* Now locate the command. */
9877         if (argc) {
9878                 int cmd_flag = DO_ERR;
9879 #if ENABLE_ASH_CMDCMD
9880                 const char *oldpath = path + 5;
9881 #endif
9882                 path += 5;
9883                 for (;;) {
9884                         find_command(argv[0], &cmdentry, cmd_flag, path);
9885                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9886                                 flush_stdout_stderr();
9887                                 status = 127;
9888                                 goto bail;
9889                         }
9890
9891                         /* implement bltin and command here */
9892                         if (cmdentry.cmdtype != CMDBUILTIN)
9893                                 break;
9894                         if (spclbltin < 0)
9895                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9896                         if (cmdentry.u.cmd == EXECCMD)
9897                                 cmd_is_exec = 1;
9898 #if ENABLE_ASH_CMDCMD
9899                         if (cmdentry.u.cmd == COMMANDCMD) {
9900                                 path = oldpath;
9901                                 nargv = parse_command_args(argv, &path);
9902                                 if (!nargv)
9903                                         break;
9904                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9905                                  * nargv => "PROG". path is updated if -p.
9906                                  */
9907                                 argc -= nargv - argv;
9908                                 argv = nargv;
9909                                 cmd_flag |= DO_NOFUNC;
9910                         } else
9911 #endif
9912                                 break;
9913                 }
9914         }
9915
9916         if (status) {
9917  bail:
9918                 exitstatus = status;
9919
9920                 /* We have a redirection error. */
9921                 if (spclbltin > 0)
9922                         raise_exception(EXERROR);
9923
9924                 goto out;
9925         }
9926
9927         /* Execute the command. */
9928         switch (cmdentry.cmdtype) {
9929         default: {
9930
9931 #if ENABLE_FEATURE_SH_NOFORK
9932 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9933  *     around run_nofork_applet() call.
9934  * (2) Should this check also be done in forkshell()?
9935  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9936  */
9937                 /* find_command() encodes applet_no as (-2 - applet_no) */
9938                 int applet_no = (- cmdentry.u.index - 2);
9939                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9940                         listsetvar(varlist.list, VEXPORT|VSTACK);
9941                         /*
9942                          * Run <applet>_main().
9943                          * Signals (^C) can't interrupt here.
9944                          * Otherwise we can mangle stdio or malloc internal state.
9945                          * This makes applets which can run for a long time
9946                          * and/or wait for user input ineligible for NOFORK:
9947                          * for example, "yes" or "rm" (rm -i waits for input).
9948                          */
9949                         INT_OFF;
9950                         status = run_nofork_applet(applet_no, argv);
9951                         /*
9952                          * Try enabling NOFORK for "yes" applet.
9953                          * ^C _will_ stop it (write returns EINTR),
9954                          * but this causes stdout FILE to be stuck
9955                          * and needing clearerr(). What if other applets
9956                          * also can get EINTRs? Do we need to switch
9957                          * our signals to SA_RESTART?
9958                          */
9959                         /*clearerr(stdout);*/
9960                         INT_ON;
9961                         break;
9962                 }
9963 #endif
9964                 /* Can we avoid forking? For example, very last command
9965                  * in a script or a subshell does not need forking,
9966                  * we can just exec it.
9967                  */
9968                 if (!(flags & EV_EXIT) || may_have_traps) {
9969                         /* No, forking off a child is necessary */
9970                         INT_OFF;
9971                         get_tty_state();
9972                         jp = makejob(/*cmd,*/ 1);
9973                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9974                                 /* parent */
9975                                 status = waitforjob(jp);
9976                                 INT_ON;
9977                                 TRACE(("forked child exited with %d\n", status));
9978                                 break;
9979                         }
9980                         /* child */
9981                         FORCE_INT_ON;
9982                         /* fall through to exec'ing external program */
9983                 }
9984                 listsetvar(varlist.list, VEXPORT|VSTACK);
9985                 shellexec(argv[0], argv, path, cmdentry.u.index);
9986                 /* NOTREACHED */
9987         } /* default */
9988         case CMDBUILTIN:
9989                 if (spclbltin > 0 || argc == 0) {
9990                         poplocalvars(1);
9991                         if (cmd_is_exec && argc > 1)
9992                                 listsetvar(varlist.list, VEXPORT);
9993                 }
9994
9995                 /* Tight loop with builtins only:
9996                  * "while kill -0 $child; do true; done"
9997                  * will never exit even if $child died, unless we do this
9998                  * to reap the zombie and make kill detect that it's gone: */
9999                 dowait(DOWAIT_NONBLOCK, NULL);
10000
10001                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10002                         if (exception_type == EXERROR && spclbltin <= 0) {
10003                                 FORCE_INT_ON;
10004                                 goto readstatus;
10005                         }
10006  raise:
10007                         longjmp(exception_handler->loc, 1);
10008                 }
10009                 goto readstatus;
10010
10011         case CMDFUNCTION:
10012                 poplocalvars(1);
10013                 /* See above for the rationale */
10014                 dowait(DOWAIT_NONBLOCK, NULL);
10015                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10016                         goto raise;
10017  readstatus:
10018                 status = exitstatus;
10019                 break;
10020         } /* switch */
10021
10022  out:
10023         if (cmd->ncmd.redirect)
10024                 popredir(/*drop:*/ cmd_is_exec);
10025         unwindredir(redir_stop);
10026         unwindlocalvars(localvar_stop);
10027         if (lastarg) {
10028                 /* dsl: I think this is intended to be used to support
10029                  * '_' in 'vi' command mode during line editing...
10030                  * However I implemented that within libedit itself.
10031                  */
10032                 setvar0("_", lastarg);
10033         }
10034         popstackmark(&smark);
10035
10036         return status;
10037 }
10038
10039 static int
10040 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10041 {
10042         char *volatile savecmdname;
10043         struct jmploc *volatile savehandler;
10044         struct jmploc jmploc;
10045         int status;
10046         int i;
10047
10048         savecmdname = commandname;
10049         savehandler = exception_handler;
10050         i = setjmp(jmploc.loc);
10051         if (i)
10052                 goto cmddone;
10053         exception_handler = &jmploc;
10054         commandname = argv[0];
10055         argptr = argv + 1;
10056         optptr = NULL;                  /* initialize nextopt */
10057         if (cmd == EVALCMD)
10058                 status = evalcmd(argc, argv, flags);
10059         else
10060                 status = (*cmd->builtin)(argc, argv);
10061         flush_stdout_stderr();
10062         status |= ferror(stdout);
10063         exitstatus = status;
10064  cmddone:
10065         clearerr(stdout);
10066         commandname = savecmdname;
10067         exception_handler = savehandler;
10068
10069         return i;
10070 }
10071
10072 static int
10073 goodname(const char *p)
10074 {
10075         return endofname(p)[0] == '\0';
10076 }
10077
10078
10079 /*
10080  * Search for a command.  This is called before we fork so that the
10081  * location of the command will be available in the parent as well as
10082  * the child.  The check for "goodname" is an overly conservative
10083  * check that the name will not be subject to expansion.
10084  */
10085 static void
10086 prehash(union node *n)
10087 {
10088         struct cmdentry entry;
10089
10090         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10091                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10092 }
10093
10094
10095 /* ============ Builtin commands
10096  *
10097  * Builtin commands whose functions are closely tied to evaluation
10098  * are implemented here.
10099  */
10100
10101 /*
10102  * Handle break and continue commands.  Break, continue, and return are
10103  * all handled by setting the evalskip flag.  The evaluation routines
10104  * above all check this flag, and if it is set they start skipping
10105  * commands rather than executing them.  The variable skipcount is
10106  * the number of loops to break/continue, or the number of function
10107  * levels to return.  (The latter is always 1.)  It should probably
10108  * be an error to break out of more loops than exist, but it isn't
10109  * in the standard shell so we don't make it one here.
10110  */
10111 static int FAST_FUNC
10112 breakcmd(int argc UNUSED_PARAM, char **argv)
10113 {
10114         int n = argv[1] ? number(argv[1]) : 1;
10115
10116         if (n <= 0)
10117                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10118         if (n > loopnest)
10119                 n = loopnest;
10120         if (n > 0) {
10121                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10122                 skipcount = n;
10123         }
10124         return 0;
10125 }
10126
10127
10128 /*
10129  * This implements the input routines used by the parser.
10130  */
10131
10132 enum {
10133         INPUT_PUSH_FILE = 1,
10134         INPUT_NOFILE_OK = 2,
10135 };
10136
10137 static smallint checkkwd;
10138 /* values of checkkwd variable */
10139 #define CHKALIAS        0x1
10140 #define CHKKWD          0x2
10141 #define CHKNL           0x4
10142 #define CHKEOFMARK      0x8
10143
10144 /*
10145  * Push a string back onto the input at this current parsefile level.
10146  * We handle aliases this way.
10147  */
10148 #if !ENABLE_ASH_ALIAS
10149 #define pushstring(s, ap) pushstring(s)
10150 #endif
10151 static void
10152 pushstring(char *s, struct alias *ap)
10153 {
10154         struct strpush *sp;
10155         int len;
10156
10157         len = strlen(s);
10158         INT_OFF;
10159         if (g_parsefile->strpush) {
10160                 sp = ckzalloc(sizeof(*sp));
10161                 sp->prev = g_parsefile->strpush;
10162         } else {
10163                 sp = &(g_parsefile->basestrpush);
10164         }
10165         g_parsefile->strpush = sp;
10166         sp->prev_string = g_parsefile->next_to_pgetc;
10167         sp->prev_left_in_line = g_parsefile->left_in_line;
10168         sp->unget = g_parsefile->unget;
10169         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10170 #if ENABLE_ASH_ALIAS
10171         sp->ap = ap;
10172         if (ap) {
10173                 ap->flag |= ALIASINUSE;
10174                 sp->string = s;
10175         }
10176 #endif
10177         g_parsefile->next_to_pgetc = s;
10178         g_parsefile->left_in_line = len;
10179         g_parsefile->unget = 0;
10180         INT_ON;
10181 }
10182
10183 static void
10184 popstring(void)
10185 {
10186         struct strpush *sp = g_parsefile->strpush;
10187
10188         INT_OFF;
10189 #if ENABLE_ASH_ALIAS
10190         if (sp->ap) {
10191                 if (g_parsefile->next_to_pgetc[-1] == ' '
10192                  || g_parsefile->next_to_pgetc[-1] == '\t'
10193                 ) {
10194                         checkkwd |= CHKALIAS;
10195                 }
10196                 if (sp->string != sp->ap->val) {
10197                         free(sp->string);
10198                 }
10199                 sp->ap->flag &= ~ALIASINUSE;
10200                 if (sp->ap->flag & ALIASDEAD) {
10201                         unalias(sp->ap->name);
10202                 }
10203         }
10204 #endif
10205         g_parsefile->next_to_pgetc = sp->prev_string;
10206         g_parsefile->left_in_line = sp->prev_left_in_line;
10207         g_parsefile->unget = sp->unget;
10208         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10209         g_parsefile->strpush = sp->prev;
10210         if (sp != &(g_parsefile->basestrpush))
10211                 free(sp);
10212         INT_ON;
10213 }
10214
10215 static int
10216 preadfd(void)
10217 {
10218         int nr;
10219         char *buf = g_parsefile->buf;
10220
10221         g_parsefile->next_to_pgetc = buf;
10222 #if ENABLE_FEATURE_EDITING
10223  retry:
10224         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10225                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10226         else {
10227 # if ENABLE_ASH_IDLE_TIMEOUT
10228                 int timeout = -1;
10229                 if (iflag) {
10230                         const char *tmout_var = lookupvar("TMOUT");
10231                         if (tmout_var) {
10232                                 timeout = atoi(tmout_var) * 1000;
10233                                 if (timeout <= 0)
10234                                         timeout = -1;
10235                         }
10236                 }
10237                 line_input_state->timeout = timeout;
10238 # endif
10239 # if ENABLE_FEATURE_TAB_COMPLETION
10240                 line_input_state->path_lookup = pathval();
10241 # endif
10242                 reinit_unicode_for_ash();
10243                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10244                 if (nr == 0) {
10245                         /* ^C pressed, "convert" to SIGINT */
10246                         write(STDOUT_FILENO, "^C", 2);
10247                         if (trap[SIGINT]) {
10248                                 buf[0] = '\n';
10249                                 buf[1] = '\0';
10250                                 raise(SIGINT);
10251                                 return 1;
10252                         }
10253                         exitstatus = 128 + SIGINT;
10254                         bb_putchar('\n');
10255                         goto retry;
10256                 }
10257                 if (nr < 0) {
10258                         if (errno == 0) {
10259                                 /* Ctrl+D pressed */
10260                                 nr = 0;
10261                         }
10262 # if ENABLE_ASH_IDLE_TIMEOUT
10263                         else if (errno == EAGAIN && timeout > 0) {
10264                                 puts("\007timed out waiting for input: auto-logout");
10265                                 exitshell();
10266                         }
10267 # endif
10268                 }
10269         }
10270 #else
10271         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10272 #endif
10273
10274 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10275         if (nr < 0) {
10276                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10277                         int flags = fcntl(0, F_GETFL);
10278                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10279                                 flags &= ~O_NONBLOCK;
10280                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10281                                         out2str("sh: turning off NDELAY mode\n");
10282                                         goto retry;
10283                                 }
10284                         }
10285                 }
10286         }
10287 #endif
10288         return nr;
10289 }
10290
10291 /*
10292  * Refill the input buffer and return the next input character:
10293  *
10294  * 1) If a string was pushed back on the input, pop it;
10295  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10296  *    or we are reading from a string so we can't refill the buffer,
10297  *    return EOF.
10298  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10299  * 4) Process input up to the next newline, deleting nul characters.
10300  */
10301 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10302 #define pgetc_debug(...) ((void)0)
10303 static int pgetc(void);
10304 static int
10305 preadbuffer(void)
10306 {
10307         char *q;
10308         int more;
10309
10310         if (g_parsefile->strpush) {
10311 #if ENABLE_ASH_ALIAS
10312                 if (g_parsefile->left_in_line == -1
10313                  && g_parsefile->strpush->ap
10314                  && g_parsefile->next_to_pgetc[-1] != ' '
10315                  && g_parsefile->next_to_pgetc[-1] != '\t'
10316                 ) {
10317                         pgetc_debug("preadbuffer PEOA");
10318                         return PEOA;
10319                 }
10320 #endif
10321                 popstring();
10322                 return pgetc();
10323         }
10324         /* on both branches above g_parsefile->left_in_line < 0.
10325          * "pgetc" needs refilling.
10326          */
10327
10328         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10329          * pungetc() may increment it a few times.
10330          * Assuming it won't increment it to less than -90.
10331          */
10332         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10333                 pgetc_debug("preadbuffer PEOF1");
10334                 /* even in failure keep left_in_line and next_to_pgetc
10335                  * in lock step, for correct multi-layer pungetc.
10336                  * left_in_line was decremented before preadbuffer(),
10337                  * must inc next_to_pgetc: */
10338                 g_parsefile->next_to_pgetc++;
10339                 return PEOF;
10340         }
10341
10342         more = g_parsefile->left_in_buffer;
10343         if (more <= 0) {
10344                 flush_stdout_stderr();
10345  again:
10346                 more = preadfd();
10347                 if (more <= 0) {
10348                         /* don't try reading again */
10349                         g_parsefile->left_in_line = -99;
10350                         pgetc_debug("preadbuffer PEOF2");
10351                         g_parsefile->next_to_pgetc++;
10352                         return PEOF;
10353                 }
10354         }
10355
10356         /* Find out where's the end of line.
10357          * Set g_parsefile->left_in_line
10358          * and g_parsefile->left_in_buffer acordingly.
10359          * NUL chars are deleted.
10360          */
10361         q = g_parsefile->next_to_pgetc;
10362         for (;;) {
10363                 char c;
10364
10365                 more--;
10366
10367                 c = *q;
10368                 if (c == '\0') {
10369                         memmove(q, q + 1, more);
10370                 } else {
10371                         q++;
10372                         if (c == '\n') {
10373                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10374                                 break;
10375                         }
10376                 }
10377
10378                 if (more <= 0) {
10379                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10380                         if (g_parsefile->left_in_line < 0)
10381                                 goto again;
10382                         break;
10383                 }
10384         }
10385         g_parsefile->left_in_buffer = more;
10386
10387         if (vflag) {
10388                 char save = *q;
10389                 *q = '\0';
10390                 out2str(g_parsefile->next_to_pgetc);
10391                 *q = save;
10392         }
10393
10394         pgetc_debug("preadbuffer at %d:%p'%s'",
10395                         g_parsefile->left_in_line,
10396                         g_parsefile->next_to_pgetc,
10397                         g_parsefile->next_to_pgetc);
10398         return (unsigned char)*g_parsefile->next_to_pgetc++;
10399 }
10400
10401 static void
10402 nlprompt(void)
10403 {
10404         g_parsefile->linno++;
10405         setprompt_if(doprompt, 2);
10406 }
10407 static void
10408 nlnoprompt(void)
10409 {
10410         g_parsefile->linno++;
10411         needprompt = doprompt;
10412 }
10413
10414 static int
10415 pgetc(void)
10416 {
10417         int c;
10418
10419         pgetc_debug("pgetc at %d:%p'%s'",
10420                         g_parsefile->left_in_line,
10421                         g_parsefile->next_to_pgetc,
10422                         g_parsefile->next_to_pgetc);
10423         if (g_parsefile->unget)
10424                 return g_parsefile->lastc[--g_parsefile->unget];
10425
10426         if (--g_parsefile->left_in_line >= 0)
10427                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10428         else
10429                 c = preadbuffer();
10430
10431         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10432         g_parsefile->lastc[0] = c;
10433
10434         return c;
10435 }
10436
10437 #if ENABLE_ASH_ALIAS
10438 static int
10439 pgetc_without_PEOA(void)
10440 {
10441         int c;
10442         do {
10443                 pgetc_debug("pgetc at %d:%p'%s'",
10444                                 g_parsefile->left_in_line,
10445                                 g_parsefile->next_to_pgetc,
10446                                 g_parsefile->next_to_pgetc);
10447                 c = pgetc();
10448         } while (c == PEOA);
10449         return c;
10450 }
10451 #else
10452 # define pgetc_without_PEOA() pgetc()
10453 #endif
10454
10455 /*
10456  * Undo a call to pgetc.  Only two characters may be pushed back.
10457  * PEOF may be pushed back.
10458  */
10459 static void
10460 pungetc(void)
10461 {
10462         g_parsefile->unget++;
10463 }
10464
10465 /* This one eats backslash+newline */
10466 static int
10467 pgetc_eatbnl(void)
10468 {
10469         int c;
10470
10471         while ((c = pgetc()) == '\\') {
10472                 if (pgetc() != '\n') {
10473                         pungetc();
10474                         break;
10475                 }
10476
10477                 nlprompt();
10478         }
10479
10480         return c;
10481 }
10482
10483 /*
10484  * To handle the "." command, a stack of input files is used.  Pushfile
10485  * adds a new entry to the stack and popfile restores the previous level.
10486  */
10487 static void
10488 pushfile(void)
10489 {
10490         struct parsefile *pf;
10491
10492         pf = ckzalloc(sizeof(*pf));
10493         pf->prev = g_parsefile;
10494         pf->pf_fd = -1;
10495         /*pf->strpush = NULL; - ckzalloc did it */
10496         /*pf->basestrpush.prev = NULL;*/
10497         /*pf->unget = 0;*/
10498         g_parsefile = pf;
10499 }
10500
10501 static void
10502 popfile(void)
10503 {
10504         struct parsefile *pf = g_parsefile;
10505
10506         if (pf == &basepf)
10507                 return;
10508
10509         INT_OFF;
10510         if (pf->pf_fd >= 0)
10511                 close(pf->pf_fd);
10512         free(pf->buf);
10513         while (pf->strpush)
10514                 popstring();
10515         g_parsefile = pf->prev;
10516         free(pf);
10517         INT_ON;
10518 }
10519
10520 /*
10521  * Return to top level.
10522  */
10523 static void
10524 popallfiles(void)
10525 {
10526         while (g_parsefile != &basepf)
10527                 popfile();
10528 }
10529
10530 /*
10531  * Close the file(s) that the shell is reading commands from.  Called
10532  * after a fork is done.
10533  */
10534 static void
10535 closescript(void)
10536 {
10537         popallfiles();
10538         if (g_parsefile->pf_fd > 0) {
10539                 close(g_parsefile->pf_fd);
10540                 g_parsefile->pf_fd = 0;
10541         }
10542 }
10543
10544 /*
10545  * Like setinputfile, but takes an open file descriptor.  Call this with
10546  * interrupts off.
10547  */
10548 static void
10549 setinputfd(int fd, int push)
10550 {
10551         if (push) {
10552                 pushfile();
10553                 g_parsefile->buf = NULL;
10554         }
10555         g_parsefile->pf_fd = fd;
10556         if (g_parsefile->buf == NULL)
10557                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10558         g_parsefile->left_in_buffer = 0;
10559         g_parsefile->left_in_line = 0;
10560         g_parsefile->linno = 1;
10561 }
10562
10563 /*
10564  * Set the input to take input from a file.  If push is set, push the
10565  * old input onto the stack first.
10566  */
10567 static int
10568 setinputfile(const char *fname, int flags)
10569 {
10570         int fd;
10571
10572         INT_OFF;
10573         fd = open(fname, O_RDONLY);
10574         if (fd < 0) {
10575                 if (flags & INPUT_NOFILE_OK)
10576                         goto out;
10577                 exitstatus = 127;
10578                 ash_msg_and_raise_error("can't open '%s'", fname);
10579         }
10580         if (fd < 10)
10581                 fd = savefd(fd);
10582         else
10583                 close_on_exec_on(fd);
10584         setinputfd(fd, flags & INPUT_PUSH_FILE);
10585  out:
10586         INT_ON;
10587         return fd;
10588 }
10589
10590 /*
10591  * Like setinputfile, but takes input from a string.
10592  */
10593 static void
10594 setinputstring(char *string)
10595 {
10596         INT_OFF;
10597         pushfile();
10598         g_parsefile->next_to_pgetc = string;
10599         g_parsefile->left_in_line = strlen(string);
10600         g_parsefile->buf = NULL;
10601         g_parsefile->linno = 1;
10602         INT_ON;
10603 }
10604
10605
10606 /*
10607  * Routines to check for mail.
10608  */
10609
10610 #if ENABLE_ASH_MAIL
10611
10612 /* Hash of mtimes of mailboxes */
10613 static unsigned mailtime_hash;
10614 /* Set if MAIL or MAILPATH is changed. */
10615 static smallint mail_var_path_changed;
10616
10617 /*
10618  * Print appropriate message(s) if mail has arrived.
10619  * If mail_var_path_changed is set,
10620  * then the value of MAIL has mail_var_path_changed,
10621  * so we just update the values.
10622  */
10623 static void
10624 chkmail(void)
10625 {
10626         const char *mpath;
10627         char *p;
10628         char *q;
10629         unsigned new_hash;
10630         struct stackmark smark;
10631         struct stat statb;
10632
10633         setstackmark(&smark);
10634         mpath = mpathset() ? mpathval() : mailval();
10635         new_hash = 0;
10636         for (;;) {
10637                 p = path_advance(&mpath, nullstr);
10638                 if (p == NULL)
10639                         break;
10640                 if (*p == '\0')
10641                         continue;
10642                 for (q = p; *q; q++)
10643                         continue;
10644 #if DEBUG
10645                 if (q[-1] != '/')
10646                         abort();
10647 #endif
10648                 q[-1] = '\0';                   /* delete trailing '/' */
10649                 if (stat(p, &statb) < 0) {
10650                         continue;
10651                 }
10652                 /* Very simplistic "hash": just a sum of all mtimes */
10653                 new_hash += (unsigned)statb.st_mtime;
10654         }
10655         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10656                 if (mailtime_hash != 0)
10657                         out2str("you have mail\n");
10658                 mailtime_hash = new_hash;
10659         }
10660         mail_var_path_changed = 0;
10661         popstackmark(&smark);
10662 }
10663
10664 static void FAST_FUNC
10665 changemail(const char *val UNUSED_PARAM)
10666 {
10667         mail_var_path_changed = 1;
10668 }
10669
10670 #endif /* ASH_MAIL */
10671
10672
10673 /* ============ ??? */
10674
10675 /*
10676  * Set the shell parameters.
10677  */
10678 static void
10679 setparam(char **argv)
10680 {
10681         char **newparam;
10682         char **ap;
10683         int nparam;
10684
10685         for (nparam = 0; argv[nparam]; nparam++)
10686                 continue;
10687         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10688         while (*argv) {
10689                 *ap++ = ckstrdup(*argv++);
10690         }
10691         *ap = NULL;
10692         freeparam(&shellparam);
10693         shellparam.malloced = 1;
10694         shellparam.nparam = nparam;
10695         shellparam.p = newparam;
10696 #if ENABLE_ASH_GETOPTS
10697         shellparam.optind = 1;
10698         shellparam.optoff = -1;
10699 #endif
10700 }
10701
10702 /*
10703  * Process shell options.  The global variable argptr contains a pointer
10704  * to the argument list; we advance it past the options.
10705  *
10706  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10707  * For a non-interactive shell, an error condition encountered
10708  * by a special built-in ... shall cause the shell to write a diagnostic message
10709  * to standard error and exit as shown in the following table:
10710  * Error                                           Special Built-In
10711  * ...
10712  * Utility syntax error (option or operand error)  Shall exit
10713  * ...
10714  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10715  * we see that bash does not do that (set "finishes" with error code 1 instead,
10716  * and shell continues), and people rely on this behavior!
10717  * Testcase:
10718  * set -o barfoo 2>/dev/null
10719  * echo $?
10720  *
10721  * Oh well. Let's mimic that.
10722  */
10723 static int
10724 plus_minus_o(char *name, int val)
10725 {
10726         int i;
10727
10728         if (name) {
10729                 for (i = 0; i < NOPTS; i++) {
10730                         if (strcmp(name, optnames(i)) == 0) {
10731                                 optlist[i] = val;
10732                                 return 0;
10733                         }
10734                 }
10735                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10736                 return 1;
10737         }
10738         for (i = 0; i < NOPTS; i++) {
10739                 if (val) {
10740                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10741                 } else {
10742                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10743                 }
10744         }
10745         return 0;
10746 }
10747 static void
10748 setoption(int flag, int val)
10749 {
10750         int i;
10751
10752         for (i = 0; i < NOPTS; i++) {
10753                 if (optletters(i) == flag) {
10754                         optlist[i] = val;
10755                         return;
10756                 }
10757         }
10758         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10759         /* NOTREACHED */
10760 }
10761 static int
10762 options(int cmdline, int *login_sh)
10763 {
10764         char *p;
10765         int val;
10766         int c;
10767
10768         if (cmdline)
10769                 minusc = NULL;
10770         while ((p = *argptr) != NULL) {
10771                 c = *p++;
10772                 if (c != '-' && c != '+')
10773                         break;
10774                 argptr++;
10775                 val = 0; /* val = 0 if c == '+' */
10776                 if (c == '-') {
10777                         val = 1;
10778                         if (p[0] == '\0' || LONE_DASH(p)) {
10779                                 if (!cmdline) {
10780                                         /* "-" means turn off -x and -v */
10781                                         if (p[0] == '\0')
10782                                                 xflag = vflag = 0;
10783                                         /* "--" means reset params */
10784                                         else if (*argptr == NULL)
10785                                                 setparam(argptr);
10786                                 }
10787                                 break;    /* "-" or "--" terminates options */
10788                         }
10789                 }
10790                 /* first char was + or - */
10791                 while ((c = *p++) != '\0') {
10792                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10793                         if (c == 'c' && cmdline) {
10794                                 minusc = p;     /* command is after shell args */
10795                         } else if (c == 'o') {
10796                                 if (plus_minus_o(*argptr, val)) {
10797                                         /* it already printed err message */
10798                                         return 1; /* error */
10799                                 }
10800                                 if (*argptr)
10801                                         argptr++;
10802                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10803                                 if (login_sh)
10804                                         *login_sh = 1;
10805                         /* bash does not accept +-login, we also won't */
10806                         } else if (cmdline && val && (c == '-')) { /* long options */
10807                                 if (strcmp(p, "login") == 0) {
10808                                         if (login_sh)
10809                                                 *login_sh = 1;
10810                                 }
10811                                 break;
10812                         } else {
10813                                 setoption(c, val);
10814                         }
10815                 }
10816         }
10817         return 0;
10818 }
10819
10820 /*
10821  * The shift builtin command.
10822  */
10823 static int FAST_FUNC
10824 shiftcmd(int argc UNUSED_PARAM, char **argv)
10825 {
10826         int n;
10827         char **ap1, **ap2;
10828
10829         n = 1;
10830         if (argv[1])
10831                 n = number(argv[1]);
10832         if (n > shellparam.nparam)
10833                 n = 0; /* bash compat, was = shellparam.nparam; */
10834         INT_OFF;
10835         shellparam.nparam -= n;
10836         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10837                 if (shellparam.malloced)
10838                         free(*ap1);
10839         }
10840         ap2 = shellparam.p;
10841         while ((*ap2++ = *ap1++) != NULL)
10842                 continue;
10843 #if ENABLE_ASH_GETOPTS
10844         shellparam.optind = 1;
10845         shellparam.optoff = -1;
10846 #endif
10847         INT_ON;
10848         return 0;
10849 }
10850
10851 /*
10852  * POSIX requires that 'set' (but not export or readonly) output the
10853  * variables in lexicographic order - by the locale's collating order (sigh).
10854  * Maybe we could keep them in an ordered balanced binary tree
10855  * instead of hashed lists.
10856  * For now just roll 'em through qsort for printing...
10857  */
10858 static int
10859 showvars(const char *sep_prefix, int on, int off)
10860 {
10861         const char *sep;
10862         char **ep, **epend;
10863
10864         ep = listvars(on, off, &epend);
10865         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10866
10867         sep = *sep_prefix ? " " : sep_prefix;
10868
10869         for (; ep < epend; ep++) {
10870                 const char *p;
10871                 const char *q;
10872
10873                 p = strchrnul(*ep, '=');
10874                 q = nullstr;
10875                 if (*p)
10876                         q = single_quote(++p);
10877                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10878         }
10879         return 0;
10880 }
10881
10882 /*
10883  * The set command builtin.
10884  */
10885 static int FAST_FUNC
10886 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10887 {
10888         int retval;
10889
10890         if (!argv[1])
10891                 return showvars(nullstr, 0, VUNSET);
10892
10893         INT_OFF;
10894         retval = options(/*cmdline:*/ 0, NULL);
10895         if (retval == 0) { /* if no parse error... */
10896                 optschanged();
10897                 if (*argptr != NULL) {
10898                         setparam(argptr);
10899                 }
10900         }
10901         INT_ON;
10902         return retval;
10903 }
10904
10905 #if ENABLE_ASH_RANDOM_SUPPORT
10906 static void FAST_FUNC
10907 change_random(const char *value)
10908 {
10909         uint32_t t;
10910
10911         if (value == NULL) {
10912                 /* "get", generate */
10913                 t = next_random(&random_gen);
10914                 /* set without recursion */
10915                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10916                 vrandom.flags &= ~VNOFUNC;
10917         } else {
10918                 /* set/reset */
10919                 t = strtoul(value, NULL, 10);
10920                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10921         }
10922 }
10923 #endif
10924
10925 #if ENABLE_ASH_GETOPTS
10926 static int
10927 getopts(char *optstr, char *optvar, char **optfirst)
10928 {
10929         char *p, *q;
10930         char c = '?';
10931         int done = 0;
10932         char sbuf[2];
10933         char **optnext;
10934         int ind = shellparam.optind;
10935         int off = shellparam.optoff;
10936
10937         sbuf[1] = '\0';
10938
10939         shellparam.optind = -1;
10940         optnext = optfirst + ind - 1;
10941
10942         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10943                 p = NULL;
10944         else
10945                 p = optnext[-1] + off;
10946         if (p == NULL || *p == '\0') {
10947                 /* Current word is done, advance */
10948                 p = *optnext;
10949                 if (p == NULL || *p != '-' || *++p == '\0') {
10950  atend:
10951                         p = NULL;
10952                         done = 1;
10953                         goto out;
10954                 }
10955                 optnext++;
10956                 if (LONE_DASH(p))        /* check for "--" */
10957                         goto atend;
10958         }
10959
10960         c = *p++;
10961         for (q = optstr; *q != c;) {
10962                 if (*q == '\0') {
10963                         if (optstr[0] == ':') {
10964                                 sbuf[0] = c;
10965                                 /*sbuf[1] = '\0'; - already is */
10966                                 setvar0("OPTARG", sbuf);
10967                         } else {
10968                                 fprintf(stderr, "Illegal option -%c\n", c);
10969                                 unsetvar("OPTARG");
10970                         }
10971                         c = '?';
10972                         goto out;
10973                 }
10974                 if (*++q == ':')
10975                         q++;
10976         }
10977
10978         if (*++q == ':') {
10979                 if (*p == '\0' && (p = *optnext) == NULL) {
10980                         if (optstr[0] == ':') {
10981                                 sbuf[0] = c;
10982                                 /*sbuf[1] = '\0'; - already is */
10983                                 setvar0("OPTARG", sbuf);
10984                                 c = ':';
10985                         } else {
10986                                 fprintf(stderr, "No arg for -%c option\n", c);
10987                                 unsetvar("OPTARG");
10988                                 c = '?';
10989                         }
10990                         goto out;
10991                 }
10992
10993                 if (p == *optnext)
10994                         optnext++;
10995                 setvar0("OPTARG", p);
10996                 p = NULL;
10997         } else
10998                 setvar0("OPTARG", nullstr);
10999  out:
11000         ind = optnext - optfirst + 1;
11001         setvar("OPTIND", itoa(ind), VNOFUNC);
11002         sbuf[0] = c;
11003         /*sbuf[1] = '\0'; - already is */
11004         setvar0(optvar, sbuf);
11005
11006         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11007         shellparam.optind = ind;
11008
11009         return done;
11010 }
11011
11012 /*
11013  * The getopts builtin.  Shellparam.optnext points to the next argument
11014  * to be processed.  Shellparam.optptr points to the next character to
11015  * be processed in the current argument.  If shellparam.optnext is NULL,
11016  * then it's the first time getopts has been called.
11017  */
11018 static int FAST_FUNC
11019 getoptscmd(int argc, char **argv)
11020 {
11021         char **optbase;
11022
11023         if (argc < 3)
11024                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11025         if (argc == 3) {
11026                 optbase = shellparam.p;
11027                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11028                         shellparam.optind = 1;
11029                         shellparam.optoff = -1;
11030                 }
11031         } else {
11032                 optbase = &argv[3];
11033                 if ((unsigned)shellparam.optind > argc - 2) {
11034                         shellparam.optind = 1;
11035                         shellparam.optoff = -1;
11036                 }
11037         }
11038
11039         return getopts(argv[1], argv[2], optbase);
11040 }
11041 #endif /* ASH_GETOPTS */
11042
11043
11044 /* ============ Shell parser */
11045
11046 struct heredoc {
11047         struct heredoc *next;   /* next here document in list */
11048         union node *here;       /* redirection node */
11049         char *eofmark;          /* string indicating end of input */
11050         smallint striptabs;     /* if set, strip leading tabs */
11051 };
11052
11053 static smallint tokpushback;           /* last token pushed back */
11054 static smallint quoteflag;             /* set if (part of) last token was quoted */
11055 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11056 static struct heredoc *heredoclist;    /* list of here documents to read */
11057 static char *wordtext;                 /* text of last word returned by readtoken */
11058 static struct nodelist *backquotelist;
11059 static union node *redirnode;
11060 static struct heredoc *heredoc;
11061
11062 static const char *
11063 tokname(char *buf, int tok)
11064 {
11065         if (tok < TSEMI)
11066                 return tokname_array[tok];
11067         sprintf(buf, "\"%s\"", tokname_array[tok]);
11068         return buf;
11069 }
11070
11071 /* raise_error_unexpected_syntax:
11072  * Called when an unexpected token is read during the parse.  The argument
11073  * is the token that is expected, or -1 if more than one type of token can
11074  * occur at this point.
11075  */
11076 static void raise_error_unexpected_syntax(int) NORETURN;
11077 static void
11078 raise_error_unexpected_syntax(int token)
11079 {
11080         char msg[64];
11081         char buf[16];
11082         int l;
11083
11084         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11085         if (token >= 0)
11086                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11087         raise_error_syntax(msg);
11088         /* NOTREACHED */
11089 }
11090
11091 /* parsing is heavily cross-recursive, need these forward decls */
11092 static union node *andor(void);
11093 static union node *pipeline(void);
11094 static union node *parse_command(void);
11095 static void parseheredoc(void);
11096 static int peektoken(void);
11097 static int readtoken(void);
11098
11099 static union node *
11100 list(int nlflag)
11101 {
11102         union node *n1, *n2, *n3;
11103         int tok;
11104
11105         n1 = NULL;
11106         for (;;) {
11107                 switch (peektoken()) {
11108                 case TNL:
11109                         if (!(nlflag & 1))
11110                                 break;
11111                         parseheredoc();
11112                         return n1;
11113
11114                 case TEOF:
11115                         if (!n1 && (nlflag & 1))
11116                                 n1 = NODE_EOF;
11117                         parseheredoc();
11118                         return n1;
11119                 }
11120
11121                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11122                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11123                         return n1;
11124                 nlflag |= 2;
11125
11126                 n2 = andor();
11127                 tok = readtoken();
11128                 if (tok == TBACKGND) {
11129                         if (n2->type == NPIPE) {
11130                                 n2->npipe.pipe_backgnd = 1;
11131                         } else {
11132                                 if (n2->type != NREDIR) {
11133                                         n3 = stzalloc(sizeof(struct nredir));
11134                                         n3->nredir.n = n2;
11135                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11136                                         n2 = n3;
11137                                 }
11138                                 n2->type = NBACKGND;
11139                         }
11140                 }
11141                 if (n1 == NULL) {
11142                         n1 = n2;
11143                 } else {
11144                         n3 = stzalloc(sizeof(struct nbinary));
11145                         n3->type = NSEMI;
11146                         n3->nbinary.ch1 = n1;
11147                         n3->nbinary.ch2 = n2;
11148                         n1 = n3;
11149                 }
11150                 switch (tok) {
11151                 case TNL:
11152                 case TEOF:
11153                         tokpushback = 1;
11154                         /* fall through */
11155                 case TBACKGND:
11156                 case TSEMI:
11157                         break;
11158                 default:
11159                         if ((nlflag & 1))
11160                                 raise_error_unexpected_syntax(-1);
11161                         tokpushback = 1;
11162                         return n1;
11163                 }
11164         }
11165 }
11166
11167 static union node *
11168 andor(void)
11169 {
11170         union node *n1, *n2, *n3;
11171         int t;
11172
11173         n1 = pipeline();
11174         for (;;) {
11175                 t = readtoken();
11176                 if (t == TAND) {
11177                         t = NAND;
11178                 } else if (t == TOR) {
11179                         t = NOR;
11180                 } else {
11181                         tokpushback = 1;
11182                         return n1;
11183                 }
11184                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11185                 n2 = pipeline();
11186                 n3 = stzalloc(sizeof(struct nbinary));
11187                 n3->type = t;
11188                 n3->nbinary.ch1 = n1;
11189                 n3->nbinary.ch2 = n2;
11190                 n1 = n3;
11191         }
11192 }
11193
11194 static union node *
11195 pipeline(void)
11196 {
11197         union node *n1, *n2, *pipenode;
11198         struct nodelist *lp, *prev;
11199         int negate;
11200
11201         negate = 0;
11202         TRACE(("pipeline: entered\n"));
11203         if (readtoken() == TNOT) {
11204                 negate = !negate;
11205                 checkkwd = CHKKWD | CHKALIAS;
11206         } else
11207                 tokpushback = 1;
11208         n1 = parse_command();
11209         if (readtoken() == TPIPE) {
11210                 pipenode = stzalloc(sizeof(struct npipe));
11211                 pipenode->type = NPIPE;
11212                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11213                 lp = stzalloc(sizeof(struct nodelist));
11214                 pipenode->npipe.cmdlist = lp;
11215                 lp->n = n1;
11216                 do {
11217                         prev = lp;
11218                         lp = stzalloc(sizeof(struct nodelist));
11219                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11220                         lp->n = parse_command();
11221                         prev->next = lp;
11222                 } while (readtoken() == TPIPE);
11223                 lp->next = NULL;
11224                 n1 = pipenode;
11225         }
11226         tokpushback = 1;
11227         if (negate) {
11228                 n2 = stzalloc(sizeof(struct nnot));
11229                 n2->type = NNOT;
11230                 n2->nnot.com = n1;
11231                 return n2;
11232         }
11233         return n1;
11234 }
11235
11236 static union node *
11237 makename(void)
11238 {
11239         union node *n;
11240
11241         n = stzalloc(sizeof(struct narg));
11242         n->type = NARG;
11243         /*n->narg.next = NULL; - stzalloc did it */
11244         n->narg.text = wordtext;
11245         n->narg.backquote = backquotelist;
11246         return n;
11247 }
11248
11249 static void
11250 fixredir(union node *n, const char *text, int err)
11251 {
11252         int fd;
11253
11254         TRACE(("Fix redir %s %d\n", text, err));
11255         if (!err)
11256                 n->ndup.vname = NULL;
11257
11258         fd = bb_strtou(text, NULL, 10);
11259         if (!errno && fd >= 0)
11260                 n->ndup.dupfd = fd;
11261         else if (LONE_DASH(text))
11262                 n->ndup.dupfd = -1;
11263         else {
11264                 if (err)
11265                         raise_error_syntax("bad fd number");
11266                 n->ndup.vname = makename();
11267         }
11268 }
11269
11270 static void
11271 parsefname(void)
11272 {
11273         union node *n = redirnode;
11274
11275         if (n->type == NHERE)
11276                 checkkwd = CHKEOFMARK;
11277         if (readtoken() != TWORD)
11278                 raise_error_unexpected_syntax(-1);
11279         if (n->type == NHERE) {
11280                 struct heredoc *here = heredoc;
11281                 struct heredoc *p;
11282
11283                 if (quoteflag == 0)
11284                         n->type = NXHERE;
11285                 TRACE(("Here document %d\n", n->type));
11286                 rmescapes(wordtext, 0);
11287                 here->eofmark = wordtext;
11288                 here->next = NULL;
11289                 if (heredoclist == NULL)
11290                         heredoclist = here;
11291                 else {
11292                         for (p = heredoclist; p->next; p = p->next)
11293                                 continue;
11294                         p->next = here;
11295                 }
11296         } else if (n->type == NTOFD || n->type == NFROMFD) {
11297                 fixredir(n, wordtext, 0);
11298         } else {
11299                 n->nfile.fname = makename();
11300         }
11301 }
11302
11303 static union node *
11304 simplecmd(void)
11305 {
11306         union node *args, **app;
11307         union node *n = NULL;
11308         union node *vars, **vpp;
11309         union node **rpp, *redir;
11310         int savecheckkwd;
11311 #if BASH_TEST2
11312         smallint double_brackets_flag = 0;
11313 #endif
11314         IF_BASH_FUNCTION(smallint function_flag = 0;)
11315
11316         args = NULL;
11317         app = &args;
11318         vars = NULL;
11319         vpp = &vars;
11320         redir = NULL;
11321         rpp = &redir;
11322
11323         savecheckkwd = CHKALIAS;
11324         for (;;) {
11325                 int t;
11326                 checkkwd = savecheckkwd;
11327                 t = readtoken();
11328                 switch (t) {
11329 #if BASH_FUNCTION
11330                 case TFUNCTION:
11331                         if (peektoken() != TWORD)
11332                                 raise_error_unexpected_syntax(TWORD);
11333                         function_flag = 1;
11334                         break;
11335 #endif
11336 #if BASH_TEST2
11337                 case TAND: /* "&&" */
11338                 case TOR: /* "||" */
11339                         if (!double_brackets_flag) {
11340                                 tokpushback = 1;
11341                                 goto out;
11342                         }
11343                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11344 #endif
11345                 case TWORD:
11346                         n = stzalloc(sizeof(struct narg));
11347                         n->type = NARG;
11348                         /*n->narg.next = NULL; - stzalloc did it */
11349                         n->narg.text = wordtext;
11350 #if BASH_TEST2
11351                         if (strcmp("[[", wordtext) == 0)
11352                                 double_brackets_flag = 1;
11353                         else if (strcmp("]]", wordtext) == 0)
11354                                 double_brackets_flag = 0;
11355 #endif
11356                         n->narg.backquote = backquotelist;
11357                         if (savecheckkwd && isassignment(wordtext)) {
11358                                 *vpp = n;
11359                                 vpp = &n->narg.next;
11360                         } else {
11361                                 *app = n;
11362                                 app = &n->narg.next;
11363                                 savecheckkwd = 0;
11364                         }
11365 #if BASH_FUNCTION
11366                         if (function_flag) {
11367                                 checkkwd = CHKNL | CHKKWD;
11368                                 switch (peektoken()) {
11369                                 case TBEGIN:
11370                                 case TIF:
11371                                 case TCASE:
11372                                 case TUNTIL:
11373                                 case TWHILE:
11374                                 case TFOR:
11375                                         goto do_func;
11376                                 case TLP:
11377                                         function_flag = 0;
11378                                         break;
11379                                 case TWORD:
11380                                         if (strcmp("[[", wordtext) == 0)
11381                                                 goto do_func;
11382                                         /* fall through */
11383                                 default:
11384                                         raise_error_unexpected_syntax(-1);
11385                                 }
11386                         }
11387 #endif
11388                         break;
11389                 case TREDIR:
11390                         *rpp = n = redirnode;
11391                         rpp = &n->nfile.next;
11392                         parsefname();   /* read name of redirection file */
11393                         break;
11394                 case TLP:
11395  IF_BASH_FUNCTION(do_func:)
11396                         if (args && app == &args->narg.next
11397                          && !vars && !redir
11398                         ) {
11399                                 struct builtincmd *bcmd;
11400                                 const char *name;
11401
11402                                 /* We have a function */
11403                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11404                                         raise_error_unexpected_syntax(TRP);
11405                                 name = n->narg.text;
11406                                 if (!goodname(name)
11407                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11408                                 ) {
11409                                         raise_error_syntax("bad function name");
11410                                 }
11411                                 n->type = NDEFUN;
11412                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11413                                 n->narg.next = parse_command();
11414                                 return n;
11415                         }
11416                         IF_BASH_FUNCTION(function_flag = 0;)
11417                         /* fall through */
11418                 default:
11419                         tokpushback = 1;
11420                         goto out;
11421                 }
11422         }
11423  out:
11424         *app = NULL;
11425         *vpp = NULL;
11426         *rpp = NULL;
11427         n = stzalloc(sizeof(struct ncmd));
11428         n->type = NCMD;
11429         n->ncmd.args = args;
11430         n->ncmd.assign = vars;
11431         n->ncmd.redirect = redir;
11432         return n;
11433 }
11434
11435 static union node *
11436 parse_command(void)
11437 {
11438         union node *n1, *n2;
11439         union node *ap, **app;
11440         union node *cp, **cpp;
11441         union node *redir, **rpp;
11442         union node **rpp2;
11443         int t;
11444
11445         redir = NULL;
11446         rpp2 = &redir;
11447
11448         switch (readtoken()) {
11449         default:
11450                 raise_error_unexpected_syntax(-1);
11451                 /* NOTREACHED */
11452         case TIF:
11453                 n1 = stzalloc(sizeof(struct nif));
11454                 n1->type = NIF;
11455                 n1->nif.test = list(0);
11456                 if (readtoken() != TTHEN)
11457                         raise_error_unexpected_syntax(TTHEN);
11458                 n1->nif.ifpart = list(0);
11459                 n2 = n1;
11460                 while (readtoken() == TELIF) {
11461                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11462                         n2 = n2->nif.elsepart;
11463                         n2->type = NIF;
11464                         n2->nif.test = list(0);
11465                         if (readtoken() != TTHEN)
11466                                 raise_error_unexpected_syntax(TTHEN);
11467                         n2->nif.ifpart = list(0);
11468                 }
11469                 if (lasttoken == TELSE)
11470                         n2->nif.elsepart = list(0);
11471                 else {
11472                         n2->nif.elsepart = NULL;
11473                         tokpushback = 1;
11474                 }
11475                 t = TFI;
11476                 break;
11477         case TWHILE:
11478         case TUNTIL: {
11479                 int got;
11480                 n1 = stzalloc(sizeof(struct nbinary));
11481                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11482                 n1->nbinary.ch1 = list(0);
11483                 got = readtoken();
11484                 if (got != TDO) {
11485                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11486                                         got == TWORD ? wordtext : ""));
11487                         raise_error_unexpected_syntax(TDO);
11488                 }
11489                 n1->nbinary.ch2 = list(0);
11490                 t = TDONE;
11491                 break;
11492         }
11493         case TFOR:
11494                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11495                         raise_error_syntax("bad for loop variable");
11496                 n1 = stzalloc(sizeof(struct nfor));
11497                 n1->type = NFOR;
11498                 n1->nfor.var = wordtext;
11499                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11500                 if (readtoken() == TIN) {
11501                         app = &ap;
11502                         while (readtoken() == TWORD) {
11503                                 n2 = stzalloc(sizeof(struct narg));
11504                                 n2->type = NARG;
11505                                 /*n2->narg.next = NULL; - stzalloc did it */
11506                                 n2->narg.text = wordtext;
11507                                 n2->narg.backquote = backquotelist;
11508                                 *app = n2;
11509                                 app = &n2->narg.next;
11510                         }
11511                         *app = NULL;
11512                         n1->nfor.args = ap;
11513                         if (lasttoken != TNL && lasttoken != TSEMI)
11514                                 raise_error_unexpected_syntax(-1);
11515                 } else {
11516                         n2 = stzalloc(sizeof(struct narg));
11517                         n2->type = NARG;
11518                         /*n2->narg.next = NULL; - stzalloc did it */
11519                         n2->narg.text = (char *)dolatstr;
11520                         /*n2->narg.backquote = NULL;*/
11521                         n1->nfor.args = n2;
11522                         /*
11523                          * Newline or semicolon here is optional (but note
11524                          * that the original Bourne shell only allowed NL).
11525                          */
11526                         if (lasttoken != TSEMI)
11527                                 tokpushback = 1;
11528                 }
11529                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11530                 if (readtoken() != TDO)
11531                         raise_error_unexpected_syntax(TDO);
11532                 n1->nfor.body = list(0);
11533                 t = TDONE;
11534                 break;
11535         case TCASE:
11536                 n1 = stzalloc(sizeof(struct ncase));
11537                 n1->type = NCASE;
11538                 if (readtoken() != TWORD)
11539                         raise_error_unexpected_syntax(TWORD);
11540                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11541                 n2->type = NARG;
11542                 /*n2->narg.next = NULL; - stzalloc did it */
11543                 n2->narg.text = wordtext;
11544                 n2->narg.backquote = backquotelist;
11545                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11546                 if (readtoken() != TIN)
11547                         raise_error_unexpected_syntax(TIN);
11548                 cpp = &n1->ncase.cases;
11549  next_case:
11550                 checkkwd = CHKNL | CHKKWD;
11551                 t = readtoken();
11552                 while (t != TESAC) {
11553                         if (lasttoken == TLP)
11554                                 readtoken();
11555                         *cpp = cp = stzalloc(sizeof(struct nclist));
11556                         cp->type = NCLIST;
11557                         app = &cp->nclist.pattern;
11558                         for (;;) {
11559                                 *app = ap = stzalloc(sizeof(struct narg));
11560                                 ap->type = NARG;
11561                                 /*ap->narg.next = NULL; - stzalloc did it */
11562                                 ap->narg.text = wordtext;
11563                                 ap->narg.backquote = backquotelist;
11564                                 if (readtoken() != TPIPE)
11565                                         break;
11566                                 app = &ap->narg.next;
11567                                 readtoken();
11568                         }
11569                         //ap->narg.next = NULL;
11570                         if (lasttoken != TRP)
11571                                 raise_error_unexpected_syntax(TRP);
11572                         cp->nclist.body = list(2);
11573
11574                         cpp = &cp->nclist.next;
11575
11576                         checkkwd = CHKNL | CHKKWD;
11577                         t = readtoken();
11578                         if (t != TESAC) {
11579                                 if (t != TENDCASE)
11580                                         raise_error_unexpected_syntax(TENDCASE);
11581                                 goto next_case;
11582                         }
11583                 }
11584                 *cpp = NULL;
11585                 goto redir;
11586         case TLP:
11587                 n1 = stzalloc(sizeof(struct nredir));
11588                 n1->type = NSUBSHELL;
11589                 n1->nredir.n = list(0);
11590                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11591                 t = TRP;
11592                 break;
11593         case TBEGIN:
11594                 n1 = list(0);
11595                 t = TEND;
11596                 break;
11597         IF_BASH_FUNCTION(case TFUNCTION:)
11598         case TWORD:
11599         case TREDIR:
11600                 tokpushback = 1;
11601                 return simplecmd();
11602         }
11603
11604         if (readtoken() != t)
11605                 raise_error_unexpected_syntax(t);
11606
11607  redir:
11608         /* Now check for redirection which may follow command */
11609         checkkwd = CHKKWD | CHKALIAS;
11610         rpp = rpp2;
11611         while (readtoken() == TREDIR) {
11612                 *rpp = n2 = redirnode;
11613                 rpp = &n2->nfile.next;
11614                 parsefname();
11615         }
11616         tokpushback = 1;
11617         *rpp = NULL;
11618         if (redir) {
11619                 if (n1->type != NSUBSHELL) {
11620                         n2 = stzalloc(sizeof(struct nredir));
11621                         n2->type = NREDIR;
11622                         n2->nredir.n = n1;
11623                         n1 = n2;
11624                 }
11625                 n1->nredir.redirect = redir;
11626         }
11627         return n1;
11628 }
11629
11630 #if BASH_DOLLAR_SQUOTE
11631 static int
11632 decode_dollar_squote(void)
11633 {
11634         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11635         int c, cnt;
11636         char *p;
11637         char buf[4];
11638
11639         c = pgetc();
11640         p = strchr(C_escapes, c);
11641         if (p) {
11642                 buf[0] = c;
11643                 p = buf;
11644                 cnt = 3;
11645                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11646                         do {
11647                                 c = pgetc();
11648                                 *++p = c;
11649                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11650                         pungetc();
11651                 } else if (c == 'x') { /* \xHH */
11652                         do {
11653                                 c = pgetc();
11654                                 *++p = c;
11655                         } while (isxdigit(c) && --cnt);
11656                         pungetc();
11657                         if (cnt == 3) { /* \x but next char is "bad" */
11658                                 c = 'x';
11659                                 goto unrecognized;
11660                         }
11661                 } else { /* simple seq like \\ or \t */
11662                         p++;
11663                 }
11664                 *p = '\0';
11665                 p = buf;
11666                 c = bb_process_escape_sequence((void*)&p);
11667         } else { /* unrecognized "\z": print both chars unless ' or " */
11668                 if (c != '\'' && c != '"') {
11669  unrecognized:
11670                         c |= 0x100; /* "please encode \, then me" */
11671                 }
11672         }
11673         return c;
11674 }
11675 #endif
11676
11677 /* Used by expandstr to get here-doc like behaviour. */
11678 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11679
11680 static ALWAYS_INLINE int
11681 realeofmark(const char *eofmark)
11682 {
11683         return eofmark && eofmark != FAKEEOFMARK;
11684 }
11685
11686 /*
11687  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11688  * is not NULL, read a here document.  In the latter case, eofmark is the
11689  * word which marks the end of the document and striptabs is true if
11690  * leading tabs should be stripped from the document.  The argument c
11691  * is the first character of the input token or document.
11692  *
11693  * Because C does not have internal subroutines, I have simulated them
11694  * using goto's to implement the subroutine linkage.  The following macros
11695  * will run code that appears at the end of readtoken1.
11696  */
11697 #define CHECKEND()      {goto checkend; checkend_return:;}
11698 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11699 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11700 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11701 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11702 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11703 static int
11704 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11705 {
11706         /* NB: syntax parameter fits into smallint */
11707         /* c parameter is an unsigned char or PEOF or PEOA */
11708         char *out;
11709         size_t len;
11710         struct nodelist *bqlist;
11711         smallint quotef;
11712         smallint dblquote;
11713         smallint oldstyle;
11714         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11715         smallint pssyntax;   /* we are expanding a prompt string */
11716         int varnest;         /* levels of variables expansion */
11717         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11718         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11719         int dqvarnest;       /* levels of variables expansion within double quotes */
11720
11721         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11722
11723         startlinno = g_parsefile->linno;
11724         bqlist = NULL;
11725         quotef = 0;
11726         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11727 #if ENABLE_ASH_EXPAND_PRMT
11728         pssyntax = (syntax == PSSYNTAX);
11729         if (pssyntax)
11730                 syntax = DQSYNTAX;
11731 #else
11732         pssyntax = 0; /* constant */
11733 #endif
11734         dblquote = (syntax == DQSYNTAX);
11735         varnest = 0;
11736         IF_FEATURE_SH_MATH(arinest = 0;)
11737         IF_FEATURE_SH_MATH(parenlevel = 0;)
11738         dqvarnest = 0;
11739
11740         STARTSTACKSTR(out);
11741  loop:
11742         /* For each line, until end of word */
11743         CHECKEND();     /* set c to PEOF if at end of here document */
11744         for (;;) {      /* until end of line or end of word */
11745                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11746                 switch (SIT(c, syntax)) {
11747                 case CNL:       /* '\n' */
11748                         if (syntax == BASESYNTAX)
11749                                 goto endword;   /* exit outer loop */
11750                         USTPUTC(c, out);
11751                         nlprompt();
11752                         c = pgetc();
11753                         goto loop;              /* continue outer loop */
11754                 case CWORD:
11755                         USTPUTC(c, out);
11756                         break;
11757                 case CCTL:
11758 #if BASH_DOLLAR_SQUOTE
11759                         if (c == '\\' && bash_dollar_squote) {
11760                                 c = decode_dollar_squote();
11761                                 if (c == '\0') {
11762                                         /* skip $'\000', $'\x00' (like bash) */
11763                                         break;
11764                                 }
11765                                 if (c & 0x100) {
11766                                         /* Unknown escape. Encode as '\z' */
11767                                         c = (unsigned char)c;
11768                                         if (eofmark == NULL || dblquote)
11769                                                 USTPUTC(CTLESC, out);
11770                                         USTPUTC('\\', out);
11771                                 }
11772                         }
11773 #endif
11774                         if (eofmark == NULL || dblquote)
11775                                 USTPUTC(CTLESC, out);
11776                         USTPUTC(c, out);
11777                         break;
11778                 case CBACK:     /* backslash */
11779                         c = pgetc_without_PEOA();
11780                         if (c == PEOF) {
11781                                 USTPUTC(CTLESC, out);
11782                                 USTPUTC('\\', out);
11783                                 pungetc();
11784                         } else if (c == '\n') {
11785                                 nlprompt();
11786                         } else {
11787                                 if (pssyntax && c == '$') {
11788                                         USTPUTC(CTLESC, out);
11789                                         USTPUTC('\\', out);
11790                                 }
11791                                 /* Backslash is retained if we are in "str" and next char isn't special */
11792                                 if (dblquote
11793                                  && c != '\\'
11794                                  && c != '`'
11795                                  && c != '$'
11796                                  && (c != '"' || eofmark != NULL)
11797                                 ) {
11798                                         USTPUTC('\\', out);
11799                                 }
11800                                 USTPUTC(CTLESC, out);
11801                                 USTPUTC(c, out);
11802                                 quotef = 1;
11803                         }
11804                         break;
11805                 case CSQUOTE:
11806                         syntax = SQSYNTAX;
11807  quotemark:
11808                         if (eofmark == NULL) {
11809                                 USTPUTC(CTLQUOTEMARK, out);
11810                         }
11811                         break;
11812                 case CDQUOTE:
11813                         syntax = DQSYNTAX;
11814                         dblquote = 1;
11815                         goto quotemark;
11816                 case CENDQUOTE:
11817                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11818                         if (eofmark != NULL && varnest == 0) {
11819                                 USTPUTC(c, out);
11820                         } else {
11821                                 if (dqvarnest == 0) {
11822                                         syntax = BASESYNTAX;
11823                                         dblquote = 0;
11824                                 }
11825                                 quotef = 1;
11826                                 goto quotemark;
11827                         }
11828                         break;
11829                 case CVAR:      /* '$' */
11830                         PARSESUB();             /* parse substitution */
11831                         break;
11832                 case CENDVAR:   /* '}' */
11833                         if (varnest > 0) {
11834                                 varnest--;
11835                                 if (dqvarnest > 0) {
11836                                         dqvarnest--;
11837                                 }
11838                                 c = CTLENDVAR;
11839                         }
11840                         USTPUTC(c, out);
11841                         break;
11842 #if ENABLE_FEATURE_SH_MATH
11843                 case CLP:       /* '(' in arithmetic */
11844                         parenlevel++;
11845                         USTPUTC(c, out);
11846                         break;
11847                 case CRP:       /* ')' in arithmetic */
11848                         if (parenlevel > 0) {
11849                                 parenlevel--;
11850                         } else {
11851                                 if (pgetc_eatbnl() == ')') {
11852                                         c = CTLENDARI;
11853                                         if (--arinest == 0) {
11854                                                 syntax = prevsyntax;
11855                                         }
11856                                 } else {
11857                                         /*
11858                                          * unbalanced parens
11859                                          * (don't 2nd guess - no error)
11860                                          */
11861                                         pungetc();
11862                                 }
11863                         }
11864                         USTPUTC(c, out);
11865                         break;
11866 #endif
11867                 case CBQUOTE:   /* '`' */
11868                         PARSEBACKQOLD();
11869                         break;
11870                 case CENDFILE:
11871                         goto endword;           /* exit outer loop */
11872                 case CIGN:
11873                         break;
11874                 default:
11875                         if (varnest == 0) {
11876 #if BASH_REDIR_OUTPUT
11877                                 if (c == '&') {
11878 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11879                                         if (pgetc() == '>')
11880                                                 c = 0x100 + '>'; /* flag &> */
11881                                         pungetc();
11882                                 }
11883 #endif
11884                                 goto endword;   /* exit outer loop */
11885                         }
11886                         IF_ASH_ALIAS(if (c != PEOA))
11887                                 USTPUTC(c, out);
11888                 }
11889                 c = pgetc();
11890         } /* for (;;) */
11891  endword:
11892
11893 #if ENABLE_FEATURE_SH_MATH
11894         if (syntax == ARISYNTAX)
11895                 raise_error_syntax("missing '))'");
11896 #endif
11897         if (syntax != BASESYNTAX && eofmark == NULL)
11898                 raise_error_syntax("unterminated quoted string");
11899         if (varnest != 0) {
11900                 startlinno = g_parsefile->linno;
11901                 /* { */
11902                 raise_error_syntax("missing '}'");
11903         }
11904         USTPUTC('\0', out);
11905         len = out - (char *)stackblock();
11906         out = stackblock();
11907         if (eofmark == NULL) {
11908                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11909                  && quotef == 0
11910                 ) {
11911                         if (isdigit_str9(out)) {
11912                                 PARSEREDIR(); /* passed as params: out, c */
11913                                 lasttoken = TREDIR;
11914                                 return lasttoken;
11915                         }
11916                         /* else: non-number X seen, interpret it
11917                          * as "NNNX>file" = "NNNX >file" */
11918                 }
11919                 pungetc();
11920         }
11921         quoteflag = quotef;
11922         backquotelist = bqlist;
11923         grabstackblock(len);
11924         wordtext = out;
11925         lasttoken = TWORD;
11926         return lasttoken;
11927 /* end of readtoken routine */
11928
11929 /*
11930  * Check to see whether we are at the end of the here document.  When this
11931  * is called, c is set to the first character of the next input line.  If
11932  * we are at the end of the here document, this routine sets the c to PEOF.
11933  */
11934 checkend: {
11935         if (realeofmark(eofmark)) {
11936                 int markloc;
11937                 char *p;
11938
11939 #if ENABLE_ASH_ALIAS
11940                 if (c == PEOA)
11941                         c = pgetc_without_PEOA();
11942 #endif
11943                 if (striptabs) {
11944                         while (c == '\t') {
11945                                 c = pgetc_without_PEOA();
11946                         }
11947                 }
11948
11949                 markloc = out - (char *)stackblock();
11950                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11951                         if (c != *p)
11952                                 goto more_heredoc;
11953
11954                         c = pgetc_without_PEOA();
11955                 }
11956
11957                 if (c == '\n' || c == PEOF) {
11958                         c = PEOF;
11959                         g_parsefile->linno++;
11960                         needprompt = doprompt;
11961                 } else {
11962                         int len_here;
11963
11964  more_heredoc:
11965                         p = (char *)stackblock() + markloc + 1;
11966                         len_here = out - p;
11967
11968                         if (len_here) {
11969                                 len_here -= (c >= PEOF);
11970                                 c = p[-1];
11971
11972                                 if (len_here) {
11973                                         char *str;
11974
11975                                         str = alloca(len_here + 1);
11976                                         *(char *)mempcpy(str, p, len_here) = '\0';
11977
11978                                         pushstring(str, NULL);
11979                                 }
11980                         }
11981                 }
11982
11983                 STADJUST((char *)stackblock() + markloc - out, out);
11984         }
11985         goto checkend_return;
11986 }
11987
11988 /*
11989  * Parse a redirection operator.  The variable "out" points to a string
11990  * specifying the fd to be redirected.  The variable "c" contains the
11991  * first character of the redirection operator.
11992  */
11993 parseredir: {
11994         /* out is already checked to be a valid number or "" */
11995         int fd = (*out == '\0' ? -1 : atoi(out));
11996         union node *np;
11997
11998         np = stzalloc(sizeof(struct nfile));
11999         if (c == '>') {
12000                 np->nfile.fd = 1;
12001                 c = pgetc();
12002                 if (c == '>')
12003                         np->type = NAPPEND;
12004                 else if (c == '|')
12005                         np->type = NCLOBBER;
12006                 else if (c == '&')
12007                         np->type = NTOFD;
12008                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12009                 else {
12010                         np->type = NTO;
12011                         pungetc();
12012                 }
12013         }
12014 #if BASH_REDIR_OUTPUT
12015         else if (c == 0x100 + '>') { /* this flags &> redirection */
12016                 np->nfile.fd = 1;
12017                 pgetc(); /* this is '>', no need to check */
12018                 np->type = NTO2;
12019         }
12020 #endif
12021         else { /* c == '<' */
12022                 /*np->nfile.fd = 0; - stzalloc did it */
12023                 c = pgetc();
12024                 switch (c) {
12025                 case '<':
12026                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12027                                 np = stzalloc(sizeof(struct nhere));
12028                                 /*np->nfile.fd = 0; - stzalloc did it */
12029                         }
12030                         np->type = NHERE;
12031                         heredoc = stzalloc(sizeof(struct heredoc));
12032                         heredoc->here = np;
12033                         c = pgetc();
12034                         if (c == '-') {
12035                                 heredoc->striptabs = 1;
12036                         } else {
12037                                 /*heredoc->striptabs = 0; - stzalloc did it */
12038                                 pungetc();
12039                         }
12040                         break;
12041
12042                 case '&':
12043                         np->type = NFROMFD;
12044                         break;
12045
12046                 case '>':
12047                         np->type = NFROMTO;
12048                         break;
12049
12050                 default:
12051                         np->type = NFROM;
12052                         pungetc();
12053                         break;
12054                 }
12055         }
12056         if (fd >= 0)
12057                 np->nfile.fd = fd;
12058         redirnode = np;
12059         goto parseredir_return;
12060 }
12061
12062 /*
12063  * Parse a substitution.  At this point, we have read the dollar sign
12064  * and nothing else.
12065  */
12066
12067 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12068  * (assuming ascii char codes, as the original implementation did) */
12069 #define is_special(c) \
12070         (((unsigned)(c) - 33 < 32) \
12071                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12072 parsesub: {
12073         unsigned char subtype;
12074         int typeloc;
12075
12076         c = pgetc_eatbnl();
12077         if ((checkkwd & CHKEOFMARK)
12078          || c > 255 /* PEOA or PEOF */
12079          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12080         ) {
12081 #if BASH_DOLLAR_SQUOTE
12082                 if (syntax != DQSYNTAX && c == '\'')
12083                         bash_dollar_squote = 1;
12084                 else
12085 #endif
12086                         USTPUTC('$', out);
12087                 pungetc();
12088         } else if (c == '(') {
12089                 /* $(command) or $((arith)) */
12090                 if (pgetc_eatbnl() == '(') {
12091 #if ENABLE_FEATURE_SH_MATH
12092                         PARSEARITH();
12093 #else
12094                         raise_error_syntax("support for $((arith)) is disabled");
12095 #endif
12096                 } else {
12097                         pungetc();
12098                         PARSEBACKQNEW();
12099                 }
12100         } else {
12101                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12102                 USTPUTC(CTLVAR, out);
12103                 typeloc = out - (char *)stackblock();
12104                 STADJUST(1, out);
12105                 subtype = VSNORMAL;
12106                 if (c == '{') {
12107                         c = pgetc_eatbnl();
12108                         subtype = 0;
12109                 }
12110  varname:
12111                 if (is_name(c)) {
12112                         /* $[{[#]]NAME[}] */
12113                         do {
12114                                 STPUTC(c, out);
12115                                 c = pgetc_eatbnl();
12116                         } while (is_in_name(c));
12117                 } else if (isdigit(c)) {
12118                         /* $[{[#]]NUM[}] */
12119                         do {
12120                                 STPUTC(c, out);
12121                                 c = pgetc_eatbnl();
12122                         } while (isdigit(c));
12123                 } else {
12124                         /* $[{[#]]<specialchar>[}] */
12125                         int cc = c;
12126
12127                         c = pgetc_eatbnl();
12128                         if (!subtype && cc == '#') {
12129                                 subtype = VSLENGTH;
12130                                 if (c == '_' || isalnum(c))
12131                                         goto varname;
12132                                 cc = c;
12133                                 c = pgetc_eatbnl();
12134                                 if (cc == '}' || c != '}') {
12135                                         pungetc();
12136                                         subtype = 0;
12137                                         c = cc;
12138                                         cc = '#';
12139                                 }
12140                         }
12141
12142                         if (!is_special(cc)) {
12143                                 if (subtype == VSLENGTH)
12144                                         subtype = 0;
12145                                 goto badsub;
12146                         }
12147
12148                         USTPUTC(cc, out);
12149                 }
12150
12151                 if (c != '}' && subtype == VSLENGTH) {
12152                         /* ${#VAR didn't end with } */
12153                         goto badsub;
12154                 }
12155
12156                 if (subtype == 0) {
12157                         static const char types[] ALIGN1 = "}-+?=";
12158                         /* ${VAR...} but not $VAR or ${#VAR} */
12159                         /* c == first char after VAR */
12160                         switch (c) {
12161                         case ':':
12162                                 c = pgetc_eatbnl();
12163 #if BASH_SUBSTR
12164                                 /* This check is only needed to not misinterpret
12165                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12166                                  * constructs.
12167                                  */
12168                                 if (!strchr(types, c)) {
12169                                         subtype = VSSUBSTR;
12170                                         pungetc();
12171                                         break; /* "goto badsub" is bigger (!) */
12172                                 }
12173 #endif
12174                                 subtype = VSNUL;
12175                                 /*FALLTHROUGH*/
12176                         default: {
12177                                 const char *p = strchr(types, c);
12178                                 if (p == NULL)
12179                                         break;
12180                                 subtype |= p - types + VSNORMAL;
12181                                 break;
12182                         }
12183                         case '%':
12184                         case '#': {
12185                                 int cc = c;
12186                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12187                                 c = pgetc_eatbnl();
12188                                 if (c != cc)
12189                                         goto badsub;
12190                                 subtype++;
12191                                 break;
12192                         }
12193 #if BASH_PATTERN_SUBST
12194                         case '/':
12195                                 /* ${v/[/]pattern/repl} */
12196 //TODO: encode pattern and repl separately.
12197 // Currently ${v/$var_with_slash/repl} is horribly broken
12198                                 subtype = VSREPLACE;
12199                                 c = pgetc_eatbnl();
12200                                 if (c != '/')
12201                                         goto badsub;
12202                                 subtype++; /* VSREPLACEALL */
12203                                 break;
12204 #endif
12205                         }
12206                 } else {
12207  badsub:
12208                         pungetc();
12209                 }
12210                 ((unsigned char *)stackblock())[typeloc] = subtype;
12211                 if (subtype != VSNORMAL) {
12212                         varnest++;
12213                         if (dblquote)
12214                                 dqvarnest++;
12215                 }
12216                 STPUTC('=', out);
12217         }
12218         goto parsesub_return;
12219 }
12220
12221 /*
12222  * Called to parse command substitutions.  Newstyle is set if the command
12223  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12224  * list of commands (passed by reference), and savelen is the number of
12225  * characters on the top of the stack which must be preserved.
12226  */
12227 parsebackq: {
12228         struct nodelist **nlpp;
12229         union node *n;
12230         char *str;
12231         size_t savelen;
12232         smallint saveprompt = 0;
12233
12234         str = NULL;
12235         savelen = out - (char *)stackblock();
12236         if (savelen > 0) {
12237                 /*
12238                  * FIXME: this can allocate very large block on stack and SEGV.
12239                  * Example:
12240                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12241                  * allocates 100kb for every command subst. With about
12242                  * a hundred command substitutions stack overflows.
12243                  * With larger prepended string, SEGV happens sooner.
12244                  */
12245                 str = alloca(savelen);
12246                 memcpy(str, stackblock(), savelen);
12247         }
12248
12249         if (oldstyle) {
12250                 /* We must read until the closing backquote, giving special
12251                  * treatment to some slashes, and then push the string and
12252                  * reread it as input, interpreting it normally.
12253                  */
12254                 char *pout;
12255                 size_t psavelen;
12256                 char *pstr;
12257
12258                 STARTSTACKSTR(pout);
12259                 for (;;) {
12260                         int pc;
12261
12262                         setprompt_if(needprompt, 2);
12263                         pc = pgetc();
12264                         switch (pc) {
12265                         case '`':
12266                                 goto done;
12267
12268                         case '\\':
12269                                 pc = pgetc();
12270                                 if (pc == '\n') {
12271                                         nlprompt();
12272                                         /*
12273                                          * If eating a newline, avoid putting
12274                                          * the newline into the new character
12275                                          * stream (via the STPUTC after the
12276                                          * switch).
12277                                          */
12278                                         continue;
12279                                 }
12280                                 if (pc != '\\' && pc != '`' && pc != '$'
12281                                  && (!dblquote || pc != '"')
12282                                 ) {
12283                                         STPUTC('\\', pout);
12284                                 }
12285                                 if (pc <= 255 /* not PEOA or PEOF */) {
12286                                         break;
12287                                 }
12288                                 /* fall through */
12289
12290                         case PEOF:
12291                         IF_ASH_ALIAS(case PEOA:)
12292                                 startlinno = g_parsefile->linno;
12293                                 raise_error_syntax("EOF in backquote substitution");
12294
12295                         case '\n':
12296                                 nlnoprompt();
12297                                 break;
12298
12299                         default:
12300                                 break;
12301                         }
12302                         STPUTC(pc, pout);
12303                 }
12304  done:
12305                 STPUTC('\0', pout);
12306                 psavelen = pout - (char *)stackblock();
12307                 if (psavelen > 0) {
12308                         pstr = grabstackstr(pout);
12309                         setinputstring(pstr);
12310                 }
12311         }
12312         nlpp = &bqlist;
12313         while (*nlpp)
12314                 nlpp = &(*nlpp)->next;
12315         *nlpp = stzalloc(sizeof(**nlpp));
12316         /* (*nlpp)->next = NULL; - stzalloc did it */
12317
12318         if (oldstyle) {
12319                 saveprompt = doprompt;
12320                 doprompt = 0;
12321         }
12322
12323         n = list(2);
12324
12325         if (oldstyle)
12326                 doprompt = saveprompt;
12327         else if (readtoken() != TRP)
12328                 raise_error_unexpected_syntax(TRP);
12329
12330         (*nlpp)->n = n;
12331         if (oldstyle) {
12332                 /*
12333                  * Start reading from old file again, ignoring any pushed back
12334                  * tokens left from the backquote parsing
12335                  */
12336                 popfile();
12337                 tokpushback = 0;
12338         }
12339         while (stackblocksize() <= savelen)
12340                 growstackblock();
12341         STARTSTACKSTR(out);
12342         if (str) {
12343                 memcpy(out, str, savelen);
12344                 STADJUST(savelen, out);
12345         }
12346         USTPUTC(CTLBACKQ, out);
12347         if (oldstyle)
12348                 goto parsebackq_oldreturn;
12349         goto parsebackq_newreturn;
12350 }
12351
12352 #if ENABLE_FEATURE_SH_MATH
12353 /*
12354  * Parse an arithmetic expansion (indicate start of one and set state)
12355  */
12356 parsearith: {
12357         if (++arinest == 1) {
12358                 prevsyntax = syntax;
12359                 syntax = ARISYNTAX;
12360         }
12361         USTPUTC(CTLARI, out);
12362         goto parsearith_return;
12363 }
12364 #endif
12365 } /* end of readtoken */
12366
12367 /*
12368  * Read the next input token.
12369  * If the token is a word, we set backquotelist to the list of cmds in
12370  *      backquotes.  We set quoteflag to true if any part of the word was
12371  *      quoted.
12372  * If the token is TREDIR, then we set redirnode to a structure containing
12373  *      the redirection.
12374  * In all cases, the variable startlinno is set to the number of the line
12375  *      on which the token starts.
12376  *
12377  * [Change comment:  here documents and internal procedures]
12378  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12379  *  word parsing code into a separate routine.  In this case, readtoken
12380  *  doesn't need to have any internal procedures, but parseword does.
12381  *  We could also make parseoperator in essence the main routine, and
12382  *  have parseword (readtoken1?) handle both words and redirection.]
12383  */
12384 #define NEW_xxreadtoken
12385 #ifdef NEW_xxreadtoken
12386 /* singles must be first! */
12387 static const char xxreadtoken_chars[7] ALIGN1 = {
12388         '\n', '(', ')', /* singles */
12389         '&', '|', ';',  /* doubles */
12390         0
12391 };
12392
12393 #define xxreadtoken_singles 3
12394 #define xxreadtoken_doubles 3
12395
12396 static const char xxreadtoken_tokens[] ALIGN1 = {
12397         TNL, TLP, TRP,          /* only single occurrence allowed */
12398         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12399         TEOF,                   /* corresponds to trailing nul */
12400         TAND, TOR, TENDCASE     /* if double occurrence */
12401 };
12402
12403 static int
12404 xxreadtoken(void)
12405 {
12406         int c;
12407
12408         if (tokpushback) {
12409                 tokpushback = 0;
12410                 return lasttoken;
12411         }
12412         setprompt_if(needprompt, 2);
12413         startlinno = g_parsefile->linno;
12414         for (;;) {                      /* until token or start of word found */
12415                 c = pgetc();
12416                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12417                         continue;
12418
12419                 if (c == '#') {
12420                         while ((c = pgetc()) != '\n' && c != PEOF)
12421                                 continue;
12422                         pungetc();
12423                 } else if (c == '\\') {
12424                         if (pgetc() != '\n') {
12425                                 pungetc();
12426                                 break; /* return readtoken1(...) */
12427                         }
12428                         nlprompt();
12429                 } else {
12430                         const char *p;
12431
12432                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12433                         if (c != PEOF) {
12434                                 if (c == '\n') {
12435                                         nlnoprompt();
12436                                 }
12437
12438                                 p = strchr(xxreadtoken_chars, c);
12439                                 if (p == NULL)
12440                                         break; /* return readtoken1(...) */
12441
12442                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12443                                         int cc = pgetc();
12444                                         if (cc == c) {    /* double occurrence? */
12445                                                 p += xxreadtoken_doubles + 1;
12446                                         } else {
12447                                                 pungetc();
12448 #if BASH_REDIR_OUTPUT
12449                                                 if (c == '&' && cc == '>') /* &> */
12450                                                         break; /* return readtoken1(...) */
12451 #endif
12452                                         }
12453                                 }
12454                         }
12455                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12456                         return lasttoken;
12457                 }
12458         } /* for (;;) */
12459
12460         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12461 }
12462 #else /* old xxreadtoken */
12463 #define RETURN(token)   return lasttoken = token
12464 static int
12465 xxreadtoken(void)
12466 {
12467         int c;
12468
12469         if (tokpushback) {
12470                 tokpushback = 0;
12471                 return lasttoken;
12472         }
12473         setprompt_if(needprompt, 2);
12474         startlinno = g_parsefile->linno;
12475         for (;;) {      /* until token or start of word found */
12476                 c = pgetc();
12477                 switch (c) {
12478                 case ' ': case '\t':
12479                 IF_ASH_ALIAS(case PEOA:)
12480                         continue;
12481                 case '#':
12482                         while ((c = pgetc()) != '\n' && c != PEOF)
12483                                 continue;
12484                         pungetc();
12485                         continue;
12486                 case '\\':
12487                         if (pgetc() == '\n') {
12488                                 nlprompt();
12489                                 continue;
12490                         }
12491                         pungetc();
12492                         goto breakloop;
12493                 case '\n':
12494                         nlnoprompt();
12495                         RETURN(TNL);
12496                 case PEOF:
12497                         RETURN(TEOF);
12498                 case '&':
12499                         if (pgetc() == '&')
12500                                 RETURN(TAND);
12501                         pungetc();
12502                         RETURN(TBACKGND);
12503                 case '|':
12504                         if (pgetc() == '|')
12505                                 RETURN(TOR);
12506                         pungetc();
12507                         RETURN(TPIPE);
12508                 case ';':
12509                         if (pgetc() == ';')
12510                                 RETURN(TENDCASE);
12511                         pungetc();
12512                         RETURN(TSEMI);
12513                 case '(':
12514                         RETURN(TLP);
12515                 case ')':
12516                         RETURN(TRP);
12517                 default:
12518                         goto breakloop;
12519                 }
12520         }
12521  breakloop:
12522         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12523 #undef RETURN
12524 }
12525 #endif /* old xxreadtoken */
12526
12527 static int
12528 readtoken(void)
12529 {
12530         int t;
12531         int kwd = checkkwd;
12532 #if DEBUG
12533         smallint alreadyseen = tokpushback;
12534 #endif
12535
12536 #if ENABLE_ASH_ALIAS
12537  top:
12538 #endif
12539
12540         t = xxreadtoken();
12541
12542         /*
12543          * eat newlines
12544          */
12545         if (kwd & CHKNL) {
12546                 while (t == TNL) {
12547                         parseheredoc();
12548                         t = xxreadtoken();
12549                 }
12550         }
12551
12552         if (t != TWORD || quoteflag) {
12553                 goto out;
12554         }
12555
12556         /*
12557          * check for keywords
12558          */
12559         if (kwd & CHKKWD) {
12560                 const char *const *pp;
12561
12562                 pp = findkwd(wordtext);
12563                 if (pp) {
12564                         lasttoken = t = pp - tokname_array;
12565                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12566                         goto out;
12567                 }
12568         }
12569
12570         if (checkkwd & CHKALIAS) {
12571 #if ENABLE_ASH_ALIAS
12572                 struct alias *ap;
12573                 ap = lookupalias(wordtext, 1);
12574                 if (ap != NULL) {
12575                         if (*ap->val) {
12576                                 pushstring(ap->val, ap);
12577                         }
12578                         goto top;
12579                 }
12580 #endif
12581         }
12582  out:
12583         checkkwd = 0;
12584 #if DEBUG
12585         if (!alreadyseen)
12586                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12587         else
12588                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12589 #endif
12590         return t;
12591 }
12592
12593 static int
12594 peektoken(void)
12595 {
12596         int t;
12597
12598         t = readtoken();
12599         tokpushback = 1;
12600         return t;
12601 }
12602
12603 /*
12604  * Read and parse a command.  Returns NODE_EOF on end of file.
12605  * (NULL is a valid parse tree indicating a blank line.)
12606  */
12607 static union node *
12608 parsecmd(int interact)
12609 {
12610         tokpushback = 0;
12611         checkkwd = 0;
12612         heredoclist = 0;
12613         doprompt = interact;
12614         setprompt_if(doprompt, doprompt);
12615         needprompt = 0;
12616         return list(1);
12617 }
12618
12619 /*
12620  * Input any here documents.
12621  */
12622 static void
12623 parseheredoc(void)
12624 {
12625         struct heredoc *here;
12626         union node *n;
12627
12628         here = heredoclist;
12629         heredoclist = NULL;
12630
12631         while (here) {
12632                 setprompt_if(needprompt, 2);
12633                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12634                                 here->eofmark, here->striptabs);
12635                 n = stzalloc(sizeof(struct narg));
12636                 n->narg.type = NARG;
12637                 /*n->narg.next = NULL; - stzalloc did it */
12638                 n->narg.text = wordtext;
12639                 n->narg.backquote = backquotelist;
12640                 here->here->nhere.doc = n;
12641                 here = here->next;
12642         }
12643 }
12644
12645
12646 static const char *
12647 expandstr(const char *ps, int syntax_type)
12648 {
12649         union node n;
12650         int saveprompt;
12651
12652         /* XXX Fix (char *) cast. */
12653         setinputstring((char *)ps);
12654
12655         saveprompt = doprompt;
12656         doprompt = 0;
12657         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12658         doprompt = saveprompt;
12659
12660         popfile();
12661
12662         n.narg.type = NARG;
12663         n.narg.next = NULL;
12664         n.narg.text = wordtext;
12665         n.narg.backquote = backquotelist;
12666
12667         expandarg(&n, NULL, EXP_QUOTED);
12668         return stackblock();
12669 }
12670
12671 static inline int
12672 parser_eof(void)
12673 {
12674         return tokpushback && lasttoken == TEOF;
12675 }
12676
12677 /*
12678  * Execute a command or commands contained in a string.
12679  */
12680 static int
12681 evalstring(char *s, int flags)
12682 {
12683         struct jmploc *volatile savehandler;
12684         struct jmploc jmploc;
12685         int ex;
12686
12687         union node *n;
12688         struct stackmark smark;
12689         int status;
12690
12691         s = sstrdup(s);
12692         setinputstring(s);
12693         setstackmark(&smark);
12694
12695         status = 0;
12696         /* On exception inside execution loop, we must popfile().
12697          * Try interactively:
12698          *      readonly a=a
12699          *      command eval "a=b"  # throws "is read only" error
12700          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12701          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12702          */
12703         savehandler = exception_handler;
12704         ex = setjmp(jmploc.loc);
12705         if (ex)
12706                 goto out;
12707         exception_handler = &jmploc;
12708
12709         while ((n = parsecmd(0)) != NODE_EOF) {
12710                 int i;
12711
12712                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12713                 if (n)
12714                         status = i;
12715                 popstackmark(&smark);
12716                 if (evalskip)
12717                         break;
12718         }
12719  out:
12720         popstackmark(&smark);
12721         popfile();
12722         stunalloc(s);
12723
12724         exception_handler = savehandler;
12725         if (ex)
12726                 longjmp(exception_handler->loc, ex);
12727
12728         return status;
12729 }
12730
12731 /*
12732  * The eval command.
12733  */
12734 static int FAST_FUNC
12735 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12736 {
12737         char *p;
12738         char *concat;
12739
12740         if (argv[1]) {
12741                 p = argv[1];
12742                 argv += 2;
12743                 if (argv[0]) {
12744                         STARTSTACKSTR(concat);
12745                         for (;;) {
12746                                 concat = stack_putstr(p, concat);
12747                                 p = *argv++;
12748                                 if (p == NULL)
12749                                         break;
12750                                 STPUTC(' ', concat);
12751                         }
12752                         STPUTC('\0', concat);
12753                         p = grabstackstr(concat);
12754                 }
12755                 return evalstring(p, flags & EV_TESTED);
12756         }
12757         return 0;
12758 }
12759
12760 /*
12761  * Read and execute commands.
12762  * "Top" is nonzero for the top level command loop;
12763  * it turns on prompting if the shell is interactive.
12764  */
12765 static int
12766 cmdloop(int top)
12767 {
12768         union node *n;
12769         struct stackmark smark;
12770         int inter;
12771         int status = 0;
12772         int numeof = 0;
12773
12774         TRACE(("cmdloop(%d) called\n", top));
12775         for (;;) {
12776                 int skip;
12777
12778                 setstackmark(&smark);
12779 #if JOBS
12780                 if (doing_jobctl)
12781                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12782 #endif
12783                 inter = 0;
12784                 if (iflag && top) {
12785                         inter++;
12786                         chkmail();
12787                 }
12788                 n = parsecmd(inter);
12789 #if DEBUG
12790                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12791                         showtree(n);
12792 #endif
12793                 if (n == NODE_EOF) {
12794                         if (!top || numeof >= 50)
12795                                 break;
12796                         if (!stoppedjobs()) {
12797                                 if (!Iflag)
12798                                         break;
12799                                 out2str("\nUse \"exit\" to leave shell.\n");
12800                         }
12801                         numeof++;
12802                 } else if (nflag == 0) {
12803                         int i;
12804
12805                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12806                         job_warning >>= 1;
12807                         numeof = 0;
12808                         i = evaltree(n, 0);
12809                         if (n)
12810                                 status = i;
12811                 }
12812                 popstackmark(&smark);
12813                 skip = evalskip;
12814
12815                 if (skip) {
12816                         evalskip &= ~SKIPFUNC;
12817                         break;
12818                 }
12819         }
12820         return status;
12821 }
12822
12823 /*
12824  * Take commands from a file.  To be compatible we should do a path
12825  * search for the file, which is necessary to find sub-commands.
12826  */
12827 static char *
12828 find_dot_file(char *name)
12829 {
12830         char *fullname;
12831         const char *path = pathval();
12832         struct stat statb;
12833
12834         /* don't try this for absolute or relative paths */
12835         if (strchr(name, '/'))
12836                 return name;
12837
12838         while ((fullname = path_advance(&path, name)) != NULL) {
12839                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12840                         /*
12841                          * Don't bother freeing here, since it will
12842                          * be freed by the caller.
12843                          */
12844                         return fullname;
12845                 }
12846                 if (fullname != name)
12847                         stunalloc(fullname);
12848         }
12849
12850         /* not found in the PATH */
12851         ash_msg_and_raise_error("%s: not found", name);
12852         /* NOTREACHED */
12853 }
12854
12855 static int FAST_FUNC
12856 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12857 {
12858         /* "false; . empty_file; echo $?" should print 0, not 1: */
12859         int status = 0;
12860         char *fullname;
12861         char **argv;
12862         char *args_need_save;
12863         volatile struct shparam saveparam;
12864
12865 //???
12866 //      struct strlist *sp;
12867 //      for (sp = cmdenviron; sp; sp = sp->next)
12868 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12869
12870         nextopt(nullstr); /* handle possible "--" */
12871         argv = argptr;
12872
12873         if (!argv[0]) {
12874                 /* bash says: "bash: .: filename argument required" */
12875                 return 2; /* bash compat */
12876         }
12877
12878         /* This aborts if file isn't found, which is POSIXly correct.
12879          * bash returns exitcode 1 instead.
12880          */
12881         fullname = find_dot_file(argv[0]);
12882         argv++;
12883         args_need_save = argv[0];
12884         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12885                 int argc;
12886                 saveparam = shellparam;
12887                 shellparam.malloced = 0;
12888                 argc = 1;
12889                 while (argv[argc])
12890                         argc++;
12891                 shellparam.nparam = argc;
12892                 shellparam.p = argv;
12893         };
12894
12895         /* This aborts if file can't be opened, which is POSIXly correct.
12896          * bash returns exitcode 1 instead.
12897          */
12898         setinputfile(fullname, INPUT_PUSH_FILE);
12899         commandname = fullname;
12900         status = cmdloop(0);
12901         popfile();
12902
12903         if (args_need_save) {
12904                 freeparam(&shellparam);
12905                 shellparam = saveparam;
12906         };
12907
12908         return status;
12909 }
12910
12911 static int FAST_FUNC
12912 exitcmd(int argc UNUSED_PARAM, char **argv)
12913 {
12914         if (stoppedjobs())
12915                 return 0;
12916         if (argv[1])
12917                 exitstatus = number(argv[1]);
12918         raise_exception(EXEXIT);
12919         /* NOTREACHED */
12920 }
12921
12922 /*
12923  * Read a file containing shell functions.
12924  */
12925 static void
12926 readcmdfile(char *name)
12927 {
12928         setinputfile(name, INPUT_PUSH_FILE);
12929         cmdloop(0);
12930         popfile();
12931 }
12932
12933
12934 /* ============ find_command inplementation */
12935
12936 /*
12937  * Resolve a command name.  If you change this routine, you may have to
12938  * change the shellexec routine as well.
12939  */
12940 static void
12941 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12942 {
12943         struct tblentry *cmdp;
12944         int idx;
12945         int prev;
12946         char *fullname;
12947         struct stat statb;
12948         int e;
12949         int updatetbl;
12950         struct builtincmd *bcmd;
12951
12952         /* If name contains a slash, don't use PATH or hash table */
12953         if (strchr(name, '/') != NULL) {
12954                 entry->u.index = -1;
12955                 if (act & DO_ABS) {
12956                         while (stat(name, &statb) < 0) {
12957 #ifdef SYSV
12958                                 if (errno == EINTR)
12959                                         continue;
12960 #endif
12961                                 entry->cmdtype = CMDUNKNOWN;
12962                                 return;
12963                         }
12964                 }
12965                 entry->cmdtype = CMDNORMAL;
12966                 return;
12967         }
12968
12969 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12970
12971         updatetbl = (path == pathval());
12972         if (!updatetbl) {
12973                 act |= DO_ALTPATH;
12974                 if (strstr(path, "%builtin") != NULL)
12975                         act |= DO_ALTBLTIN;
12976         }
12977
12978         /* If name is in the table, check answer will be ok */
12979         cmdp = cmdlookup(name, 0);
12980         if (cmdp != NULL) {
12981                 int bit;
12982
12983                 switch (cmdp->cmdtype) {
12984                 default:
12985 #if DEBUG
12986                         abort();
12987 #endif
12988                 case CMDNORMAL:
12989                         bit = DO_ALTPATH;
12990                         break;
12991                 case CMDFUNCTION:
12992                         bit = DO_NOFUNC;
12993                         break;
12994                 case CMDBUILTIN:
12995                         bit = DO_ALTBLTIN;
12996                         break;
12997                 }
12998                 if (act & bit) {
12999                         updatetbl = 0;
13000                         cmdp = NULL;
13001                 } else if (cmdp->rehash == 0)
13002                         /* if not invalidated by cd, we're done */
13003                         goto success;
13004         }
13005
13006         /* If %builtin not in path, check for builtin next */
13007         bcmd = find_builtin(name);
13008         if (bcmd) {
13009                 if (IS_BUILTIN_REGULAR(bcmd))
13010                         goto builtin_success;
13011                 if (act & DO_ALTPATH) {
13012                         if (!(act & DO_ALTBLTIN))
13013                                 goto builtin_success;
13014                 } else if (builtinloc <= 0) {
13015                         goto builtin_success;
13016                 }
13017         }
13018
13019 #if ENABLE_FEATURE_SH_STANDALONE
13020         {
13021                 int applet_no = find_applet_by_name(name);
13022                 if (applet_no >= 0) {
13023                         entry->cmdtype = CMDNORMAL;
13024                         entry->u.index = -2 - applet_no;
13025                         return;
13026                 }
13027         }
13028 #endif
13029
13030         /* We have to search path. */
13031         prev = -1;              /* where to start */
13032         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13033                 if (cmdp->cmdtype == CMDBUILTIN)
13034                         prev = builtinloc;
13035                 else
13036                         prev = cmdp->param.index;
13037         }
13038
13039         e = ENOENT;
13040         idx = -1;
13041  loop:
13042         while ((fullname = path_advance(&path, name)) != NULL) {
13043                 stunalloc(fullname);
13044                 /* NB: code below will still use fullname
13045                  * despite it being "unallocated" */
13046                 idx++;
13047                 if (pathopt) {
13048                         if (prefix(pathopt, "builtin")) {
13049                                 if (bcmd)
13050                                         goto builtin_success;
13051                                 continue;
13052                         }
13053                         if ((act & DO_NOFUNC)
13054                          || !prefix(pathopt, "func")
13055                         ) {     /* ignore unimplemented options */
13056                                 continue;
13057                         }
13058                 }
13059                 /* if rehash, don't redo absolute path names */
13060                 if (fullname[0] == '/' && idx <= prev) {
13061                         if (idx < prev)
13062                                 continue;
13063                         TRACE(("searchexec \"%s\": no change\n", name));
13064                         goto success;
13065                 }
13066                 while (stat(fullname, &statb) < 0) {
13067 #ifdef SYSV
13068                         if (errno == EINTR)
13069                                 continue;
13070 #endif
13071                         if (errno != ENOENT && errno != ENOTDIR)
13072                                 e = errno;
13073                         goto loop;
13074                 }
13075                 e = EACCES;     /* if we fail, this will be the error */
13076                 if (!S_ISREG(statb.st_mode))
13077                         continue;
13078                 if (pathopt) {          /* this is a %func directory */
13079                         stalloc(strlen(fullname) + 1);
13080                         /* NB: stalloc will return space pointed by fullname
13081                          * (because we don't have any intervening allocations
13082                          * between stunalloc above and this stalloc) */
13083                         readcmdfile(fullname);
13084                         cmdp = cmdlookup(name, 0);
13085                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13086                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13087                         stunalloc(fullname);
13088                         goto success;
13089                 }
13090                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13091                 if (!updatetbl) {
13092                         entry->cmdtype = CMDNORMAL;
13093                         entry->u.index = idx;
13094                         return;
13095                 }
13096                 INT_OFF;
13097                 cmdp = cmdlookup(name, 1);
13098                 cmdp->cmdtype = CMDNORMAL;
13099                 cmdp->param.index = idx;
13100                 INT_ON;
13101                 goto success;
13102         }
13103
13104         /* We failed.  If there was an entry for this command, delete it */
13105         if (cmdp && updatetbl)
13106                 delete_cmd_entry();
13107         if (act & DO_ERR)
13108                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13109         entry->cmdtype = CMDUNKNOWN;
13110         return;
13111
13112  builtin_success:
13113         if (!updatetbl) {
13114                 entry->cmdtype = CMDBUILTIN;
13115                 entry->u.cmd = bcmd;
13116                 return;
13117         }
13118         INT_OFF;
13119         cmdp = cmdlookup(name, 1);
13120         cmdp->cmdtype = CMDBUILTIN;
13121         cmdp->param.cmd = bcmd;
13122         INT_ON;
13123  success:
13124         cmdp->rehash = 0;
13125         entry->cmdtype = cmdp->cmdtype;
13126         entry->u = cmdp->param;
13127 }
13128
13129
13130 /*
13131  * The trap builtin.
13132  */
13133 static int FAST_FUNC
13134 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13135 {
13136         char *action;
13137         char **ap;
13138         int signo, exitcode;
13139
13140         nextopt(nullstr);
13141         ap = argptr;
13142         if (!*ap) {
13143                 for (signo = 0; signo < NSIG; signo++) {
13144                         char *tr = trap_ptr[signo];
13145                         if (tr) {
13146                                 /* note: bash adds "SIG", but only if invoked
13147                                  * as "bash". If called as "sh", or if set -o posix,
13148                                  * then it prints short signal names.
13149                                  * We are printing short names: */
13150                                 out1fmt("trap -- %s %s\n",
13151                                                 single_quote(tr),
13152                                                 get_signame(signo));
13153                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13154                  * In this case, we will exit very soon, no need to free(). */
13155                                 /* if (trap_ptr != trap && tp[0]) */
13156                                 /*      free(tr); */
13157                         }
13158                 }
13159                 /*
13160                 if (trap_ptr != trap) {
13161                         free(trap_ptr);
13162                         trap_ptr = trap;
13163                 }
13164                 */
13165                 return 0;
13166         }
13167
13168         /* Why the second check?
13169          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13170          * In this case, NUM is signal no, not an action.
13171          */
13172         action = NULL;
13173         if (ap[1] && !is_number(ap[0]))
13174                 action = *ap++;
13175
13176         exitcode = 0;
13177         while (*ap) {
13178                 signo = get_signum(*ap);
13179                 if (signo < 0) {
13180                         /* Mimic bash message exactly */
13181                         ash_msg("%s: invalid signal specification", *ap);
13182                         exitcode = 1;
13183                         goto next;
13184                 }
13185                 INT_OFF;
13186                 if (action) {
13187                         if (LONE_DASH(action))
13188                                 action = NULL;
13189                         else {
13190                                 if (action[0]) /* not NULL and not "" and not "-" */
13191                                         may_have_traps = 1;
13192                                 action = ckstrdup(action);
13193                         }
13194                 }
13195                 free(trap[signo]);
13196                 trap[signo] = action;
13197                 if (signo != 0)
13198                         setsignal(signo);
13199                 INT_ON;
13200  next:
13201                 ap++;
13202         }
13203         return exitcode;
13204 }
13205
13206
13207 /* ============ Builtins */
13208
13209 #if ENABLE_ASH_HELP
13210 static int FAST_FUNC
13211 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13212 {
13213         unsigned col;
13214         unsigned i;
13215
13216         out1fmt(
13217                 "Built-in commands:\n"
13218                 "------------------\n");
13219         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13220                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13221                                         builtintab[i].name + 1);
13222                 if (col > 60) {
13223                         out1fmt("\n");
13224                         col = 0;
13225                 }
13226         }
13227 # if ENABLE_FEATURE_SH_STANDALONE
13228         {
13229                 const char *a = applet_names;
13230                 while (*a) {
13231                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13232                         if (col > 60) {
13233                                 out1fmt("\n");
13234                                 col = 0;
13235                         }
13236                         while (*a++ != '\0')
13237                                 continue;
13238                 }
13239         }
13240 # endif
13241         newline_and_flush(stdout);
13242         return EXIT_SUCCESS;
13243 }
13244 #endif
13245
13246 #if MAX_HISTORY
13247 static int FAST_FUNC
13248 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13249 {
13250         show_history(line_input_state);
13251         return EXIT_SUCCESS;
13252 }
13253 #endif
13254
13255 /*
13256  * The export and readonly commands.
13257  */
13258 static int FAST_FUNC
13259 exportcmd(int argc UNUSED_PARAM, char **argv)
13260 {
13261         struct var *vp;
13262         char *name;
13263         const char *p;
13264         char **aptr;
13265         char opt;
13266         int flag;
13267         int flag_off;
13268
13269         /* "readonly" in bash accepts, but ignores -n.
13270          * We do the same: it saves a conditional in nextopt's param.
13271          */
13272         flag_off = 0;
13273         while ((opt = nextopt("np")) != '\0') {
13274                 if (opt == 'n')
13275                         flag_off = VEXPORT;
13276         }
13277         flag = VEXPORT;
13278         if (argv[0][0] == 'r') {
13279                 flag = VREADONLY;
13280                 flag_off = 0; /* readonly ignores -n */
13281         }
13282         flag_off = ~flag_off;
13283
13284         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13285         {
13286                 aptr = argptr;
13287                 name = *aptr;
13288                 if (name) {
13289                         do {
13290                                 p = strchr(name, '=');
13291                                 if (p != NULL) {
13292                                         p++;
13293                                 } else {
13294                                         vp = *findvar(hashvar(name), name);
13295                                         if (vp) {
13296                                                 vp->flags = ((vp->flags | flag) & flag_off);
13297                                                 continue;
13298                                         }
13299                                 }
13300                                 setvar(name, p, (flag & flag_off));
13301                         } while ((name = *++aptr) != NULL);
13302                         return 0;
13303                 }
13304         }
13305
13306         /* No arguments. Show the list of exported or readonly vars.
13307          * -n is ignored.
13308          */
13309         showvars(argv[0], flag, 0);
13310         return 0;
13311 }
13312
13313 /*
13314  * Delete a function if it exists.
13315  */
13316 static void
13317 unsetfunc(const char *name)
13318 {
13319         struct tblentry *cmdp;
13320
13321         cmdp = cmdlookup(name, 0);
13322         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13323                 delete_cmd_entry();
13324 }
13325
13326 /*
13327  * The unset builtin command.  We unset the function before we unset the
13328  * variable to allow a function to be unset when there is a readonly variable
13329  * with the same name.
13330  */
13331 static int FAST_FUNC
13332 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13333 {
13334         char **ap;
13335         int i;
13336         int flag = 0;
13337
13338         while ((i = nextopt("vf")) != 0) {
13339                 flag = i;
13340         }
13341
13342         for (ap = argptr; *ap; ap++) {
13343                 if (flag != 'f') {
13344                         unsetvar(*ap);
13345                         continue;
13346                 }
13347                 if (flag != 'v')
13348                         unsetfunc(*ap);
13349         }
13350         return 0;
13351 }
13352
13353 static const unsigned char timescmd_str[] ALIGN1 = {
13354         ' ',  offsetof(struct tms, tms_utime),
13355         '\n', offsetof(struct tms, tms_stime),
13356         ' ',  offsetof(struct tms, tms_cutime),
13357         '\n', offsetof(struct tms, tms_cstime),
13358         0
13359 };
13360 static int FAST_FUNC
13361 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13362 {
13363         unsigned clk_tck;
13364         const unsigned char *p;
13365         struct tms buf;
13366
13367         clk_tck = bb_clk_tck();
13368
13369         times(&buf);
13370         p = timescmd_str;
13371         do {
13372                 unsigned sec, frac;
13373                 unsigned long t;
13374                 t = *(clock_t *)(((char *) &buf) + p[1]);
13375                 sec = t / clk_tck;
13376                 frac = t % clk_tck;
13377                 out1fmt("%um%u.%03us%c",
13378                         sec / 60, sec % 60,
13379                         (frac * 1000) / clk_tck,
13380                         p[0]);
13381                 p += 2;
13382         } while (*p);
13383
13384         return 0;
13385 }
13386
13387 #if ENABLE_FEATURE_SH_MATH
13388 /*
13389  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13390  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13391  *
13392  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13393  */
13394 static int FAST_FUNC
13395 letcmd(int argc UNUSED_PARAM, char **argv)
13396 {
13397         arith_t i;
13398
13399         argv++;
13400         if (!*argv)
13401                 ash_msg_and_raise_error("expression expected");
13402         do {
13403                 i = ash_arith(*argv);
13404         } while (*++argv);
13405
13406         return !i;
13407 }
13408 #endif
13409
13410 /*
13411  * The read builtin. Options:
13412  *      -r              Do not interpret '\' specially
13413  *      -s              Turn off echo (tty only)
13414  *      -n NCHARS       Read NCHARS max
13415  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13416  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13417  *      -u FD           Read from given FD instead of fd 0
13418  *      -d DELIM        End on DELIM char, not newline
13419  * This uses unbuffered input, which may be avoidable in some cases.
13420  * TODO: bash also has:
13421  *      -a ARRAY        Read into array[0],[1],etc
13422  *      -e              Use line editing (tty only)
13423  */
13424 static int FAST_FUNC
13425 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13426 {
13427         char *opt_n = NULL;
13428         char *opt_p = NULL;
13429         char *opt_t = NULL;
13430         char *opt_u = NULL;
13431         char *opt_d = NULL; /* optimized out if !BASH */
13432         int read_flags = 0;
13433         const char *r;
13434         int i;
13435
13436         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13437                 switch (i) {
13438                 case 'p':
13439                         opt_p = optionarg;
13440                         break;
13441                 case 'n':
13442                         opt_n = optionarg;
13443                         break;
13444                 case 's':
13445                         read_flags |= BUILTIN_READ_SILENT;
13446                         break;
13447                 case 't':
13448                         opt_t = optionarg;
13449                         break;
13450                 case 'r':
13451                         read_flags |= BUILTIN_READ_RAW;
13452                         break;
13453                 case 'u':
13454                         opt_u = optionarg;
13455                         break;
13456 #if BASH_READ_D
13457                 case 'd':
13458                         opt_d = optionarg;
13459                         break;
13460 #endif
13461                 default:
13462                         break;
13463                 }
13464         }
13465
13466         /* "read -s" needs to save/restore termios, can't allow ^C
13467          * to jump out of it.
13468          */
13469  again:
13470         INT_OFF;
13471         r = shell_builtin_read(setvar0,
13472                 argptr,
13473                 bltinlookup("IFS"), /* can be NULL */
13474                 read_flags,
13475                 opt_n,
13476                 opt_p,
13477                 opt_t,
13478                 opt_u,
13479                 opt_d
13480         );
13481         INT_ON;
13482
13483         if ((uintptr_t)r == 1 && errno == EINTR) {
13484                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13485                  * Correct behavior is to not exit "read"
13486                  */
13487                 if (pending_sig == 0)
13488                         goto again;
13489         }
13490
13491         if ((uintptr_t)r > 1)
13492                 ash_msg_and_raise_error(r);
13493
13494         return (uintptr_t)r;
13495 }
13496
13497 static int FAST_FUNC
13498 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13499 {
13500         static const char permuser[3] ALIGN1 = "ogu";
13501
13502         mode_t mask;
13503         int symbolic_mode = 0;
13504
13505         while (nextopt("S") != '\0') {
13506                 symbolic_mode = 1;
13507         }
13508
13509         INT_OFF;
13510         mask = umask(0);
13511         umask(mask);
13512         INT_ON;
13513
13514         if (*argptr == NULL) {
13515                 if (symbolic_mode) {
13516                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13517                         char *p = buf;
13518                         int i;
13519
13520                         i = 2;
13521                         for (;;) {
13522                                 *p++ = ',';
13523                                 *p++ = permuser[i];
13524                                 *p++ = '=';
13525                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13526                                 if (!(mask & 0400)) *p++ = 'r';
13527                                 if (!(mask & 0200)) *p++ = 'w';
13528                                 if (!(mask & 0100)) *p++ = 'x';
13529                                 mask <<= 3;
13530                                 if (--i < 0)
13531                                         break;
13532                         }
13533                         *p = '\0';
13534                         puts(buf + 1);
13535                 } else {
13536                         out1fmt("%04o\n", mask);
13537                 }
13538         } else {
13539                 char *modestr = *argptr;
13540                 /* numeric umasks are taken as-is */
13541                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13542                 if (!isdigit(modestr[0]))
13543                         mask ^= 0777;
13544                 mask = bb_parse_mode(modestr, mask);
13545                 if ((unsigned)mask > 0777) {
13546                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13547                 }
13548                 if (!isdigit(modestr[0]))
13549                         mask ^= 0777;
13550                 umask(mask);
13551         }
13552         return 0;
13553 }
13554
13555 static int FAST_FUNC
13556 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13557 {
13558         return shell_builtin_ulimit(argv);
13559 }
13560
13561 /* ============ main() and helpers */
13562
13563 /*
13564  * Called to exit the shell.
13565  */
13566 static void
13567 exitshell(void)
13568 {
13569         struct jmploc loc;
13570         char *p;
13571         int status;
13572
13573 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13574         save_history(line_input_state);
13575 #endif
13576         status = exitstatus;
13577         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13578         if (setjmp(loc.loc)) {
13579                 if (exception_type == EXEXIT)
13580                         status = exitstatus;
13581                 goto out;
13582         }
13583         exception_handler = &loc;
13584         p = trap[0];
13585         if (p) {
13586                 trap[0] = NULL;
13587                 evalskip = 0;
13588                 evalstring(p, 0);
13589                 /*free(p); - we'll exit soon */
13590         }
13591  out:
13592         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13593          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13594          */
13595         setjobctl(0);
13596         flush_stdout_stderr();
13597         _exit(status);
13598         /* NOTREACHED */
13599 }
13600
13601 /* Don't inline: conserve stack of caller from having our locals too */
13602 static NOINLINE void
13603 init(void)
13604 {
13605         /* we will never free this */
13606         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13607         basepf.linno = 1;
13608
13609         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13610         setsignal(SIGCHLD);
13611
13612         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13613          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13614          */
13615         signal(SIGHUP, SIG_DFL);
13616
13617         {
13618                 char **envp;
13619                 const char *p;
13620
13621                 initvar();
13622                 for (envp = environ; envp && *envp; envp++) {
13623                         p = endofname(*envp);
13624                         if (p != *envp && *p == '=') {
13625                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13626                         }
13627                 }
13628
13629                 setvareq((char*)defoptindvar, VTEXTFIXED);
13630
13631                 setvar0("PPID", utoa(getppid()));
13632 #if BASH_SHLVL_VAR
13633                 p = lookupvar("SHLVL");
13634                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13635 #endif
13636 #if BASH_HOSTNAME_VAR
13637                 if (!lookupvar("HOSTNAME")) {
13638                         struct utsname uts;
13639                         uname(&uts);
13640                         setvar0("HOSTNAME", uts.nodename);
13641                 }
13642 #endif
13643                 p = lookupvar("PWD");
13644                 if (p) {
13645                         struct stat st1, st2;
13646                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13647                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13648                         ) {
13649                                 p = NULL;
13650                         }
13651                 }
13652                 setpwd(p, 0);
13653         }
13654 }
13655
13656
13657 //usage:#define ash_trivial_usage
13658 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13659 //usage:#define ash_full_usage "\n\n"
13660 //usage:        "Unix shell interpreter"
13661
13662 /*
13663  * Process the shell command line arguments.
13664  */
13665 static int
13666 procargs(char **argv)
13667 {
13668         int i;
13669         const char *xminusc;
13670         char **xargv;
13671         int login_sh;
13672
13673         xargv = argv;
13674         login_sh = xargv[0] && xargv[0][0] == '-';
13675         arg0 = xargv[0];
13676         /* if (xargv[0]) - mmm, this is always true! */
13677                 xargv++;
13678         for (i = 0; i < NOPTS; i++)
13679                 optlist[i] = 2;
13680         argptr = xargv;
13681         if (options(/*cmdline:*/ 1, &login_sh)) {
13682                 /* it already printed err message */
13683                 raise_exception(EXERROR);
13684         }
13685         xargv = argptr;
13686         xminusc = minusc;
13687         if (*xargv == NULL) {
13688                 if (xminusc)
13689                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13690                 sflag = 1;
13691         }
13692         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13693                 iflag = 1;
13694         if (mflag == 2)
13695                 mflag = iflag;
13696         for (i = 0; i < NOPTS; i++)
13697                 if (optlist[i] == 2)
13698                         optlist[i] = 0;
13699 #if DEBUG == 2
13700         debug = 1;
13701 #endif
13702         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13703         if (xminusc) {
13704                 minusc = *xargv++;
13705                 if (*xargv)
13706                         goto setarg0;
13707         } else if (!sflag) {
13708                 setinputfile(*xargv, 0);
13709  setarg0:
13710                 arg0 = *xargv++;
13711                 commandname = arg0;
13712         }
13713
13714         shellparam.p = xargv;
13715 #if ENABLE_ASH_GETOPTS
13716         shellparam.optind = 1;
13717         shellparam.optoff = -1;
13718 #endif
13719         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13720         while (*xargv) {
13721                 shellparam.nparam++;
13722                 xargv++;
13723         }
13724         optschanged();
13725
13726         return login_sh;
13727 }
13728
13729 /*
13730  * Read /etc/profile, ~/.profile, $ENV.
13731  */
13732 static void
13733 read_profile(const char *name)
13734 {
13735         name = expandstr(name, DQSYNTAX);
13736         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13737                 return;
13738         cmdloop(0);
13739         popfile();
13740 }
13741
13742 /*
13743  * This routine is called when an error or an interrupt occurs in an
13744  * interactive shell and control is returned to the main command loop.
13745  * (In dash, this function is auto-generated by build machinery).
13746  */
13747 static void
13748 reset(void)
13749 {
13750         /* from eval.c: */
13751         evalskip = 0;
13752         loopnest = 0;
13753
13754         /* from expand.c: */
13755         ifsfree();
13756
13757         /* from input.c: */
13758         g_parsefile->left_in_buffer = 0;
13759         g_parsefile->left_in_line = 0;      /* clear input buffer */
13760         popallfiles();
13761
13762         /* from redir.c: */
13763         unwindredir(NULL);
13764
13765         /* from var.c: */
13766         unwindlocalvars(NULL);
13767 }
13768
13769 #if PROFILE
13770 static short profile_buf[16384];
13771 extern int etext();
13772 #endif
13773
13774 /*
13775  * Main routine.  We initialize things, parse the arguments, execute
13776  * profiles if we're a login shell, and then call cmdloop to execute
13777  * commands.  The setjmp call sets up the location to jump to when an
13778  * exception occurs.  When an exception occurs the variable "state"
13779  * is used to figure out how far we had gotten.
13780  */
13781 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13782 int ash_main(int argc UNUSED_PARAM, char **argv)
13783 {
13784         volatile smallint state;
13785         struct jmploc jmploc;
13786         struct stackmark smark;
13787         int login_sh;
13788
13789         /* Initialize global data */
13790         INIT_G_misc();
13791         INIT_G_memstack();
13792         INIT_G_var();
13793 #if ENABLE_ASH_ALIAS
13794         INIT_G_alias();
13795 #endif
13796         INIT_G_cmdtable();
13797
13798 #if PROFILE
13799         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13800 #endif
13801
13802 #if ENABLE_FEATURE_EDITING
13803         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13804 #endif
13805         state = 0;
13806         if (setjmp(jmploc.loc)) {
13807                 smallint e;
13808                 smallint s;
13809
13810                 reset();
13811
13812                 e = exception_type;
13813                 s = state;
13814                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13815                         exitshell();
13816                 }
13817                 if (e == EXINT) {
13818                         newline_and_flush(stderr);
13819                 }
13820
13821                 popstackmark(&smark);
13822                 FORCE_INT_ON; /* enable interrupts */
13823                 if (s == 1)
13824                         goto state1;
13825                 if (s == 2)
13826                         goto state2;
13827                 if (s == 3)
13828                         goto state3;
13829                 goto state4;
13830         }
13831         exception_handler = &jmploc;
13832         rootpid = getpid();
13833
13834         init();
13835         setstackmark(&smark);
13836         login_sh = procargs(argv);
13837 #if DEBUG
13838         TRACE(("Shell args: "));
13839         trace_puts_args(argv);
13840 #endif
13841
13842         if (login_sh) {
13843                 const char *hp;
13844
13845                 state = 1;
13846                 read_profile("/etc/profile");
13847  state1:
13848                 state = 2;
13849                 hp = lookupvar("HOME");
13850                 if (hp)
13851                         read_profile("$HOME/.profile");
13852         }
13853  state2:
13854         state = 3;
13855         if (
13856 #ifndef linux
13857          getuid() == geteuid() && getgid() == getegid() &&
13858 #endif
13859          iflag
13860         ) {
13861                 const char *shinit = lookupvar("ENV");
13862                 if (shinit != NULL && *shinit != '\0')
13863                         read_profile(shinit);
13864         }
13865         popstackmark(&smark);
13866  state3:
13867         state = 4;
13868         if (minusc) {
13869                 /* evalstring pushes parsefile stack.
13870                  * Ensure we don't falsely claim that 0 (stdin)
13871                  * is one of stacked source fds.
13872                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13873                 // if (!sflag) g_parsefile->pf_fd = -1;
13874                 // ^^ not necessary since now we special-case fd 0
13875                 // in save_fd_on_redirect()
13876                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13877         }
13878
13879         if (sflag || minusc == NULL) {
13880 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13881                 if (iflag) {
13882                         const char *hp = lookupvar("HISTFILE");
13883                         if (!hp) {
13884                                 hp = lookupvar("HOME");
13885                                 if (hp) {
13886                                         INT_OFF;
13887                                         hp = concat_path_file(hp, ".ash_history");
13888                                         setvar0("HISTFILE", hp);
13889                                         free((char*)hp);
13890                                         INT_ON;
13891                                         hp = lookupvar("HISTFILE");
13892                                 }
13893                         }
13894                         if (hp)
13895                                 line_input_state->hist_file = hp;
13896 # if ENABLE_FEATURE_SH_HISTFILESIZE
13897                         hp = lookupvar("HISTFILESIZE");
13898                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13899 # endif
13900                 }
13901 #endif
13902  state4: /* XXX ??? - why isn't this before the "if" statement */
13903                 cmdloop(1);
13904         }
13905 #if PROFILE
13906         monitor(0);
13907 #endif
13908 #ifdef GPROF
13909         {
13910                 extern void _mcleanup(void);
13911                 _mcleanup();
13912         }
13913 #endif
13914         TRACE(("End of main reached\n"));
13915         exitshell();
13916         /* NOTREACHED */
13917 }
13918
13919
13920 /*-
13921  * Copyright (c) 1989, 1991, 1993, 1994
13922  *      The Regents of the University of California.  All rights reserved.
13923  *
13924  * This code is derived from software contributed to Berkeley by
13925  * Kenneth Almquist.
13926  *
13927  * Redistribution and use in source and binary forms, with or without
13928  * modification, are permitted provided that the following conditions
13929  * are met:
13930  * 1. Redistributions of source code must retain the above copyright
13931  *    notice, this list of conditions and the following disclaimer.
13932  * 2. Redistributions in binary form must reproduce the above copyright
13933  *    notice, this list of conditions and the following disclaimer in the
13934  *    documentation and/or other materials provided with the distribution.
13935  * 3. Neither the name of the University nor the names of its contributors
13936  *    may be used to endorse or promote products derived from this software
13937  *    without specific prior written permission.
13938  *
13939  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
13940  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13941  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13942  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13943  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13944  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13945  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13946  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13947  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13948  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13949  * SUCH DAMAGE.
13950  */