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