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