ash: make tryexec(cmd) parameter const char
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps);
2492
2493 static void
2494 setprompt_if(smallint do_set, int whichprompt)
2495 {
2496         const char *prompt;
2497         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2498
2499         if (!do_set)
2500                 return;
2501
2502         needprompt = 0;
2503
2504         switch (whichprompt) {
2505         case 1:
2506                 prompt = ps1val();
2507                 break;
2508         case 2:
2509                 prompt = ps2val();
2510                 break;
2511         default:                        /* 0 */
2512                 prompt = nullstr;
2513         }
2514 #if ENABLE_ASH_EXPAND_PRMT
2515         pushstackmark(&smark, stackblocksize());
2516         putprompt(expandstr(prompt));
2517         popstackmark(&smark);
2518 #else
2519         putprompt(prompt);
2520 #endif
2521 }
2522
2523
2524 /* ============ The cd and pwd commands */
2525
2526 #define CD_PHYSICAL 1
2527 #define CD_PRINT 2
2528
2529 static int
2530 cdopt(void)
2531 {
2532         int flags = 0;
2533         int i, j;
2534
2535         j = 'L';
2536         while ((i = nextopt("LP")) != '\0') {
2537                 if (i != j) {
2538                         flags ^= CD_PHYSICAL;
2539                         j = i;
2540                 }
2541         }
2542
2543         return flags;
2544 }
2545
2546 /*
2547  * Update curdir (the name of the current directory) in response to a
2548  * cd command.
2549  */
2550 static const char *
2551 updatepwd(const char *dir)
2552 {
2553         char *new;
2554         char *p;
2555         char *cdcomppath;
2556         const char *lim;
2557
2558         cdcomppath = sstrdup(dir);
2559         STARTSTACKSTR(new);
2560         if (*dir != '/') {
2561                 if (curdir == nullstr)
2562                         return 0;
2563                 new = stack_putstr(curdir, new);
2564         }
2565         new = makestrspace(strlen(dir) + 2, new);
2566         lim = (char *)stackblock() + 1;
2567         if (*dir != '/') {
2568                 if (new[-1] != '/')
2569                         USTPUTC('/', new);
2570                 if (new > lim && *lim == '/')
2571                         lim++;
2572         } else {
2573                 USTPUTC('/', new);
2574                 cdcomppath++;
2575                 if (dir[1] == '/' && dir[2] != '/') {
2576                         USTPUTC('/', new);
2577                         cdcomppath++;
2578                         lim++;
2579                 }
2580         }
2581         p = strtok(cdcomppath, "/");
2582         while (p) {
2583                 switch (*p) {
2584                 case '.':
2585                         if (p[1] == '.' && p[2] == '\0') {
2586                                 while (new > lim) {
2587                                         STUNPUTC(new);
2588                                         if (new[-1] == '/')
2589                                                 break;
2590                                 }
2591                                 break;
2592                         }
2593                         if (p[1] == '\0')
2594                                 break;
2595                         /* fall through */
2596                 default:
2597                         new = stack_putstr(p, new);
2598                         USTPUTC('/', new);
2599                 }
2600                 p = strtok(NULL, "/");
2601         }
2602         if (new > lim)
2603                 STUNPUTC(new);
2604         *new = 0;
2605         return stackblock();
2606 }
2607
2608 /*
2609  * Find out what the current directory is. If we already know the current
2610  * directory, this routine returns immediately.
2611  */
2612 static char *
2613 getpwd(void)
2614 {
2615         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2616         return dir ? dir : nullstr;
2617 }
2618
2619 static void
2620 setpwd(const char *val, int setold)
2621 {
2622         char *oldcur, *dir;
2623
2624         oldcur = dir = curdir;
2625
2626         if (setold) {
2627                 setvar("OLDPWD", oldcur, VEXPORT);
2628         }
2629         INT_OFF;
2630         if (physdir != nullstr) {
2631                 if (physdir != oldcur)
2632                         free(physdir);
2633                 physdir = nullstr;
2634         }
2635         if (oldcur == val || !val) {
2636                 char *s = getpwd();
2637                 physdir = s;
2638                 if (!val)
2639                         dir = s;
2640         } else
2641                 dir = ckstrdup(val);
2642         if (oldcur != dir && oldcur != nullstr) {
2643                 free(oldcur);
2644         }
2645         curdir = dir;
2646         INT_ON;
2647         setvar("PWD", dir, VEXPORT);
2648 }
2649
2650 static void hashcd(void);
2651
2652 /*
2653  * Actually do the chdir.  We also call hashcd to let other routines
2654  * know that the current directory has changed.
2655  */
2656 static int
2657 docd(const char *dest, int flags)
2658 {
2659         const char *dir = NULL;
2660         int err;
2661
2662         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2663
2664         INT_OFF;
2665         if (!(flags & CD_PHYSICAL)) {
2666                 dir = updatepwd(dest);
2667                 if (dir)
2668                         dest = dir;
2669         }
2670         err = chdir(dest);
2671         if (err)
2672                 goto out;
2673         setpwd(dir, 1);
2674         hashcd();
2675  out:
2676         INT_ON;
2677         return err;
2678 }
2679
2680 static int FAST_FUNC
2681 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2682 {
2683         const char *dest;
2684         const char *path;
2685         const char *p;
2686         char c;
2687         struct stat statb;
2688         int flags;
2689
2690         flags = cdopt();
2691         dest = *argptr;
2692         if (!dest)
2693                 dest = bltinlookup("HOME");
2694         else if (LONE_DASH(dest)) {
2695                 dest = bltinlookup("OLDPWD");
2696                 flags |= CD_PRINT;
2697         }
2698         if (!dest)
2699                 dest = nullstr;
2700         if (*dest == '/')
2701                 goto step6;
2702         if (*dest == '.') {
2703                 c = dest[1];
2704  dotdot:
2705                 switch (c) {
2706                 case '\0':
2707                 case '/':
2708                         goto step6;
2709                 case '.':
2710                         c = dest[2];
2711                         if (c != '.')
2712                                 goto dotdot;
2713                 }
2714         }
2715         if (!*dest)
2716                 dest = ".";
2717         path = bltinlookup("CDPATH");
2718         while (path) {
2719                 c = *path;
2720                 p = path_advance(&path, dest);
2721                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2722                         if (c && c != ':')
2723                                 flags |= CD_PRINT;
2724  docd:
2725                         if (!docd(p, flags))
2726                                 goto out;
2727                         goto err;
2728                 }
2729         }
2730
2731  step6:
2732         p = dest;
2733         goto docd;
2734
2735  err:
2736         ash_msg_and_raise_error("can't cd to %s", dest);
2737         /* NOTREACHED */
2738  out:
2739         if (flags & CD_PRINT)
2740                 out1fmt("%s\n", curdir);
2741         return 0;
2742 }
2743
2744 static int FAST_FUNC
2745 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2746 {
2747         int flags;
2748         const char *dir = curdir;
2749
2750         flags = cdopt();
2751         if (flags) {
2752                 if (physdir == nullstr)
2753                         setpwd(dir, 0);
2754                 dir = physdir;
2755         }
2756         out1fmt("%s\n", dir);
2757         return 0;
2758 }
2759
2760
2761 /* ============ ... */
2762
2763
2764 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2765
2766 /* Syntax classes */
2767 #define CWORD     0             /* character is nothing special */
2768 #define CNL       1             /* newline character */
2769 #define CBACK     2             /* a backslash character */
2770 #define CSQUOTE   3             /* single quote */
2771 #define CDQUOTE   4             /* double quote */
2772 #define CENDQUOTE 5             /* a terminating quote */
2773 #define CBQUOTE   6             /* backwards single quote */
2774 #define CVAR      7             /* a dollar sign */
2775 #define CENDVAR   8             /* a '}' character */
2776 #define CLP       9             /* a left paren in arithmetic */
2777 #define CRP      10             /* a right paren in arithmetic */
2778 #define CENDFILE 11             /* end of file */
2779 #define CCTL     12             /* like CWORD, except it must be escaped */
2780 #define CSPCL    13             /* these terminate a word */
2781 #define CIGN     14             /* character should be ignored */
2782
2783 #define PEOF     256
2784 #if ENABLE_ASH_ALIAS
2785 # define PEOA    257
2786 #endif
2787
2788 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2789
2790 #if ENABLE_FEATURE_SH_MATH
2791 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2792 #else
2793 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2794 #endif
2795 static const uint16_t S_I_T[] ALIGN2 = {
2796 #if ENABLE_ASH_ALIAS
2797         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2798 #endif
2799         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2800         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2801         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2802         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2803         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2804         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2805         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2806         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2807         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2808         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2809         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2810 #if !USE_SIT_FUNCTION
2811         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2812         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2813         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2814 #endif
2815 #undef SIT_ITEM
2816 };
2817 /* Constants below must match table above */
2818 enum {
2819 #if ENABLE_ASH_ALIAS
2820         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2821 #endif
2822         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2823         CNL_CNL_CNL_CNL                    , /*  2 */
2824         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2825         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2826         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2827         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2828         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2829         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2830         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2831         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2832         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2833         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2834         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2835         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2836 };
2837
2838 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2839  * caller must ensure proper cast on it if c is *char_ptr!
2840  */
2841 /* Values for syntax param */
2842 #define BASESYNTAX 0    /* not in quotes */
2843 #define DQSYNTAX   1    /* in double quotes */
2844 #define SQSYNTAX   2    /* in single quotes */
2845 #define ARISYNTAX  3    /* in arithmetic */
2846 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2847
2848 #if USE_SIT_FUNCTION
2849
2850 static int
2851 SIT(int c, int syntax)
2852 {
2853         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2854         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2855         /*
2856          * This causes '/' to be prepended with CTLESC in dquoted string,
2857          * making "./file"* treated incorrectly because we feed
2858          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2859          * The "homegrown" glob implementation is okay with that,
2860          * but glibc one isn't. With '/' always treated as CWORD,
2861          * both work fine.
2862          */
2863 # if ENABLE_ASH_ALIAS
2864         static const uint8_t syntax_index_table[] ALIGN1 = {
2865                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2866                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2867                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2868                 11, 3                           /* "}~" */
2869         };
2870 # else
2871         static const uint8_t syntax_index_table[] ALIGN1 = {
2872                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2873                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2874                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2875                 10, 2                           /* "}~" */
2876         };
2877 # endif
2878         const char *s;
2879         int indx;
2880
2881         if (c == PEOF)
2882                 return CENDFILE;
2883 # if ENABLE_ASH_ALIAS
2884         if (c == PEOA)
2885                 indx = 0;
2886         else
2887 # endif
2888         {
2889                 /* Cast is purely for paranoia here,
2890                  * just in case someone passed signed char to us */
2891                 if ((unsigned char)c >= CTL_FIRST
2892                  && (unsigned char)c <= CTL_LAST
2893                 ) {
2894                         return CCTL;
2895                 }
2896                 s = strchrnul(spec_symbls, c);
2897                 if (*s == '\0')
2898                         return CWORD;
2899                 indx = syntax_index_table[s - spec_symbls];
2900         }
2901         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2902 }
2903
2904 #else   /* !USE_SIT_FUNCTION */
2905
2906 static const uint8_t syntax_index_table[] ALIGN1 = {
2907         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2908         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2909         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2910         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2911         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2912         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2913         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2918         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2919         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2920         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2921         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2922         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2941         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2942         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2943         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2945         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2947         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2948         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2949         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2950         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2951         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2953         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2954         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2955 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2956         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2968         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2969         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2970         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2971         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2972         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2973         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3001         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3002         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3003         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3006         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3034         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3035         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3036         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3037         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3038         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3039         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3040         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3041         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3042         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3043         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3044         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3045         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3046         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3165         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3166 # if ENABLE_ASH_ALIAS
3167         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3168 # endif
3169 };
3170
3171 #if 1
3172 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3173 #else /* debug version, caught one signed char bug */
3174 # define SIT(c, syntax) \
3175         ({ \
3176                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3177                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3178                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3179                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3180                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3181         })
3182 #endif
3183
3184 #endif  /* !USE_SIT_FUNCTION */
3185
3186
3187 /* ============ Alias handling */
3188
3189 #if ENABLE_ASH_ALIAS
3190
3191 #define ALIASINUSE 1
3192 #define ALIASDEAD  2
3193
3194 struct alias {
3195         struct alias *next;
3196         char *name;
3197         char *val;
3198         int flag;
3199 };
3200
3201
3202 static struct alias **atab; // [ATABSIZE];
3203 #define INIT_G_alias() do { \
3204         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3205 } while (0)
3206
3207
3208 static struct alias **
3209 __lookupalias(const char *name)
3210 {
3211         unsigned int hashval;
3212         struct alias **app;
3213         const char *p;
3214         unsigned int ch;
3215
3216         p = name;
3217
3218         ch = (unsigned char)*p;
3219         hashval = ch << 4;
3220         while (ch) {
3221                 hashval += ch;
3222                 ch = (unsigned char)*++p;
3223         }
3224         app = &atab[hashval % ATABSIZE];
3225
3226         for (; *app; app = &(*app)->next) {
3227                 if (strcmp(name, (*app)->name) == 0) {
3228                         break;
3229                 }
3230         }
3231
3232         return app;
3233 }
3234
3235 static struct alias *
3236 lookupalias(const char *name, int check)
3237 {
3238         struct alias *ap = *__lookupalias(name);
3239
3240         if (check && ap && (ap->flag & ALIASINUSE))
3241                 return NULL;
3242         return ap;
3243 }
3244
3245 static struct alias *
3246 freealias(struct alias *ap)
3247 {
3248         struct alias *next;
3249
3250         if (ap->flag & ALIASINUSE) {
3251                 ap->flag |= ALIASDEAD;
3252                 return ap;
3253         }
3254
3255         next = ap->next;
3256         free(ap->name);
3257         free(ap->val);
3258         free(ap);
3259         return next;
3260 }
3261
3262 static void
3263 setalias(const char *name, const char *val)
3264 {
3265         struct alias *ap, **app;
3266
3267         app = __lookupalias(name);
3268         ap = *app;
3269         INT_OFF;
3270         if (ap) {
3271                 if (!(ap->flag & ALIASINUSE)) {
3272                         free(ap->val);
3273                 }
3274                 ap->val = ckstrdup(val);
3275                 ap->flag &= ~ALIASDEAD;
3276         } else {
3277                 /* not found */
3278                 ap = ckzalloc(sizeof(struct alias));
3279                 ap->name = ckstrdup(name);
3280                 ap->val = ckstrdup(val);
3281                 /*ap->flag = 0; - ckzalloc did it */
3282                 /*ap->next = NULL;*/
3283                 *app = ap;
3284         }
3285         INT_ON;
3286 }
3287
3288 static int
3289 unalias(const char *name)
3290 {
3291         struct alias **app;
3292
3293         app = __lookupalias(name);
3294
3295         if (*app) {
3296                 INT_OFF;
3297                 *app = freealias(*app);
3298                 INT_ON;
3299                 return 0;
3300         }
3301
3302         return 1;
3303 }
3304
3305 static void
3306 rmaliases(void)
3307 {
3308         struct alias *ap, **app;
3309         int i;
3310
3311         INT_OFF;
3312         for (i = 0; i < ATABSIZE; i++) {
3313                 app = &atab[i];
3314                 for (ap = *app; ap; ap = *app) {
3315                         *app = freealias(*app);
3316                         if (ap == *app) {
3317                                 app = &ap->next;
3318                         }
3319                 }
3320         }
3321         INT_ON;
3322 }
3323
3324 static void
3325 printalias(const struct alias *ap)
3326 {
3327         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3328 }
3329
3330 /*
3331  * TODO - sort output
3332  */
3333 static int FAST_FUNC
3334 aliascmd(int argc UNUSED_PARAM, char **argv)
3335 {
3336         char *n, *v;
3337         int ret = 0;
3338         struct alias *ap;
3339
3340         if (!argv[1]) {
3341                 int i;
3342
3343                 for (i = 0; i < ATABSIZE; i++) {
3344                         for (ap = atab[i]; ap; ap = ap->next) {
3345                                 printalias(ap);
3346                         }
3347                 }
3348                 return 0;
3349         }
3350         while ((n = *++argv) != NULL) {
3351                 v = strchr(n+1, '=');
3352                 if (v == NULL) { /* n+1: funny ksh stuff */
3353                         ap = *__lookupalias(n);
3354                         if (ap == NULL) {
3355                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3356                                 ret = 1;
3357                         } else
3358                                 printalias(ap);
3359                 } else {
3360                         *v++ = '\0';
3361                         setalias(n, v);
3362                 }
3363         }
3364
3365         return ret;
3366 }
3367
3368 static int FAST_FUNC
3369 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3370 {
3371         int i;
3372
3373         while (nextopt("a") != '\0') {
3374                 rmaliases();
3375                 return 0;
3376         }
3377         for (i = 0; *argptr; argptr++) {
3378                 if (unalias(*argptr)) {
3379                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3380                         i = 1;
3381                 }
3382         }
3383
3384         return i;
3385 }
3386
3387 #endif /* ASH_ALIAS */
3388
3389
3390 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3391 #define FORK_FG    0
3392 #define FORK_BG    1
3393 #define FORK_NOJOB 2
3394
3395 /* mode flags for showjob(s) */
3396 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3397 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3398 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3399 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3400
3401 /*
3402  * A job structure contains information about a job.  A job is either a
3403  * single process or a set of processes contained in a pipeline.  In the
3404  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3405  * array of pids.
3406  */
3407 struct procstat {
3408         pid_t   ps_pid;         /* process id */
3409         int     ps_status;      /* last process status from wait() */
3410         char    *ps_cmd;        /* text of command being run */
3411 };
3412
3413 struct job {
3414         struct procstat ps0;    /* status of process */
3415         struct procstat *ps;    /* status or processes when more than one */
3416 #if JOBS
3417         int stopstatus;         /* status of a stopped job */
3418 #endif
3419         unsigned nprocs;        /* number of processes */
3420
3421 #define JOBRUNNING      0       /* at least one proc running */
3422 #define JOBSTOPPED      1       /* all procs are stopped */
3423 #define JOBDONE         2       /* all procs are completed */
3424         unsigned
3425                 state: 8,
3426 #if JOBS
3427                 sigint: 1,      /* job was killed by SIGINT */
3428                 jobctl: 1,      /* job running under job control */
3429 #endif
3430                 waited: 1,      /* true if this entry has been waited for */
3431                 used: 1,        /* true if this entry is in used */
3432                 changed: 1;     /* true if status has changed */
3433         struct job *prev_job;   /* previous job */
3434 };
3435
3436 static struct job *makejob(/*union node *,*/ int);
3437 static int forkshell(struct job *, union node *, int);
3438 static int waitforjob(struct job *);
3439
3440 #if !JOBS
3441 enum { doing_jobctl = 0 };
3442 #define setjobctl(on) do {} while (0)
3443 #else
3444 static smallint doing_jobctl; //references:8
3445 static void setjobctl(int);
3446 #endif
3447
3448 /*
3449  * Ignore a signal.
3450  */
3451 static void
3452 ignoresig(int signo)
3453 {
3454         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3455         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3456                 /* No, need to do it */
3457                 signal(signo, SIG_IGN);
3458         }
3459         sigmode[signo - 1] = S_HARD_IGN;
3460 }
3461
3462 /*
3463  * Only one usage site - in setsignal()
3464  */
3465 static void
3466 signal_handler(int signo)
3467 {
3468         if (signo == SIGCHLD) {
3469                 got_sigchld = 1;
3470                 if (!trap[SIGCHLD])
3471                         return;
3472         }
3473
3474         gotsig[signo - 1] = 1;
3475         pending_sig = signo;
3476
3477         if (signo == SIGINT && !trap[SIGINT]) {
3478                 if (!suppress_int) {
3479                         pending_sig = 0;
3480                         raise_interrupt(); /* does not return */
3481                 }
3482                 pending_int = 1;
3483         }
3484 }
3485
3486 /*
3487  * Set the signal handler for the specified signal.  The routine figures
3488  * out what it should be set to.
3489  */
3490 static void
3491 setsignal(int signo)
3492 {
3493         char *t;
3494         char cur_act, new_act;
3495         struct sigaction act;
3496
3497         t = trap[signo];
3498         new_act = S_DFL;
3499         if (t != NULL) { /* trap for this sig is set */
3500                 new_act = S_CATCH;
3501                 if (t[0] == '\0') /* trap is "": ignore this sig */
3502                         new_act = S_IGN;
3503         }
3504
3505         if (rootshell && new_act == S_DFL) {
3506                 switch (signo) {
3507                 case SIGINT:
3508                         if (iflag || minusc || sflag == 0)
3509                                 new_act = S_CATCH;
3510                         break;
3511                 case SIGQUIT:
3512 #if DEBUG
3513                         if (debug)
3514                                 break;
3515 #endif
3516                         /* man bash:
3517                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3518                          * commands run by bash have signal handlers
3519                          * set to the values inherited by the shell
3520                          * from its parent". */
3521                         new_act = S_IGN;
3522                         break;
3523                 case SIGTERM:
3524                         if (iflag)
3525                                 new_act = S_IGN;
3526                         break;
3527 #if JOBS
3528                 case SIGTSTP:
3529                 case SIGTTOU:
3530                         if (mflag)
3531                                 new_act = S_IGN;
3532                         break;
3533 #endif
3534                 }
3535         }
3536 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3537 //whereas we have to restore it to what shell got on entry
3538 //from the parent. See comment above
3539
3540         if (signo == SIGCHLD)
3541                 new_act = S_CATCH;
3542
3543         t = &sigmode[signo - 1];
3544         cur_act = *t;
3545         if (cur_act == 0) {
3546                 /* current setting is not yet known */
3547                 if (sigaction(signo, NULL, &act)) {
3548                         /* pretend it worked; maybe we should give a warning,
3549                          * but other shells don't. We don't alter sigmode,
3550                          * so we retry every time.
3551                          * btw, in Linux it never fails. --vda */
3552                         return;
3553                 }
3554                 if (act.sa_handler == SIG_IGN) {
3555                         cur_act = S_HARD_IGN;
3556                         if (mflag
3557                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3558                         ) {
3559                                 cur_act = S_IGN;   /* don't hard ignore these */
3560                         }
3561                 }
3562         }
3563         if (cur_act == S_HARD_IGN || cur_act == new_act)
3564                 return;
3565
3566         act.sa_handler = SIG_DFL;
3567         switch (new_act) {
3568         case S_CATCH:
3569                 act.sa_handler = signal_handler;
3570                 break;
3571         case S_IGN:
3572                 act.sa_handler = SIG_IGN;
3573                 break;
3574         }
3575
3576         /* flags and mask matter only if !DFL and !IGN, but we do it
3577          * for all cases for more deterministic behavior:
3578          */
3579         act.sa_flags = 0;
3580         sigfillset(&act.sa_mask);
3581
3582         sigaction_set(signo, &act);
3583
3584         *t = new_act;
3585 }
3586
3587 /* mode flags for set_curjob */
3588 #define CUR_DELETE 2
3589 #define CUR_RUNNING 1
3590 #define CUR_STOPPED 0
3591
3592 #if JOBS
3593 /* pgrp of shell on invocation */
3594 static int initialpgrp; //references:2
3595 static int ttyfd = -1; //5
3596 #endif
3597 /* array of jobs */
3598 static struct job *jobtab; //5
3599 /* size of array */
3600 static unsigned njobs; //4
3601 /* current job */
3602 static struct job *curjob; //lots
3603 /* number of presumed living untracked jobs */
3604 static int jobless; //4
3605
3606 #if 0
3607 /* Bash has a feature: it restores termios after a successful wait for
3608  * a foreground job which had at least one stopped or sigkilled member.
3609  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3610  * properly restoring tty state. Should we do this too?
3611  * A reproducer: ^Z an interactive python:
3612  *
3613  * # python
3614  * Python 2.7.12 (...)
3615  * >>> ^Z
3616  *      { python leaves tty in -icanon -echo state. We do survive that... }
3617  *  [1]+  Stopped                    python
3618  *      { ...however, next program (python #2) does not survive it well: }
3619  * # python
3620  * Python 2.7.12 (...)
3621  * >>> Traceback (most recent call last):
3622  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3623  *   File "<stdin>", line 1, in <module>
3624  * NameError: name 'qwerty' is not defined
3625  *
3626  * The implementation below is modeled on bash code and seems to work.
3627  * However, I'm not sure we should do this. For one: what if I'd fg
3628  * the stopped python instead? It'll be confused by "restored" tty state.
3629  */
3630 static struct termios shell_tty_info;
3631 static void
3632 get_tty_state(void)
3633 {
3634         if (rootshell && ttyfd >= 0)
3635                 tcgetattr(ttyfd, &shell_tty_info);
3636 }
3637 static void
3638 set_tty_state(void)
3639 {
3640         /* if (rootshell) - caller ensures this */
3641         if (ttyfd >= 0)
3642                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3643 }
3644 static int
3645 job_signal_status(struct job *jp)
3646 {
3647         int status;
3648         unsigned i;
3649         struct procstat *ps = jp->ps;
3650         for (i = 0; i < jp->nprocs; i++) {
3651                 status = ps[i].ps_status;
3652                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3653                         return status;
3654         }
3655         return 0;
3656 }
3657 static void
3658 restore_tty_if_stopped_or_signaled(struct job *jp)
3659 {
3660 //TODO: check what happens if we come from waitforjob() in expbackq()
3661         if (rootshell) {
3662                 int s = job_signal_status(jp);
3663                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3664                         set_tty_state();
3665         }
3666 }
3667 #else
3668 # define get_tty_state() ((void)0)
3669 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3670 #endif
3671
3672 static void
3673 set_curjob(struct job *jp, unsigned mode)
3674 {
3675         struct job *jp1;
3676         struct job **jpp, **curp;
3677
3678         /* first remove from list */
3679         jpp = curp = &curjob;
3680         while (1) {
3681                 jp1 = *jpp;
3682                 if (jp1 == jp)
3683                         break;
3684                 jpp = &jp1->prev_job;
3685         }
3686         *jpp = jp1->prev_job;
3687
3688         /* Then re-insert in correct position */
3689         jpp = curp;
3690         switch (mode) {
3691         default:
3692 #if DEBUG
3693                 abort();
3694 #endif
3695         case CUR_DELETE:
3696                 /* job being deleted */
3697                 break;
3698         case CUR_RUNNING:
3699                 /* newly created job or backgrounded job,
3700                  * put after all stopped jobs.
3701                  */
3702                 while (1) {
3703                         jp1 = *jpp;
3704 #if JOBS
3705                         if (!jp1 || jp1->state != JOBSTOPPED)
3706 #endif
3707                                 break;
3708                         jpp = &jp1->prev_job;
3709                 }
3710                 /* FALLTHROUGH */
3711 #if JOBS
3712         case CUR_STOPPED:
3713 #endif
3714                 /* newly stopped job - becomes curjob */
3715                 jp->prev_job = *jpp;
3716                 *jpp = jp;
3717                 break;
3718         }
3719 }
3720
3721 #if JOBS || DEBUG
3722 static int
3723 jobno(const struct job *jp)
3724 {
3725         return jp - jobtab + 1;
3726 }
3727 #endif
3728
3729 /*
3730  * Convert a job name to a job structure.
3731  */
3732 #if !JOBS
3733 #define getjob(name, getctl) getjob(name)
3734 #endif
3735 static struct job *
3736 getjob(const char *name, int getctl)
3737 {
3738         struct job *jp;
3739         struct job *found;
3740         const char *err_msg = "%s: no such job";
3741         unsigned num;
3742         int c;
3743         const char *p;
3744         char *(*match)(const char *, const char *);
3745
3746         jp = curjob;
3747         p = name;
3748         if (!p)
3749                 goto currentjob;
3750
3751         if (*p != '%')
3752                 goto err;
3753
3754         c = *++p;
3755         if (!c)
3756                 goto currentjob;
3757
3758         if (!p[1]) {
3759                 if (c == '+' || c == '%') {
3760  currentjob:
3761                         err_msg = "No current job";
3762                         goto check;
3763                 }
3764                 if (c == '-') {
3765                         if (jp)
3766                                 jp = jp->prev_job;
3767                         err_msg = "No previous job";
3768  check:
3769                         if (!jp)
3770                                 goto err;
3771                         goto gotit;
3772                 }
3773         }
3774
3775         if (is_number(p)) {
3776                 num = atoi(p);
3777                 if (num > 0 && num <= njobs) {
3778                         jp = jobtab + num - 1;
3779                         if (jp->used)
3780                                 goto gotit;
3781                         goto err;
3782                 }
3783         }
3784
3785         match = prefix;
3786         if (*p == '?') {
3787                 match = strstr;
3788                 p++;
3789         }
3790
3791         found = NULL;
3792         while (jp) {
3793                 if (match(jp->ps[0].ps_cmd, p)) {
3794                         if (found)
3795                                 goto err;
3796                         found = jp;
3797                         err_msg = "%s: ambiguous";
3798                 }
3799                 jp = jp->prev_job;
3800         }
3801         if (!found)
3802                 goto err;
3803         jp = found;
3804
3805  gotit:
3806 #if JOBS
3807         err_msg = "job %s not created under job control";
3808         if (getctl && jp->jobctl == 0)
3809                 goto err;
3810 #endif
3811         return jp;
3812  err:
3813         ash_msg_and_raise_error(err_msg, name);
3814 }
3815
3816 /*
3817  * Mark a job structure as unused.
3818  */
3819 static void
3820 freejob(struct job *jp)
3821 {
3822         struct procstat *ps;
3823         int i;
3824
3825         INT_OFF;
3826         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3827                 if (ps->ps_cmd != nullstr)
3828                         free(ps->ps_cmd);
3829         }
3830         if (jp->ps != &jp->ps0)
3831                 free(jp->ps);
3832         jp->used = 0;
3833         set_curjob(jp, CUR_DELETE);
3834         INT_ON;
3835 }
3836
3837 #if JOBS
3838 static void
3839 xtcsetpgrp(int fd, pid_t pgrp)
3840 {
3841         if (tcsetpgrp(fd, pgrp))
3842                 ash_msg_and_raise_perror("can't set tty process group");
3843 }
3844
3845 /*
3846  * Turn job control on and off.
3847  *
3848  * Note:  This code assumes that the third arg to ioctl is a character
3849  * pointer, which is true on Berkeley systems but not System V.  Since
3850  * System V doesn't have job control yet, this isn't a problem now.
3851  *
3852  * Called with interrupts off.
3853  */
3854 static void
3855 setjobctl(int on)
3856 {
3857         int fd;
3858         int pgrp;
3859
3860         if (on == doing_jobctl || rootshell == 0)
3861                 return;
3862         if (on) {
3863                 int ofd;
3864                 ofd = fd = open(_PATH_TTY, O_RDWR);
3865                 if (fd < 0) {
3866         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3867          * That sometimes helps to acquire controlling tty.
3868          * Obviously, a workaround for bugs when someone
3869          * failed to provide a controlling tty to bash! :) */
3870                         fd = 2;
3871                         while (!isatty(fd))
3872                                 if (--fd < 0)
3873                                         goto out;
3874                 }
3875                 /* fd is a tty at this point */
3876                 fd = fcntl(fd, F_DUPFD, 10);
3877                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3878                         close(ofd);
3879                 if (fd < 0)
3880                         goto out; /* F_DUPFD failed */
3881                 close_on_exec_on(fd);
3882                 while (1) { /* while we are in the background */
3883                         pgrp = tcgetpgrp(fd);
3884                         if (pgrp < 0) {
3885  out:
3886                                 ash_msg("can't access tty; job control turned off");
3887                                 mflag = on = 0;
3888                                 goto close;
3889                         }
3890                         if (pgrp == getpgrp())
3891                                 break;
3892                         killpg(0, SIGTTIN);
3893                 }
3894                 initialpgrp = pgrp;
3895
3896                 setsignal(SIGTSTP);
3897                 setsignal(SIGTTOU);
3898                 setsignal(SIGTTIN);
3899                 pgrp = rootpid;
3900                 setpgid(0, pgrp);
3901                 xtcsetpgrp(fd, pgrp);
3902         } else {
3903                 /* turning job control off */
3904                 fd = ttyfd;
3905                 pgrp = initialpgrp;
3906                 /* was xtcsetpgrp, but this can make exiting ash
3907                  * loop forever if pty is already deleted */
3908                 tcsetpgrp(fd, pgrp);
3909                 setpgid(0, pgrp);
3910                 setsignal(SIGTSTP);
3911                 setsignal(SIGTTOU);
3912                 setsignal(SIGTTIN);
3913  close:
3914                 if (fd >= 0)
3915                         close(fd);
3916                 fd = -1;
3917         }
3918         ttyfd = fd;
3919         doing_jobctl = on;
3920 }
3921
3922 static int FAST_FUNC
3923 killcmd(int argc, char **argv)
3924 {
3925         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3926                 int i = 1;
3927                 do {
3928                         if (argv[i][0] == '%') {
3929                                 /*
3930                                  * "kill %N" - job kill
3931                                  * Converting to pgrp / pid kill
3932                                  */
3933                                 struct job *jp;
3934                                 char *dst;
3935                                 int j, n;
3936
3937                                 jp = getjob(argv[i], 0);
3938                                 /*
3939                                  * In jobs started under job control, we signal
3940                                  * entire process group by kill -PGRP_ID.
3941                                  * This happens, f.e., in interactive shell.
3942                                  *
3943                                  * Otherwise, we signal each child via
3944                                  * kill PID1 PID2 PID3.
3945                                  * Testcases:
3946                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3947                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3948                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3949                                  */
3950                                 n = jp->nprocs; /* can't be 0 (I hope) */
3951                                 if (jp->jobctl)
3952                                         n = 1;
3953                                 dst = alloca(n * sizeof(int)*4);
3954                                 argv[i] = dst;
3955                                 for (j = 0; j < n; j++) {
3956                                         struct procstat *ps = &jp->ps[j];
3957                                         /* Skip non-running and not-stopped members
3958                                          * (i.e. dead members) of the job
3959                                          */
3960                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3961                                                 continue;
3962                                         /*
3963                                          * kill_main has matching code to expect
3964                                          * leading space. Needed to not confuse
3965                                          * negative pids with "kill -SIGNAL_NO" syntax
3966                                          */
3967                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3968                                 }
3969                                 *dst = '\0';
3970                         }
3971                 } while (argv[++i]);
3972         }
3973         return kill_main(argc, argv);
3974 }
3975
3976 static void
3977 showpipe(struct job *jp /*, FILE *out*/)
3978 {
3979         struct procstat *ps;
3980         struct procstat *psend;
3981
3982         psend = jp->ps + jp->nprocs;
3983         for (ps = jp->ps + 1; ps < psend; ps++)
3984                 printf(" | %s", ps->ps_cmd);
3985         newline_and_flush(stdout);
3986         flush_stdout_stderr();
3987 }
3988
3989
3990 static int
3991 restartjob(struct job *jp, int mode)
3992 {
3993         struct procstat *ps;
3994         int i;
3995         int status;
3996         pid_t pgid;
3997
3998         INT_OFF;
3999         if (jp->state == JOBDONE)
4000                 goto out;
4001         jp->state = JOBRUNNING;
4002         pgid = jp->ps[0].ps_pid;
4003         if (mode == FORK_FG) {
4004                 get_tty_state();
4005                 xtcsetpgrp(ttyfd, pgid);
4006         }
4007         killpg(pgid, SIGCONT);
4008         ps = jp->ps;
4009         i = jp->nprocs;
4010         do {
4011                 if (WIFSTOPPED(ps->ps_status)) {
4012                         ps->ps_status = -1;
4013                 }
4014                 ps++;
4015         } while (--i);
4016  out:
4017         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4018         INT_ON;
4019         return status;
4020 }
4021
4022 static int FAST_FUNC
4023 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4024 {
4025         struct job *jp;
4026         int mode;
4027         int retval;
4028
4029         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4030         nextopt(nullstr);
4031         argv = argptr;
4032         do {
4033                 jp = getjob(*argv, 1);
4034                 if (mode == FORK_BG) {
4035                         set_curjob(jp, CUR_RUNNING);
4036                         printf("[%d] ", jobno(jp));
4037                 }
4038                 out1str(jp->ps[0].ps_cmd);
4039                 showpipe(jp /*, stdout*/);
4040                 retval = restartjob(jp, mode);
4041         } while (*argv && *++argv);
4042         return retval;
4043 }
4044 #endif
4045
4046 static int
4047 sprint_status48(char *s, int status, int sigonly)
4048 {
4049         int col;
4050         int st;
4051
4052         col = 0;
4053         if (!WIFEXITED(status)) {
4054 #if JOBS
4055                 if (WIFSTOPPED(status))
4056                         st = WSTOPSIG(status);
4057                 else
4058 #endif
4059                         st = WTERMSIG(status);
4060                 if (sigonly) {
4061                         if (st == SIGINT || st == SIGPIPE)
4062                                 goto out;
4063 #if JOBS
4064                         if (WIFSTOPPED(status))
4065                                 goto out;
4066 #endif
4067                 }
4068                 st &= 0x7f;
4069 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4070                 col = fmtstr(s, 32, strsignal(st));
4071                 if (WCOREDUMP(status)) {
4072                         strcpy(s + col, " (core dumped)");
4073                         col += sizeof(" (core dumped)")-1;
4074                 }
4075         } else if (!sigonly) {
4076                 st = WEXITSTATUS(status);
4077                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4078         }
4079  out:
4080         return col;
4081 }
4082
4083 static int
4084 wait_block_or_sig(int *status)
4085 {
4086         int pid;
4087
4088         do {
4089                 sigset_t mask;
4090
4091                 /* Poll all children for changes in their state */
4092                 got_sigchld = 0;
4093                 /* if job control is active, accept stopped processes too */
4094                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4095                 if (pid != 0)
4096                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4097
4098                 /* Children exist, but none are ready. Sleep until interesting signal */
4099 #if 1
4100                 sigfillset(&mask);
4101                 sigprocmask(SIG_SETMASK, &mask, &mask);
4102                 while (!got_sigchld && !pending_sig)
4103                         sigsuspend(&mask);
4104                 sigprocmask(SIG_SETMASK, &mask, NULL);
4105 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4106                 while (!got_sigchld && !pending_sig)
4107                         pause();
4108 #endif
4109
4110                 /* If it was SIGCHLD, poll children again */
4111         } while (got_sigchld);
4112
4113         return pid;
4114 }
4115
4116 #define DOWAIT_NONBLOCK 0
4117 #define DOWAIT_BLOCK    1
4118 #define DOWAIT_BLOCK_OR_SIG 2
4119
4120 static int
4121 dowait(int block, struct job *job)
4122 {
4123         int pid;
4124         int status;
4125         struct job *jp;
4126         struct job *thisjob = NULL;
4127
4128         TRACE(("dowait(0x%x) called\n", block));
4129
4130         /* It's wrong to call waitpid() outside of INT_OFF region:
4131          * signal can arrive just after syscall return and handler can
4132          * longjmp away, losing stop/exit notification processing.
4133          * Thus, for "jobs" builtin, and for waiting for a fg job,
4134          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4135          *
4136          * However, for "wait" builtin it is wrong to simply call waitpid()
4137          * in INT_OFF region: "wait" needs to wait for any running job
4138          * to change state, but should exit on any trap too.
4139          * In INT_OFF region, a signal just before syscall entry can set
4140          * pending_sig variables, but we can't check them, and we would
4141          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4142          *
4143          * Because of this, we run inside INT_OFF, but use a special routine
4144          * which combines waitpid() and sigsuspend().
4145          * This is the reason why we need to have a handler for SIGCHLD:
4146          * SIG_DFL handler does not wake sigsuspend().
4147          */
4148         INT_OFF;
4149         if (block == DOWAIT_BLOCK_OR_SIG) {
4150                 pid = wait_block_or_sig(&status);
4151         } else {
4152                 int wait_flags = 0;
4153                 if (block == DOWAIT_NONBLOCK)
4154                         wait_flags = WNOHANG;
4155                 /* if job control is active, accept stopped processes too */
4156                 if (doing_jobctl)
4157                         wait_flags |= WUNTRACED;
4158                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4159                 pid = waitpid(-1, &status, wait_flags);
4160         }
4161         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4162                                 pid, status, errno, strerror(errno)));
4163         if (pid <= 0)
4164                 goto out;
4165
4166         thisjob = NULL;
4167         for (jp = curjob; jp; jp = jp->prev_job) {
4168                 int jobstate;
4169                 struct procstat *ps;
4170                 struct procstat *psend;
4171                 if (jp->state == JOBDONE)
4172                         continue;
4173                 jobstate = JOBDONE;
4174                 ps = jp->ps;
4175                 psend = ps + jp->nprocs;
4176                 do {
4177                         if (ps->ps_pid == pid) {
4178                                 TRACE(("Job %d: changing status of proc %d "
4179                                         "from 0x%x to 0x%x\n",
4180                                         jobno(jp), pid, ps->ps_status, status));
4181                                 ps->ps_status = status;
4182                                 thisjob = jp;
4183                         }
4184                         if (ps->ps_status == -1)
4185                                 jobstate = JOBRUNNING;
4186 #if JOBS
4187                         if (jobstate == JOBRUNNING)
4188                                 continue;
4189                         if (WIFSTOPPED(ps->ps_status)) {
4190                                 jp->stopstatus = ps->ps_status;
4191                                 jobstate = JOBSTOPPED;
4192                         }
4193 #endif
4194                 } while (++ps < psend);
4195                 if (!thisjob)
4196                         continue;
4197
4198                 /* Found the job where one of its processes changed its state.
4199                  * Is there at least one live and running process in this job? */
4200                 if (jobstate != JOBRUNNING) {
4201                         /* No. All live processes in the job are stopped
4202                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4203                          */
4204                         thisjob->changed = 1;
4205                         if (thisjob->state != jobstate) {
4206                                 TRACE(("Job %d: changing state from %d to %d\n",
4207                                         jobno(thisjob), thisjob->state, jobstate));
4208                                 thisjob->state = jobstate;
4209 #if JOBS
4210                                 if (jobstate == JOBSTOPPED)
4211                                         set_curjob(thisjob, CUR_STOPPED);
4212 #endif
4213                         }
4214                 }
4215                 goto out;
4216         }
4217         /* The process wasn't found in job list */
4218 #if JOBS
4219         if (!WIFSTOPPED(status))
4220                 jobless--;
4221 #endif
4222  out:
4223         INT_ON;
4224
4225         if (thisjob && thisjob == job) {
4226                 char s[48 + 1];
4227                 int len;
4228
4229                 len = sprint_status48(s, status, 1);
4230                 if (len) {
4231                         s[len] = '\n';
4232                         s[len + 1] = '\0';
4233                         out2str(s);
4234                 }
4235         }
4236         return pid;
4237 }
4238
4239 #if JOBS
4240 static void
4241 showjob(struct job *jp, int mode)
4242 {
4243         struct procstat *ps;
4244         struct procstat *psend;
4245         int col;
4246         int indent_col;
4247         char s[16 + 16 + 48];
4248         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4249
4250         ps = jp->ps;
4251
4252         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4253                 /* just output process (group) id of pipeline */
4254                 fprintf(out, "%d\n", ps->ps_pid);
4255                 return;
4256         }
4257
4258         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4259         indent_col = col;
4260
4261         if (jp == curjob)
4262                 s[col - 3] = '+';
4263         else if (curjob && jp == curjob->prev_job)
4264                 s[col - 3] = '-';
4265
4266         if (mode & SHOW_PIDS)
4267                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4268
4269         psend = ps + jp->nprocs;
4270
4271         if (jp->state == JOBRUNNING) {
4272                 strcpy(s + col, "Running");
4273                 col += sizeof("Running") - 1;
4274         } else {
4275                 int status = psend[-1].ps_status;
4276                 if (jp->state == JOBSTOPPED)
4277                         status = jp->stopstatus;
4278                 col += sprint_status48(s + col, status, 0);
4279         }
4280         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4281
4282         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4283          * or prints several "PID             | <cmdN>" lines,
4284          * depending on SHOW_PIDS bit.
4285          * We do not print status of individual processes
4286          * between PID and <cmdN>. bash does it, but not very well:
4287          * first line shows overall job status, not process status,
4288          * making it impossible to know 1st process status.
4289          */
4290         goto start;
4291         do {
4292                 /* for each process */
4293                 s[0] = '\0';
4294                 col = 33;
4295                 if (mode & SHOW_PIDS)
4296                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4297  start:
4298                 fprintf(out, "%s%*c%s%s",
4299                                 s,
4300                                 33 - col >= 0 ? 33 - col : 0, ' ',
4301                                 ps == jp->ps ? "" : "| ",
4302                                 ps->ps_cmd
4303                 );
4304         } while (++ps != psend);
4305         newline_and_flush(out);
4306
4307         jp->changed = 0;
4308
4309         if (jp->state == JOBDONE) {
4310                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4311                 freejob(jp);
4312         }
4313 }
4314
4315 /*
4316  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4317  * statuses have changed since the last call to showjobs.
4318  */
4319 static void
4320 showjobs(int mode)
4321 {
4322         struct job *jp;
4323
4324         TRACE(("showjobs(0x%x) called\n", mode));
4325
4326         /* Handle all finished jobs */
4327         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4328                 continue;
4329
4330         for (jp = curjob; jp; jp = jp->prev_job) {
4331                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4332                         showjob(jp, mode);
4333                 }
4334         }
4335 }
4336
4337 static int FAST_FUNC
4338 jobscmd(int argc UNUSED_PARAM, char **argv)
4339 {
4340         int mode, m;
4341
4342         mode = 0;
4343         while ((m = nextopt("lp")) != '\0') {
4344                 if (m == 'l')
4345                         mode |= SHOW_PIDS;
4346                 else
4347                         mode |= SHOW_ONLY_PGID;
4348         }
4349
4350         argv = argptr;
4351         if (*argv) {
4352                 do
4353                         showjob(getjob(*argv, 0), mode);
4354                 while (*++argv);
4355         } else {
4356                 showjobs(mode);
4357         }
4358
4359         return 0;
4360 }
4361 #endif /* JOBS */
4362
4363 /* Called only on finished or stopped jobs (no members are running) */
4364 static int
4365 getstatus(struct job *job)
4366 {
4367         int status;
4368         int retval;
4369         struct procstat *ps;
4370
4371         /* Fetch last member's status */
4372         ps = job->ps + job->nprocs - 1;
4373         status = ps->ps_status;
4374         if (pipefail) {
4375                 /* "set -o pipefail" mode: use last _nonzero_ status */
4376                 while (status == 0 && --ps >= job->ps)
4377                         status = ps->ps_status;
4378         }
4379
4380         retval = WEXITSTATUS(status);
4381         if (!WIFEXITED(status)) {
4382 #if JOBS
4383                 retval = WSTOPSIG(status);
4384                 if (!WIFSTOPPED(status))
4385 #endif
4386                 {
4387                         /* XXX: limits number of signals */
4388                         retval = WTERMSIG(status);
4389 #if JOBS
4390                         if (retval == SIGINT)
4391                                 job->sigint = 1;
4392 #endif
4393                 }
4394                 retval += 128;
4395         }
4396         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4397                 jobno(job), job->nprocs, status, retval));
4398         return retval;
4399 }
4400
4401 static int FAST_FUNC
4402 waitcmd(int argc UNUSED_PARAM, char **argv)
4403 {
4404         struct job *job;
4405         int retval;
4406         struct job *jp;
4407
4408         nextopt(nullstr);
4409         retval = 0;
4410
4411         argv = argptr;
4412         if (!*argv) {
4413                 /* wait for all jobs */
4414                 for (;;) {
4415                         jp = curjob;
4416                         while (1) {
4417                                 if (!jp) /* no running procs */
4418                                         goto ret;
4419                                 if (jp->state == JOBRUNNING)
4420                                         break;
4421                                 jp->waited = 1;
4422                                 jp = jp->prev_job;
4423                         }
4424         /* man bash:
4425          * "When bash is waiting for an asynchronous command via
4426          * the wait builtin, the reception of a signal for which a trap
4427          * has been set will cause the wait builtin to return immediately
4428          * with an exit status greater than 128, immediately after which
4429          * the trap is executed."
4430          */
4431                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4432         /* if child sends us a signal *and immediately exits*,
4433          * dowait() returns pid > 0. Check this case,
4434          * not "if (dowait() < 0)"!
4435          */
4436                         if (pending_sig)
4437                                 goto sigout;
4438                 }
4439         }
4440
4441         retval = 127;
4442         do {
4443                 if (**argv != '%') {
4444                         pid_t pid = number(*argv);
4445                         job = curjob;
4446                         while (1) {
4447                                 if (!job)
4448                                         goto repeat;
4449                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4450                                         break;
4451                                 job = job->prev_job;
4452                         }
4453                 } else {
4454                         job = getjob(*argv, 0);
4455                 }
4456                 /* loop until process terminated or stopped */
4457                 while (job->state == JOBRUNNING) {
4458                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4459                         if (pending_sig)
4460                                 goto sigout;
4461                 }
4462                 job->waited = 1;
4463                 retval = getstatus(job);
4464  repeat: ;
4465         } while (*++argv);
4466
4467  ret:
4468         return retval;
4469  sigout:
4470         retval = 128 + pending_sig;
4471         return retval;
4472 }
4473
4474 static struct job *
4475 growjobtab(void)
4476 {
4477         size_t len;
4478         ptrdiff_t offset;
4479         struct job *jp, *jq;
4480
4481         len = njobs * sizeof(*jp);
4482         jq = jobtab;
4483         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4484
4485         offset = (char *)jp - (char *)jq;
4486         if (offset) {
4487                 /* Relocate pointers */
4488                 size_t l = len;
4489
4490                 jq = (struct job *)((char *)jq + l);
4491                 while (l) {
4492                         l -= sizeof(*jp);
4493                         jq--;
4494 #define joff(p) ((struct job *)((char *)(p) + l))
4495 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4496                         if (joff(jp)->ps == &jq->ps0)
4497                                 jmove(joff(jp)->ps);
4498                         if (joff(jp)->prev_job)
4499                                 jmove(joff(jp)->prev_job);
4500                 }
4501                 if (curjob)
4502                         jmove(curjob);
4503 #undef joff
4504 #undef jmove
4505         }
4506
4507         njobs += 4;
4508         jobtab = jp;
4509         jp = (struct job *)((char *)jp + len);
4510         jq = jp + 3;
4511         do {
4512                 jq->used = 0;
4513         } while (--jq >= jp);
4514         return jp;
4515 }
4516
4517 /*
4518  * Return a new job structure.
4519  * Called with interrupts off.
4520  */
4521 static struct job *
4522 makejob(/*union node *node,*/ int nprocs)
4523 {
4524         int i;
4525         struct job *jp;
4526
4527         for (i = njobs, jp = jobtab; ; jp++) {
4528                 if (--i < 0) {
4529                         jp = growjobtab();
4530                         break;
4531                 }
4532                 if (jp->used == 0)
4533                         break;
4534                 if (jp->state != JOBDONE || !jp->waited)
4535                         continue;
4536 #if JOBS
4537                 if (doing_jobctl)
4538                         continue;
4539 #endif
4540                 freejob(jp);
4541                 break;
4542         }
4543         memset(jp, 0, sizeof(*jp));
4544 #if JOBS
4545         /* jp->jobctl is a bitfield.
4546          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4547         if (doing_jobctl)
4548                 jp->jobctl = 1;
4549 #endif
4550         jp->prev_job = curjob;
4551         curjob = jp;
4552         jp->used = 1;
4553         jp->ps = &jp->ps0;
4554         if (nprocs > 1) {
4555                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4556         }
4557         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4558                                 jobno(jp)));
4559         return jp;
4560 }
4561
4562 #if JOBS
4563 /*
4564  * Return a string identifying a command (to be printed by the
4565  * jobs command).
4566  */
4567 static char *cmdnextc;
4568
4569 static void
4570 cmdputs(const char *s)
4571 {
4572         static const char vstype[VSTYPE + 1][3] = {
4573                 "", "}", "-", "+", "?", "=",
4574                 "%", "%%", "#", "##"
4575                 IF_BASH_SUBSTR(, ":")
4576                 IF_BASH_PATTERN_SUBST(, "/", "//")
4577         };
4578
4579         const char *p, *str;
4580         char cc[2];
4581         char *nextc;
4582         unsigned char c;
4583         unsigned char subtype = 0;
4584         int quoted = 0;
4585
4586         cc[1] = '\0';
4587         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4588         p = s;
4589         while ((c = *p++) != '\0') {
4590                 str = NULL;
4591                 switch (c) {
4592                 case CTLESC:
4593                         c = *p++;
4594                         break;
4595                 case CTLVAR:
4596                         subtype = *p++;
4597                         if ((subtype & VSTYPE) == VSLENGTH)
4598                                 str = "${#";
4599                         else
4600                                 str = "${";
4601                         goto dostr;
4602                 case CTLENDVAR:
4603                         str = "\"}" + !(quoted & 1);
4604                         quoted >>= 1;
4605                         subtype = 0;
4606                         goto dostr;
4607                 case CTLBACKQ:
4608                         str = "$(...)";
4609                         goto dostr;
4610 #if ENABLE_FEATURE_SH_MATH
4611                 case CTLARI:
4612                         str = "$((";
4613                         goto dostr;
4614                 case CTLENDARI:
4615                         str = "))";
4616                         goto dostr;
4617 #endif
4618                 case CTLQUOTEMARK:
4619                         quoted ^= 1;
4620                         c = '"';
4621                         break;
4622                 case '=':
4623                         if (subtype == 0)
4624                                 break;
4625                         if ((subtype & VSTYPE) != VSNORMAL)
4626                                 quoted <<= 1;
4627                         str = vstype[subtype & VSTYPE];
4628                         if (subtype & VSNUL)
4629                                 c = ':';
4630                         else
4631                                 goto checkstr;
4632                         break;
4633                 case '\'':
4634                 case '\\':
4635                 case '"':
4636                 case '$':
4637                         /* These can only happen inside quotes */
4638                         cc[0] = c;
4639                         str = cc;
4640                         c = '\\';
4641                         break;
4642                 default:
4643                         break;
4644                 }
4645                 USTPUTC(c, nextc);
4646  checkstr:
4647                 if (!str)
4648                         continue;
4649  dostr:
4650                 while ((c = *str++) != '\0') {
4651                         USTPUTC(c, nextc);
4652                 }
4653         } /* while *p++ not NUL */
4654
4655         if (quoted & 1) {
4656                 USTPUTC('"', nextc);
4657         }
4658         *nextc = 0;
4659         cmdnextc = nextc;
4660 }
4661
4662 /* cmdtxt() and cmdlist() call each other */
4663 static void cmdtxt(union node *n);
4664
4665 static void
4666 cmdlist(union node *np, int sep)
4667 {
4668         for (; np; np = np->narg.next) {
4669                 if (!sep)
4670                         cmdputs(" ");
4671                 cmdtxt(np);
4672                 if (sep && np->narg.next)
4673                         cmdputs(" ");
4674         }
4675 }
4676
4677 static void
4678 cmdtxt(union node *n)
4679 {
4680         union node *np;
4681         struct nodelist *lp;
4682         const char *p;
4683
4684         if (!n)
4685                 return;
4686         switch (n->type) {
4687         default:
4688 #if DEBUG
4689                 abort();
4690 #endif
4691         case NPIPE:
4692                 lp = n->npipe.cmdlist;
4693                 for (;;) {
4694                         cmdtxt(lp->n);
4695                         lp = lp->next;
4696                         if (!lp)
4697                                 break;
4698                         cmdputs(" | ");
4699                 }
4700                 break;
4701         case NSEMI:
4702                 p = "; ";
4703                 goto binop;
4704         case NAND:
4705                 p = " && ";
4706                 goto binop;
4707         case NOR:
4708                 p = " || ";
4709  binop:
4710                 cmdtxt(n->nbinary.ch1);
4711                 cmdputs(p);
4712                 n = n->nbinary.ch2;
4713                 goto donode;
4714         case NREDIR:
4715         case NBACKGND:
4716                 n = n->nredir.n;
4717                 goto donode;
4718         case NNOT:
4719                 cmdputs("!");
4720                 n = n->nnot.com;
4721  donode:
4722                 cmdtxt(n);
4723                 break;
4724         case NIF:
4725                 cmdputs("if ");
4726                 cmdtxt(n->nif.test);
4727                 cmdputs("; then ");
4728                 if (n->nif.elsepart) {
4729                         cmdtxt(n->nif.ifpart);
4730                         cmdputs("; else ");
4731                         n = n->nif.elsepart;
4732                 } else {
4733                         n = n->nif.ifpart;
4734                 }
4735                 p = "; fi";
4736                 goto dotail;
4737         case NSUBSHELL:
4738                 cmdputs("(");
4739                 n = n->nredir.n;
4740                 p = ")";
4741                 goto dotail;
4742         case NWHILE:
4743                 p = "while ";
4744                 goto until;
4745         case NUNTIL:
4746                 p = "until ";
4747  until:
4748                 cmdputs(p);
4749                 cmdtxt(n->nbinary.ch1);
4750                 n = n->nbinary.ch2;
4751                 p = "; done";
4752  dodo:
4753                 cmdputs("; do ");
4754  dotail:
4755                 cmdtxt(n);
4756                 goto dotail2;
4757         case NFOR:
4758                 cmdputs("for ");
4759                 cmdputs(n->nfor.var);
4760                 cmdputs(" in ");
4761                 cmdlist(n->nfor.args, 1);
4762                 n = n->nfor.body;
4763                 p = "; done";
4764                 goto dodo;
4765         case NDEFUN:
4766                 cmdputs(n->narg.text);
4767                 p = "() { ... }";
4768                 goto dotail2;
4769         case NCMD:
4770                 cmdlist(n->ncmd.args, 1);
4771                 cmdlist(n->ncmd.redirect, 0);
4772                 break;
4773         case NARG:
4774                 p = n->narg.text;
4775  dotail2:
4776                 cmdputs(p);
4777                 break;
4778         case NHERE:
4779         case NXHERE:
4780                 p = "<<...";
4781                 goto dotail2;
4782         case NCASE:
4783                 cmdputs("case ");
4784                 cmdputs(n->ncase.expr->narg.text);
4785                 cmdputs(" in ");
4786                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4787                         cmdtxt(np->nclist.pattern);
4788                         cmdputs(") ");
4789                         cmdtxt(np->nclist.body);
4790                         cmdputs(";; ");
4791                 }
4792                 p = "esac";
4793                 goto dotail2;
4794         case NTO:
4795                 p = ">";
4796                 goto redir;
4797         case NCLOBBER:
4798                 p = ">|";
4799                 goto redir;
4800         case NAPPEND:
4801                 p = ">>";
4802                 goto redir;
4803 #if BASH_REDIR_OUTPUT
4804         case NTO2:
4805 #endif
4806         case NTOFD:
4807                 p = ">&";
4808                 goto redir;
4809         case NFROM:
4810                 p = "<";
4811                 goto redir;
4812         case NFROMFD:
4813                 p = "<&";
4814                 goto redir;
4815         case NFROMTO:
4816                 p = "<>";
4817  redir:
4818                 cmdputs(utoa(n->nfile.fd));
4819                 cmdputs(p);
4820                 if (n->type == NTOFD || n->type == NFROMFD) {
4821                         cmdputs(utoa(n->ndup.dupfd));
4822                         break;
4823                 }
4824                 n = n->nfile.fname;
4825                 goto donode;
4826         }
4827 }
4828
4829 static char *
4830 commandtext(union node *n)
4831 {
4832         char *name;
4833
4834         STARTSTACKSTR(cmdnextc);
4835         cmdtxt(n);
4836         name = stackblock();
4837         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4838         return ckstrdup(name);
4839 }
4840 #endif /* JOBS */
4841
4842 /*
4843  * Fork off a subshell.  If we are doing job control, give the subshell its
4844  * own process group.  Jp is a job structure that the job is to be added to.
4845  * N is the command that will be evaluated by the child.  Both jp and n may
4846  * be NULL.  The mode parameter can be one of the following:
4847  *      FORK_FG - Fork off a foreground process.
4848  *      FORK_BG - Fork off a background process.
4849  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4850  *                   process group even if job control is on.
4851  *
4852  * When job control is turned off, background processes have their standard
4853  * input redirected to /dev/null (except for the second and later processes
4854  * in a pipeline).
4855  *
4856  * Called with interrupts off.
4857  */
4858 /*
4859  * Clear traps on a fork.
4860  */
4861 static void
4862 clear_traps(void)
4863 {
4864         char **tp;
4865
4866         INT_OFF;
4867         for (tp = trap; tp < &trap[NSIG]; tp++) {
4868                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4869                         if (trap_ptr == trap)
4870                                 free(*tp);
4871                         /* else: it "belongs" to trap_ptr vector, don't free */
4872                         *tp = NULL;
4873                         if ((tp - trap) != 0)
4874                                 setsignal(tp - trap);
4875                 }
4876         }
4877         may_have_traps = 0;
4878         INT_ON;
4879 }
4880
4881 /* Lives far away from here, needed for forkchild */
4882 static void closescript(void);
4883
4884 /* Called after fork(), in child */
4885 /* jp and n are NULL when called by openhere() for heredoc support */
4886 static NOINLINE void
4887 forkchild(struct job *jp, union node *n, int mode)
4888 {
4889         int oldlvl;
4890
4891         TRACE(("Child shell %d\n", getpid()));
4892         oldlvl = shlvl;
4893         shlvl++;
4894
4895         /* man bash: "Non-builtin commands run by bash have signal handlers
4896          * set to the values inherited by the shell from its parent".
4897          * Do we do it correctly? */
4898
4899         closescript();
4900
4901         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4902          && n && n->type == NCMD        /* is it single cmd? */
4903         /* && n->ncmd.args->type == NARG - always true? */
4904          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4905          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4906         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4907         ) {
4908                 TRACE(("Trap hack\n"));
4909                 /* Awful hack for `trap` or $(trap).
4910                  *
4911                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4912                  * contains an example where "trap" is executed in a subshell:
4913                  *
4914                  * save_traps=$(trap)
4915                  * ...
4916                  * eval "$save_traps"
4917                  *
4918                  * Standard does not say that "trap" in subshell shall print
4919                  * parent shell's traps. It only says that its output
4920                  * must have suitable form, but then, in the above example
4921                  * (which is not supposed to be normative), it implies that.
4922                  *
4923                  * bash (and probably other shell) does implement it
4924                  * (traps are reset to defaults, but "trap" still shows them),
4925                  * but as a result, "trap" logic is hopelessly messed up:
4926                  *
4927                  * # trap
4928                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4929                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4930                  * # true | trap   <--- trap is in subshell - no output (ditto)
4931                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4932                  * trap -- 'echo Ho' SIGWINCH
4933                  * # echo `(trap)`         <--- in subshell in subshell - output
4934                  * trap -- 'echo Ho' SIGWINCH
4935                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4936                  * trap -- 'echo Ho' SIGWINCH
4937                  *
4938                  * The rules when to forget and when to not forget traps
4939                  * get really complex and nonsensical.
4940                  *
4941                  * Our solution: ONLY bare $(trap) or `trap` is special.
4942                  */
4943                 /* Save trap handler strings for trap builtin to print */
4944                 trap_ptr = xmemdup(trap, sizeof(trap));
4945                 /* Fall through into clearing traps */
4946         }
4947         clear_traps();
4948 #if JOBS
4949         /* do job control only in root shell */
4950         doing_jobctl = 0;
4951         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4952                 pid_t pgrp;
4953
4954                 if (jp->nprocs == 0)
4955                         pgrp = getpid();
4956                 else
4957                         pgrp = jp->ps[0].ps_pid;
4958                 /* this can fail because we are doing it in the parent also */
4959                 setpgid(0, pgrp);
4960                 if (mode == FORK_FG)
4961                         xtcsetpgrp(ttyfd, pgrp);
4962                 setsignal(SIGTSTP);
4963                 setsignal(SIGTTOU);
4964         } else
4965 #endif
4966         if (mode == FORK_BG) {
4967                 /* man bash: "When job control is not in effect,
4968                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4969                 ignoresig(SIGINT);
4970                 ignoresig(SIGQUIT);
4971                 if (jp->nprocs == 0) {
4972                         close(0);
4973                         if (open(bb_dev_null, O_RDONLY) != 0)
4974                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4975                 }
4976         }
4977         if (oldlvl == 0) {
4978                 if (iflag) { /* why if iflag only? */
4979                         setsignal(SIGINT);
4980                         setsignal(SIGTERM);
4981                 }
4982                 /* man bash:
4983                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4984                  * commands run by bash have signal handlers
4985                  * set to the values inherited by the shell
4986                  * from its parent".
4987                  * Take care of the second rule: */
4988                 setsignal(SIGQUIT);
4989         }
4990 #if JOBS
4991         if (n && n->type == NCMD
4992          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4993         ) {
4994                 TRACE(("Job hack\n"));
4995                 /* "jobs": we do not want to clear job list for it,
4996                  * instead we remove only _its_ own_ job from job list.
4997                  * This makes "jobs .... | cat" more useful.
4998                  */
4999                 freejob(curjob);
5000                 return;
5001         }
5002 #endif
5003         for (jp = curjob; jp; jp = jp->prev_job)
5004                 freejob(jp);
5005         jobless = 0;
5006 }
5007
5008 /* Called after fork(), in parent */
5009 #if !JOBS
5010 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5011 #endif
5012 static void
5013 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5014 {
5015         TRACE(("In parent shell: child = %d\n", pid));
5016         if (!jp) {
5017                 /* jp is NULL when called by openhere() for heredoc support */
5018                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5019                         continue;
5020                 jobless++;
5021                 return;
5022         }
5023 #if JOBS
5024         if (mode != FORK_NOJOB && jp->jobctl) {
5025                 int pgrp;
5026
5027                 if (jp->nprocs == 0)
5028                         pgrp = pid;
5029                 else
5030                         pgrp = jp->ps[0].ps_pid;
5031                 /* This can fail because we are doing it in the child also */
5032                 setpgid(pid, pgrp);
5033         }
5034 #endif
5035         if (mode == FORK_BG) {
5036                 backgndpid = pid;               /* set $! */
5037                 set_curjob(jp, CUR_RUNNING);
5038         }
5039         if (jp) {
5040                 struct procstat *ps = &jp->ps[jp->nprocs++];
5041                 ps->ps_pid = pid;
5042                 ps->ps_status = -1;
5043                 ps->ps_cmd = nullstr;
5044 #if JOBS
5045                 if (doing_jobctl && n)
5046                         ps->ps_cmd = commandtext(n);
5047 #endif
5048         }
5049 }
5050
5051 /* jp and n are NULL when called by openhere() for heredoc support */
5052 static int
5053 forkshell(struct job *jp, union node *n, int mode)
5054 {
5055         int pid;
5056
5057         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5058         pid = fork();
5059         if (pid < 0) {
5060                 TRACE(("Fork failed, errno=%d", errno));
5061                 if (jp)
5062                         freejob(jp);
5063                 ash_msg_and_raise_error("can't fork");
5064         }
5065         if (pid == 0) {
5066                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5067                 forkchild(jp, n, mode);
5068         } else {
5069                 forkparent(jp, n, mode, pid);
5070         }
5071         return pid;
5072 }
5073
5074 /*
5075  * Wait for job to finish.
5076  *
5077  * Under job control we have the problem that while a child process
5078  * is running interrupts generated by the user are sent to the child
5079  * but not to the shell.  This means that an infinite loop started by
5080  * an interactive user may be hard to kill.  With job control turned off,
5081  * an interactive user may place an interactive program inside a loop.
5082  * If the interactive program catches interrupts, the user doesn't want
5083  * these interrupts to also abort the loop.  The approach we take here
5084  * is to have the shell ignore interrupt signals while waiting for a
5085  * foreground process to terminate, and then send itself an interrupt
5086  * signal if the child process was terminated by an interrupt signal.
5087  * Unfortunately, some programs want to do a bit of cleanup and then
5088  * exit on interrupt; unless these processes terminate themselves by
5089  * sending a signal to themselves (instead of calling exit) they will
5090  * confuse this approach.
5091  *
5092  * Called with interrupts off.
5093  */
5094 static int
5095 waitforjob(struct job *jp)
5096 {
5097         int st;
5098
5099         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5100
5101         INT_OFF;
5102         while (jp->state == JOBRUNNING) {
5103                 /* In non-interactive shells, we _can_ get
5104                  * a keyboard signal here and be EINTRed,
5105                  * but we just loop back, waiting for command to complete.
5106                  *
5107                  * man bash:
5108                  * "If bash is waiting for a command to complete and receives
5109                  * a signal for which a trap has been set, the trap
5110                  * will not be executed until the command completes."
5111                  *
5112                  * Reality is that even if trap is not set, bash
5113                  * will not act on the signal until command completes.
5114                  * Try this. sleep5intoff.c:
5115                  * #include <signal.h>
5116                  * #include <unistd.h>
5117                  * int main() {
5118                  *         sigset_t set;
5119                  *         sigemptyset(&set);
5120                  *         sigaddset(&set, SIGINT);
5121                  *         sigaddset(&set, SIGQUIT);
5122                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5123                  *         sleep(5);
5124                  *         return 0;
5125                  * }
5126                  * $ bash -c './sleep5intoff; echo hi'
5127                  * ^C^C^C^C <--- pressing ^C once a second
5128                  * $ _
5129                  * $ bash -c './sleep5intoff; echo hi'
5130                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5131                  * $ _
5132                  */
5133                 dowait(DOWAIT_BLOCK, jp);
5134         }
5135         INT_ON;
5136
5137         st = getstatus(jp);
5138 #if JOBS
5139         if (jp->jobctl) {
5140                 xtcsetpgrp(ttyfd, rootpid);
5141                 restore_tty_if_stopped_or_signaled(jp);
5142
5143                 /*
5144                  * This is truly gross.
5145                  * If we're doing job control, then we did a TIOCSPGRP which
5146                  * caused us (the shell) to no longer be in the controlling
5147                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5148                  * intuit from the subprocess exit status whether a SIGINT
5149                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5150                  */
5151                 if (jp->sigint) /* TODO: do the same with all signals */
5152                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5153         }
5154         if (jp->state == JOBDONE)
5155 #endif
5156                 freejob(jp);
5157         return st;
5158 }
5159
5160 /*
5161  * return 1 if there are stopped jobs, otherwise 0
5162  */
5163 static int
5164 stoppedjobs(void)
5165 {
5166         struct job *jp;
5167         int retval;
5168
5169         retval = 0;
5170         if (job_warning)
5171                 goto out;
5172         jp = curjob;
5173         if (jp && jp->state == JOBSTOPPED) {
5174                 out2str("You have stopped jobs.\n");
5175                 job_warning = 2;
5176                 retval++;
5177         }
5178  out:
5179         return retval;
5180 }
5181
5182
5183 /*
5184  * Code for dealing with input/output redirection.
5185  */
5186
5187 #undef EMPTY
5188 #undef CLOSED
5189 #define EMPTY -2                /* marks an unused slot in redirtab */
5190 #define CLOSED -3               /* marks a slot of previously-closed fd */
5191
5192 /*
5193  * Handle here documents.  Normally we fork off a process to write the
5194  * data to a pipe.  If the document is short, we can stuff the data in
5195  * the pipe without forking.
5196  */
5197 /* openhere needs this forward reference */
5198 static void expandhere(union node *arg, int fd);
5199 static int
5200 openhere(union node *redir)
5201 {
5202         int pip[2];
5203         size_t len = 0;
5204
5205         if (pipe(pip) < 0)
5206                 ash_msg_and_raise_error("pipe call failed");
5207         if (redir->type == NHERE) {
5208                 len = strlen(redir->nhere.doc->narg.text);
5209                 if (len <= PIPE_BUF) {
5210                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5211                         goto out;
5212                 }
5213         }
5214         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5215                 /* child */
5216                 close(pip[0]);
5217                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5218                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5219                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5220                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5221                 signal(SIGPIPE, SIG_DFL);
5222                 if (redir->type == NHERE)
5223                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5224                 else /* NXHERE */
5225                         expandhere(redir->nhere.doc, pip[1]);
5226                 _exit(EXIT_SUCCESS);
5227         }
5228  out:
5229         close(pip[1]);
5230         return pip[0];
5231 }
5232
5233 static int
5234 openredirect(union node *redir)
5235 {
5236         struct stat sb;
5237         char *fname;
5238         int f;
5239
5240         switch (redir->nfile.type) {
5241 /* Can't happen, our single caller does this itself */
5242 //      case NTOFD:
5243 //      case NFROMFD:
5244 //              return -1;
5245         case NHERE:
5246         case NXHERE:
5247                 return openhere(redir);
5248         }
5249
5250         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5251          * allocated space. Do it only when we know it is safe.
5252          */
5253         fname = redir->nfile.expfname;
5254
5255         switch (redir->nfile.type) {
5256         default:
5257 #if DEBUG
5258                 abort();
5259 #endif
5260         case NFROM:
5261                 f = open(fname, O_RDONLY);
5262                 if (f < 0)
5263                         goto eopen;
5264                 break;
5265         case NFROMTO:
5266                 f = open(fname, O_RDWR|O_CREAT, 0666);
5267                 if (f < 0)
5268                         goto ecreate;
5269                 break;
5270         case NTO:
5271 #if BASH_REDIR_OUTPUT
5272         case NTO2:
5273 #endif
5274                 /* Take care of noclobber mode. */
5275                 if (Cflag) {
5276                         if (stat(fname, &sb) < 0) {
5277                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5278                                 if (f < 0)
5279                                         goto ecreate;
5280                         } else if (!S_ISREG(sb.st_mode)) {
5281                                 f = open(fname, O_WRONLY, 0666);
5282                                 if (f < 0)
5283                                         goto ecreate;
5284                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5285                                         close(f);
5286                                         errno = EEXIST;
5287                                         goto ecreate;
5288                                 }
5289                         } else {
5290                                 errno = EEXIST;
5291                                 goto ecreate;
5292                         }
5293                         break;
5294                 }
5295                 /* FALLTHROUGH */
5296         case NCLOBBER:
5297                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5298                 if (f < 0)
5299                         goto ecreate;
5300                 break;
5301         case NAPPEND:
5302                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5303                 if (f < 0)
5304                         goto ecreate;
5305                 break;
5306         }
5307
5308         return f;
5309  ecreate:
5310         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5311  eopen:
5312         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5313 }
5314
5315 /*
5316  * Copy a file descriptor to be >= 10. Throws exception on error.
5317  */
5318 static int
5319 savefd(int from)
5320 {
5321         int newfd;
5322         int err;
5323
5324         newfd = fcntl(from, F_DUPFD, 10);
5325         err = newfd < 0 ? errno : 0;
5326         if (err != EBADF) {
5327                 if (err)
5328                         ash_msg_and_raise_perror("%d", from);
5329                 close(from);
5330                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5331         }
5332
5333         return newfd;
5334 }
5335 static int
5336 dup2_or_raise(int from, int to)
5337 {
5338         int newfd;
5339
5340         newfd = (from != to) ? dup2(from, to) : to;
5341         if (newfd < 0) {
5342                 /* Happens when source fd is not open: try "echo >&99" */
5343                 ash_msg_and_raise_perror("%d", from);
5344         }
5345         return newfd;
5346 }
5347
5348 /* Struct def and variable are moved down to the first usage site */
5349 struct two_fd_t {
5350         int orig, copy;
5351 };
5352 struct redirtab {
5353         struct redirtab *next;
5354         int pair_count;
5355         struct two_fd_t two_fd[];
5356 };
5357 #define redirlist (G_var.redirlist)
5358 enum {
5359         COPYFD_RESTORE = (int)~(INT_MAX),
5360 };
5361
5362 static int
5363 need_to_remember(struct redirtab *rp, int fd)
5364 {
5365         int i;
5366
5367         if (!rp) /* remembering was not requested */
5368                 return 0;
5369
5370         for (i = 0; i < rp->pair_count; i++) {
5371                 if (rp->two_fd[i].orig == fd) {
5372                         /* already remembered */
5373                         return 0;
5374                 }
5375         }
5376         return 1;
5377 }
5378
5379 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5380 static int
5381 is_hidden_fd(struct redirtab *rp, int fd)
5382 {
5383         int i;
5384         struct parsefile *pf;
5385
5386         if (fd == -1)
5387                 return 0;
5388         /* Check open scripts' fds */
5389         pf = g_parsefile;
5390         while (pf) {
5391                 /* We skip pf_fd == 0 case because of the following case:
5392                  * $ ash  # running ash interactively
5393                  * $ . ./script.sh
5394                  * and in script.sh: "exec 9>&0".
5395                  * Even though top-level pf_fd _is_ 0,
5396                  * it's still ok to use it: "read" builtin uses it,
5397                  * why should we cripple "exec" builtin?
5398                  */
5399                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5400                         return 1;
5401                 }
5402                 pf = pf->prev;
5403         }
5404
5405         if (!rp)
5406                 return 0;
5407         /* Check saved fds of redirects */
5408         fd |= COPYFD_RESTORE;
5409         for (i = 0; i < rp->pair_count; i++) {
5410                 if (rp->two_fd[i].copy == fd) {
5411                         return 1;
5412                 }
5413         }
5414         return 0;
5415 }
5416
5417 /*
5418  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5419  * old file descriptors are stashed away so that the redirection can be
5420  * undone by calling popredir.
5421  */
5422 /* flags passed to redirect */
5423 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5424 #define REDIR_SAVEFD2 03        /* set preverrout */
5425 static void
5426 redirect(union node *redir, int flags)
5427 {
5428         struct redirtab *sv;
5429         int sv_pos;
5430         int i;
5431         int fd;
5432         int newfd;
5433         int copied_fd2 = -1;
5434
5435         if (!redir) {
5436                 return;
5437         }
5438
5439         sv = NULL;
5440         sv_pos = 0;
5441         INT_OFF;
5442         if (flags & REDIR_PUSH) {
5443                 union node *tmp = redir;
5444                 do {
5445                         sv_pos++;
5446 #if BASH_REDIR_OUTPUT
5447                         if (tmp->nfile.type == NTO2)
5448                                 sv_pos++;
5449 #endif
5450                         tmp = tmp->nfile.next;
5451                 } while (tmp);
5452                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5453                 sv->next = redirlist;
5454                 sv->pair_count = sv_pos;
5455                 redirlist = sv;
5456                 while (sv_pos > 0) {
5457                         sv_pos--;
5458                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5459                 }
5460         }
5461
5462         do {
5463                 int right_fd = -1;
5464                 fd = redir->nfile.fd;
5465                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5466                         right_fd = redir->ndup.dupfd;
5467                         //bb_error_msg("doing %d > %d", fd, right_fd);
5468                         /* redirect from/to same file descriptor? */
5469                         if (right_fd == fd)
5470                                 continue;
5471                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5472                         if (is_hidden_fd(sv, right_fd)) {
5473                                 errno = EBADF; /* as if it is closed */
5474                                 ash_msg_and_raise_perror("%d", right_fd);
5475                         }
5476                         newfd = -1;
5477                 } else {
5478                         newfd = openredirect(redir); /* always >= 0 */
5479                         if (fd == newfd) {
5480                                 /* Descriptor wasn't open before redirect.
5481                                  * Mark it for close in the future */
5482                                 if (need_to_remember(sv, fd)) {
5483                                         goto remember_to_close;
5484                                 }
5485                                 continue;
5486                         }
5487                 }
5488 #if BASH_REDIR_OUTPUT
5489  redirect_more:
5490 #endif
5491                 if (need_to_remember(sv, fd)) {
5492                         /* Copy old descriptor */
5493                         /* Careful to not accidentally "save"
5494                          * to the same fd as right side fd in N>&M */
5495                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5496 #if defined(F_DUPFD_CLOEXEC)
5497                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5498 #else
5499                         i = fcntl(fd, F_DUPFD, minfd);
5500 #endif
5501                         if (i == -1) {
5502                                 i = errno;
5503                                 if (i != EBADF) {
5504                                         /* Strange error (e.g. "too many files" EMFILE?) */
5505                                         if (newfd >= 0)
5506                                                 close(newfd);
5507                                         errno = i;
5508                                         ash_msg_and_raise_perror("%d", fd);
5509                                         /* NOTREACHED */
5510                                 }
5511                                 /* EBADF: it is not open - good, remember to close it */
5512  remember_to_close:
5513                                 i = CLOSED;
5514                         } else { /* fd is open, save its copy */
5515 #if !defined(F_DUPFD_CLOEXEC)
5516                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5517 #endif
5518                                 /* "exec fd>&-" should not close fds
5519                                  * which point to script file(s).
5520                                  * Force them to be restored afterwards */
5521                                 if (is_hidden_fd(sv, fd))
5522                                         i |= COPYFD_RESTORE;
5523                         }
5524                         if (fd == 2)
5525                                 copied_fd2 = i;
5526                         sv->two_fd[sv_pos].orig = fd;
5527                         sv->two_fd[sv_pos].copy = i;
5528                         sv_pos++;
5529                 }
5530                 if (newfd < 0) {
5531                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5532                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5533                                 /* Don't want to trigger debugging */
5534                                 if (fd != -1)
5535                                         close(fd);
5536                         } else {
5537                                 dup2_or_raise(redir->ndup.dupfd, fd);
5538                         }
5539                 } else if (fd != newfd) { /* move newfd to fd */
5540                         dup2_or_raise(newfd, fd);
5541 #if BASH_REDIR_OUTPUT
5542                         if (!(redir->nfile.type == NTO2 && fd == 2))
5543 #endif
5544                                 close(newfd);
5545                 }
5546 #if BASH_REDIR_OUTPUT
5547                 if (redir->nfile.type == NTO2 && fd == 1) {
5548                         /* We already redirected it to fd 1, now copy it to 2 */
5549                         newfd = 1;
5550                         fd = 2;
5551                         goto redirect_more;
5552                 }
5553 #endif
5554         } while ((redir = redir->nfile.next) != NULL);
5555
5556         INT_ON;
5557         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5558                 preverrout_fd = copied_fd2;
5559 }
5560
5561 /*
5562  * Undo the effects of the last redirection.
5563  */
5564 static void
5565 popredir(int drop, int restore)
5566 {
5567         struct redirtab *rp;
5568         int i;
5569
5570         if (redirlist == NULL)
5571                 return;
5572         INT_OFF;
5573         rp = redirlist;
5574         for (i = 0; i < rp->pair_count; i++) {
5575                 int fd = rp->two_fd[i].orig;
5576                 int copy = rp->two_fd[i].copy;
5577                 if (copy == CLOSED) {
5578                         if (!drop)
5579                                 close(fd);
5580                         continue;
5581                 }
5582                 if (copy != EMPTY) {
5583                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5584                                 copy &= ~COPYFD_RESTORE;
5585                                 /*close(fd);*/
5586                                 dup2_or_raise(copy, fd);
5587                         }
5588                         close(copy & ~COPYFD_RESTORE);
5589                 }
5590         }
5591         redirlist = rp->next;
5592         free(rp);
5593         INT_ON;
5594 }
5595
5596 /*
5597  * Undo all redirections.  Called on error or interrupt.
5598  */
5599
5600 static int
5601 redirectsafe(union node *redir, int flags)
5602 {
5603         int err;
5604         volatile int saveint;
5605         struct jmploc *volatile savehandler = exception_handler;
5606         struct jmploc jmploc;
5607
5608         SAVE_INT(saveint);
5609         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5610         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5611         if (!err) {
5612                 exception_handler = &jmploc;
5613                 redirect(redir, flags);
5614         }
5615         exception_handler = savehandler;
5616         if (err && exception_type != EXERROR)
5617                 longjmp(exception_handler->loc, 1);
5618         RESTORE_INT(saveint);
5619         return err;
5620 }
5621
5622
5623 /* ============ Routines to expand arguments to commands
5624  *
5625  * We have to deal with backquotes, shell variables, and file metacharacters.
5626  */
5627
5628 #if ENABLE_FEATURE_SH_MATH
5629 static arith_t
5630 ash_arith(const char *s)
5631 {
5632         arith_state_t math_state;
5633         arith_t result;
5634
5635         math_state.lookupvar = lookupvar;
5636         math_state.setvar    = setvar0;
5637         //math_state.endofname = endofname;
5638
5639         INT_OFF;
5640         result = arith(&math_state, s);
5641         if (math_state.errmsg)
5642                 ash_msg_and_raise_error(math_state.errmsg);
5643         INT_ON;
5644
5645         return result;
5646 }
5647 #endif
5648
5649 /*
5650  * expandarg flags
5651  */
5652 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5653 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5654 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5655 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5656 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5657  * POSIX says for this case:
5658  *  Pathname expansion shall not be performed on the word by a
5659  *  non-interactive shell; an interactive shell may perform it, but shall
5660  *  do so only when the expansion would result in one word.
5661  * Currently, our code complies to the above rule by never globbing
5662  * redirection filenames.
5663  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5664  * (this means that on a typical Linux distro, bash almost always
5665  * performs globbing, and thus diverges from what we do).
5666  */
5667 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5668 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5669 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5670 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5671 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5672 /*
5673  * rmescape() flags
5674  */
5675 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5676 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5677 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5678 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5679 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5680
5681 /* Add CTLESC when necessary. */
5682 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5683 /* Do not skip NUL characters. */
5684 #define QUOTES_KEEPNUL EXP_TILDE
5685
5686 /*
5687  * Structure specifying which parts of the string should be searched
5688  * for IFS characters.
5689  */
5690 struct ifsregion {
5691         struct ifsregion *next; /* next region in list */
5692         int begoff;             /* offset of start of region */
5693         int endoff;             /* offset of end of region */
5694         int nulonly;            /* search for nul bytes only */
5695 };
5696
5697 struct arglist {
5698         struct strlist *list;
5699         struct strlist **lastp;
5700 };
5701
5702 /* output of current string */
5703 static char *expdest;
5704 /* list of back quote expressions */
5705 static struct nodelist *argbackq;
5706 /* first struct in list of ifs regions */
5707 static struct ifsregion ifsfirst;
5708 /* last struct in list */
5709 static struct ifsregion *ifslastp;
5710 /* holds expanded arg list */
5711 static struct arglist exparg;
5712
5713 /*
5714  * Our own itoa().
5715  * cvtnum() is used even if math support is off (to prepare $? values and such).
5716  */
5717 static int
5718 cvtnum(arith_t num)
5719 {
5720         int len;
5721
5722         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5723         len = sizeof(arith_t) * 3;
5724         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5725         if (sizeof(arith_t) < 4) len += 2;
5726
5727         expdest = makestrspace(len, expdest);
5728         len = fmtstr(expdest, len, ARITH_FMT, num);
5729         STADJUST(len, expdest);
5730         return len;
5731 }
5732
5733 /*
5734  * Break the argument string into pieces based upon IFS and add the
5735  * strings to the argument list.  The regions of the string to be
5736  * searched for IFS characters have been stored by recordregion.
5737  */
5738 static void
5739 ifsbreakup(char *string, struct arglist *arglist)
5740 {
5741         struct ifsregion *ifsp;
5742         struct strlist *sp;
5743         char *start;
5744         char *p;
5745         char *q;
5746         const char *ifs, *realifs;
5747         int ifsspc;
5748         int nulonly;
5749
5750         start = string;
5751         if (ifslastp != NULL) {
5752                 ifsspc = 0;
5753                 nulonly = 0;
5754                 realifs = ifsset() ? ifsval() : defifs;
5755                 ifsp = &ifsfirst;
5756                 do {
5757                         p = string + ifsp->begoff;
5758                         nulonly = ifsp->nulonly;
5759                         ifs = nulonly ? nullstr : realifs;
5760                         ifsspc = 0;
5761                         while (p < string + ifsp->endoff) {
5762                                 q = p;
5763                                 if ((unsigned char)*p == CTLESC)
5764                                         p++;
5765                                 if (!strchr(ifs, *p)) {
5766                                         p++;
5767                                         continue;
5768                                 }
5769                                 if (!nulonly)
5770                                         ifsspc = (strchr(defifs, *p) != NULL);
5771                                 /* Ignore IFS whitespace at start */
5772                                 if (q == start && ifsspc) {
5773                                         p++;
5774                                         start = p;
5775                                         continue;
5776                                 }
5777                                 *q = '\0';
5778                                 sp = stzalloc(sizeof(*sp));
5779                                 sp->text = start;
5780                                 *arglist->lastp = sp;
5781                                 arglist->lastp = &sp->next;
5782                                 p++;
5783                                 if (!nulonly) {
5784                                         for (;;) {
5785                                                 if (p >= string + ifsp->endoff) {
5786                                                         break;
5787                                                 }
5788                                                 q = p;
5789                                                 if ((unsigned char)*p == CTLESC)
5790                                                         p++;
5791                                                 if (strchr(ifs, *p) == NULL) {
5792                                                         p = q;
5793                                                         break;
5794                                                 }
5795                                                 if (strchr(defifs, *p) == NULL) {
5796                                                         if (ifsspc) {
5797                                                                 p++;
5798                                                                 ifsspc = 0;
5799                                                         } else {
5800                                                                 p = q;
5801                                                                 break;
5802                                                         }
5803                                                 } else
5804                                                         p++;
5805                                         }
5806                                 }
5807                                 start = p;
5808                         } /* while */
5809                         ifsp = ifsp->next;
5810                 } while (ifsp != NULL);
5811                 if (nulonly)
5812                         goto add;
5813         }
5814
5815         if (!*start)
5816                 return;
5817
5818  add:
5819         sp = stzalloc(sizeof(*sp));
5820         sp->text = start;
5821         *arglist->lastp = sp;
5822         arglist->lastp = &sp->next;
5823 }
5824
5825 static void
5826 ifsfree(void)
5827 {
5828         struct ifsregion *p = ifsfirst.next;
5829
5830         if (!p)
5831                 goto out;
5832
5833         INT_OFF;
5834         do {
5835                 struct ifsregion *ifsp;
5836                 ifsp = p->next;
5837                 free(p);
5838                 p = ifsp;
5839         } while (p);
5840         ifsfirst.next = NULL;
5841         INT_ON;
5842  out:
5843         ifslastp = NULL;
5844 }
5845
5846 static size_t
5847 esclen(const char *start, const char *p)
5848 {
5849         size_t esc = 0;
5850
5851         while (p > start && (unsigned char)*--p == CTLESC) {
5852                 esc++;
5853         }
5854         return esc;
5855 }
5856
5857 /*
5858  * Remove any CTLESC characters from a string.
5859  */
5860 static char *
5861 rmescapes(char *str, int flag)
5862 {
5863         static const char qchars[] ALIGN1 = {
5864                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5865
5866         char *p, *q, *r;
5867         unsigned inquotes;
5868         unsigned protect_against_glob;
5869         unsigned globbing;
5870         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5871
5872         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5873         if (!p)
5874                 return str;
5875
5876         q = p;
5877         r = str;
5878         if (flag & RMESCAPE_ALLOC) {
5879                 size_t len = p - str;
5880                 size_t fulllen = len + strlen(p) + 1;
5881
5882                 if (flag & RMESCAPE_GROW) {
5883                         int strloc = str - (char *)stackblock();
5884                         r = makestrspace(fulllen, expdest);
5885                         /* p and str may be invalidated by makestrspace */
5886                         str = (char *)stackblock() + strloc;
5887                         p = str + len;
5888                 } else if (flag & RMESCAPE_HEAP) {
5889                         r = ckmalloc(fulllen);
5890                 } else {
5891                         r = stalloc(fulllen);
5892                 }
5893                 q = r;
5894                 if (len > 0) {
5895                         q = (char *)mempcpy(q, str, len);
5896                 }
5897         }
5898
5899         inquotes = 0;
5900         globbing = flag & RMESCAPE_GLOB;
5901         protect_against_glob = globbing;
5902         while (*p) {
5903                 if ((unsigned char)*p == CTLQUOTEMARK) {
5904 // Note: both inquotes and protect_against_glob only affect whether
5905 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5906                         inquotes = ~inquotes;
5907                         p++;
5908                         protect_against_glob = globbing;
5909                         continue;
5910                 }
5911                 if ((unsigned char)*p == CTLESC) {
5912                         p++;
5913 #if DEBUG
5914                         if (*p == '\0')
5915                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5916 #endif
5917                         if (protect_against_glob) {
5918                                 /*
5919                                  * We used to trust glob() and fnmatch() to eat
5920                                  * superfluous escapes (\z where z has no
5921                                  * special meaning anyway). But this causes
5922                                  * bugs such as string of one greek letter rho
5923                                  * (unicode-encoded as two bytes "cf,81")
5924                                  * getting encoded as "cf,CTLESC,81"
5925                                  * and here, converted to "cf,\,81" -
5926                                  * which does not go well with some flavors
5927                                  * of fnmatch() in unicode locales
5928                                  * (for example, glibc <= 2.22).
5929                                  *
5930                                  * Lets add "\" only on the chars which need it.
5931                                  * Testcases for less obvious chars are shown.
5932                                  */
5933                                 if (*p == '*'
5934                                  || *p == '?'
5935                                  || *p == '['
5936                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5937                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5938                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5939                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5940                                 /* Some libc support [^negate], that's why "^" also needs love */
5941                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5942                                 ) {
5943                                         *q++ = '\\';
5944                                 }
5945                         }
5946                 } else if (*p == '\\' && !inquotes) {
5947                         /* naked back slash */
5948                         protect_against_glob = 0;
5949                         goto copy;
5950                 }
5951 #if BASH_PATTERN_SUBST
5952                 else if (*p == '/' && slash) {
5953                         /* stop handling globbing and mark location of slash */
5954                         globbing = slash = 0;
5955                         *p = CTLESC;
5956                 }
5957 #endif
5958                 protect_against_glob = globbing;
5959  copy:
5960                 *q++ = *p++;
5961         }
5962         *q = '\0';
5963         if (flag & RMESCAPE_GROW) {
5964                 expdest = r;
5965                 STADJUST(q - r + 1, expdest);
5966         }
5967         return r;
5968 }
5969 #define pmatch(a, b) !fnmatch((a), (b), 0)
5970
5971 /*
5972  * Prepare a pattern for a expmeta (internal glob(3)) call.
5973  *
5974  * Returns an stalloced string.
5975  */
5976 static char *
5977 preglob(const char *pattern, int flag)
5978 {
5979         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5980 }
5981
5982 /*
5983  * Put a string on the stack.
5984  */
5985 static void
5986 memtodest(const char *p, size_t len, int syntax, int quotes)
5987 {
5988         char *q;
5989
5990         if (!len)
5991                 return;
5992
5993         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5994
5995         do {
5996                 unsigned char c = *p++;
5997                 if (c) {
5998                         if (quotes & QUOTES_ESC) {
5999                                 int n = SIT(c, syntax);
6000                                 if (n == CCTL
6001                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6002                                      && n == CBACK
6003                                     )
6004                                 ) {
6005                                         USTPUTC(CTLESC, q);
6006                                 }
6007                         }
6008                 } else if (!(quotes & QUOTES_KEEPNUL))
6009                         continue;
6010                 USTPUTC(c, q);
6011         } while (--len);
6012
6013         expdest = q;
6014 }
6015
6016 static size_t
6017 strtodest(const char *p, int syntax, int quotes)
6018 {
6019         size_t len = strlen(p);
6020         memtodest(p, len, syntax, quotes);
6021         return len;
6022 }
6023
6024 /*
6025  * Record the fact that we have to scan this region of the
6026  * string for IFS characters.
6027  */
6028 static void
6029 recordregion(int start, int end, int nulonly)
6030 {
6031         struct ifsregion *ifsp;
6032
6033         if (ifslastp == NULL) {
6034                 ifsp = &ifsfirst;
6035         } else {
6036                 INT_OFF;
6037                 ifsp = ckzalloc(sizeof(*ifsp));
6038                 /*ifsp->next = NULL; - ckzalloc did it */
6039                 ifslastp->next = ifsp;
6040                 INT_ON;
6041         }
6042         ifslastp = ifsp;
6043         ifslastp->begoff = start;
6044         ifslastp->endoff = end;
6045         ifslastp->nulonly = nulonly;
6046 }
6047
6048 static void
6049 removerecordregions(int endoff)
6050 {
6051         if (ifslastp == NULL)
6052                 return;
6053
6054         if (ifsfirst.endoff > endoff) {
6055                 while (ifsfirst.next) {
6056                         struct ifsregion *ifsp;
6057                         INT_OFF;
6058                         ifsp = ifsfirst.next->next;
6059                         free(ifsfirst.next);
6060                         ifsfirst.next = ifsp;
6061                         INT_ON;
6062                 }
6063                 if (ifsfirst.begoff > endoff) {
6064                         ifslastp = NULL;
6065                 } else {
6066                         ifslastp = &ifsfirst;
6067                         ifsfirst.endoff = endoff;
6068                 }
6069                 return;
6070         }
6071
6072         ifslastp = &ifsfirst;
6073         while (ifslastp->next && ifslastp->next->begoff < endoff)
6074                 ifslastp = ifslastp->next;
6075         while (ifslastp->next) {
6076                 struct ifsregion *ifsp;
6077                 INT_OFF;
6078                 ifsp = ifslastp->next->next;
6079                 free(ifslastp->next);
6080                 ifslastp->next = ifsp;
6081                 INT_ON;
6082         }
6083         if (ifslastp->endoff > endoff)
6084                 ifslastp->endoff = endoff;
6085 }
6086
6087 static char *
6088 exptilde(char *startp, char *p, int flags)
6089 {
6090         unsigned char c;
6091         char *name;
6092         struct passwd *pw;
6093         const char *home;
6094         int quotes = flags & QUOTES_ESC;
6095
6096         name = p + 1;
6097
6098         while ((c = *++p) != '\0') {
6099                 switch (c) {
6100                 case CTLESC:
6101                         return startp;
6102                 case CTLQUOTEMARK:
6103                         return startp;
6104                 case ':':
6105                         if (flags & EXP_VARTILDE)
6106                                 goto done;
6107                         break;
6108                 case '/':
6109                 case CTLENDVAR:
6110                         goto done;
6111                 }
6112         }
6113  done:
6114         *p = '\0';
6115         if (*name == '\0') {
6116                 home = lookupvar("HOME");
6117         } else {
6118                 pw = getpwnam(name);
6119                 if (pw == NULL)
6120                         goto lose;
6121                 home = pw->pw_dir;
6122         }
6123         if (!home || !*home)
6124                 goto lose;
6125         *p = c;
6126         strtodest(home, SQSYNTAX, quotes);
6127         return p;
6128  lose:
6129         *p = c;
6130         return startp;
6131 }
6132
6133 /*
6134  * Execute a command inside back quotes.  If it's a builtin command, we
6135  * want to save its output in a block obtained from malloc.  Otherwise
6136  * we fork off a subprocess and get the output of the command via a pipe.
6137  * Should be called with interrupts off.
6138  */
6139 struct backcmd {                /* result of evalbackcmd */
6140         int fd;                 /* file descriptor to read from */
6141         int nleft;              /* number of chars in buffer */
6142         char *buf;              /* buffer */
6143         struct job *jp;         /* job structure for command */
6144 };
6145
6146 /* These forward decls are needed to use "eval" code for backticks handling: */
6147 /* flags in argument to evaltree */
6148 #define EV_EXIT    01           /* exit after evaluating tree */
6149 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6150 static int evaltree(union node *, int);
6151
6152 /* An evaltree() which is known to never return.
6153  * Used to use an alias:
6154  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6155  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6156  */
6157 static ALWAYS_INLINE NORETURN void
6158 evaltreenr(union node *n, int flags)
6159 {
6160         evaltree(n, flags);
6161         bb_unreachable(abort());
6162         /* NOTREACHED */
6163 }
6164
6165 static void FAST_FUNC
6166 evalbackcmd(union node *n, struct backcmd *result)
6167 {
6168         int pip[2];
6169         struct job *jp;
6170
6171         result->fd = -1;
6172         result->buf = NULL;
6173         result->nleft = 0;
6174         result->jp = NULL;
6175         if (n == NULL) {
6176                 goto out;
6177         }
6178
6179         if (pipe(pip) < 0)
6180                 ash_msg_and_raise_error("pipe call failed");
6181         jp = makejob(/*n,*/ 1);
6182         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6183                 /* child */
6184                 FORCE_INT_ON;
6185                 close(pip[0]);
6186                 if (pip[1] != 1) {
6187                         /*close(1);*/
6188                         dup2_or_raise(pip[1], 1);
6189                         close(pip[1]);
6190                 }
6191 /* TODO: eflag clearing makes the following not abort:
6192  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6193  * which is what bash does (unless it is in POSIX mode).
6194  * dash deleted "eflag = 0" line in the commit
6195  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6196  *  [EVAL] Don't clear eflag in evalbackcmd
6197  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6198  */
6199                 eflag = 0;
6200                 ifsfree();
6201                 evaltreenr(n, EV_EXIT);
6202                 /* NOTREACHED */
6203         }
6204         /* parent */
6205         close(pip[1]);
6206         result->fd = pip[0];
6207         result->jp = jp;
6208
6209  out:
6210         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6211                 result->fd, result->buf, result->nleft, result->jp));
6212 }
6213
6214 /*
6215  * Expand stuff in backwards quotes.
6216  */
6217 static void
6218 expbackq(union node *cmd, int flag)
6219 {
6220         struct backcmd in;
6221         int i;
6222         char buf[128];
6223         char *p;
6224         char *dest;
6225         int startloc;
6226         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6227         struct stackmark smark;
6228
6229         INT_OFF;
6230         startloc = expdest - (char *)stackblock();
6231         pushstackmark(&smark, startloc);
6232         evalbackcmd(cmd, &in);
6233         popstackmark(&smark);
6234
6235         p = in.buf;
6236         i = in.nleft;
6237         if (i == 0)
6238                 goto read;
6239         for (;;) {
6240                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6241  read:
6242                 if (in.fd < 0)
6243                         break;
6244                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6245                 TRACE(("expbackq: read returns %d\n", i));
6246                 if (i <= 0)
6247                         break;
6248                 p = buf;
6249         }
6250
6251         free(in.buf);
6252         if (in.fd >= 0) {
6253                 close(in.fd);
6254                 back_exitstatus = waitforjob(in.jp);
6255         }
6256         INT_ON;
6257
6258         /* Eat all trailing newlines */
6259         dest = expdest;
6260         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6261                 STUNPUTC(dest);
6262         expdest = dest;
6263
6264         if (!(flag & EXP_QUOTED))
6265                 recordregion(startloc, dest - (char *)stackblock(), 0);
6266         TRACE(("evalbackq: size:%d:'%.*s'\n",
6267                 (int)((dest - (char *)stackblock()) - startloc),
6268                 (int)((dest - (char *)stackblock()) - startloc),
6269                 stackblock() + startloc));
6270 }
6271
6272 #if ENABLE_FEATURE_SH_MATH
6273 /*
6274  * Expand arithmetic expression.  Backup to start of expression,
6275  * evaluate, place result in (backed up) result, adjust string position.
6276  */
6277 static void
6278 expari(int flag)
6279 {
6280         char *p, *start;
6281         int begoff;
6282         int len;
6283
6284         /* ifsfree(); */
6285
6286         /*
6287          * This routine is slightly over-complicated for
6288          * efficiency.  Next we scan backwards looking for the
6289          * start of arithmetic.
6290          */
6291         start = stackblock();
6292         p = expdest - 1;
6293         *p = '\0';
6294         p--;
6295         while (1) {
6296                 int esc;
6297
6298                 while ((unsigned char)*p != CTLARI) {
6299                         p--;
6300 #if DEBUG
6301                         if (p < start) {
6302                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6303                         }
6304 #endif
6305                 }
6306
6307                 esc = esclen(start, p);
6308                 if (!(esc % 2)) {
6309                         break;
6310                 }
6311
6312                 p -= esc + 1;
6313         }
6314
6315         begoff = p - start;
6316
6317         removerecordregions(begoff);
6318
6319         expdest = p;
6320
6321         if (flag & QUOTES_ESC)
6322                 rmescapes(p + 1, 0);
6323
6324         len = cvtnum(ash_arith(p + 1));
6325
6326         if (!(flag & EXP_QUOTED))
6327                 recordregion(begoff, begoff + len, 0);
6328 }
6329 #endif
6330
6331 /* argstr needs it */
6332 static char *evalvar(char *p, int flags);
6333
6334 /*
6335  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6336  * characters to allow for further processing.  Otherwise treat
6337  * $@ like $* since no splitting will be performed.
6338  */
6339 static void
6340 argstr(char *p, int flags)
6341 {
6342         static const char spclchars[] ALIGN1 = {
6343                 '=',
6344                 ':',
6345                 CTLQUOTEMARK,
6346                 CTLENDVAR,
6347                 CTLESC,
6348                 CTLVAR,
6349                 CTLBACKQ,
6350 #if ENABLE_FEATURE_SH_MATH
6351                 CTLENDARI,
6352 #endif
6353                 '\0'
6354         };
6355         const char *reject = spclchars;
6356         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6357         int inquotes;
6358         size_t length;
6359         int startloc;
6360
6361         if (!(flags & EXP_VARTILDE)) {
6362                 reject += 2;
6363         } else if (flags & EXP_VARTILDE2) {
6364                 reject++;
6365         }
6366         inquotes = 0;
6367         length = 0;
6368         if (flags & EXP_TILDE) {
6369                 char *q;
6370
6371                 flags &= ~EXP_TILDE;
6372  tilde:
6373                 q = p;
6374                 if (*q == '~')
6375                         p = exptilde(p, q, flags);
6376         }
6377  start:
6378         startloc = expdest - (char *)stackblock();
6379         for (;;) {
6380                 unsigned char c;
6381
6382                 length += strcspn(p + length, reject);
6383                 c = p[length];
6384                 if (c) {
6385                         if (!(c & 0x80)
6386                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6387                         ) {
6388                                 /* c == '=' || c == ':' || c == CTLENDARI */
6389                                 length++;
6390                         }
6391                 }
6392                 if (length > 0) {
6393                         int newloc;
6394                         expdest = stack_nputstr(p, length, expdest);
6395                         newloc = expdest - (char *)stackblock();
6396                         if (breakall && !inquotes && newloc > startloc) {
6397                                 recordregion(startloc, newloc, 0);
6398                         }
6399                         startloc = newloc;
6400                 }
6401                 p += length + 1;
6402                 length = 0;
6403
6404                 switch (c) {
6405                 case '\0':
6406                         goto breakloop;
6407                 case '=':
6408                         if (flags & EXP_VARTILDE2) {
6409                                 p--;
6410                                 continue;
6411                         }
6412                         flags |= EXP_VARTILDE2;
6413                         reject++;
6414                         /* fall through */
6415                 case ':':
6416                         /*
6417                          * sort of a hack - expand tildes in variable
6418                          * assignments (after the first '=' and after ':'s).
6419                          */
6420                         if (*--p == '~') {
6421                                 goto tilde;
6422                         }
6423                         continue;
6424                 }
6425
6426                 switch (c) {
6427                 case CTLENDVAR: /* ??? */
6428                         goto breakloop;
6429                 case CTLQUOTEMARK:
6430                         inquotes ^= EXP_QUOTED;
6431                         /* "$@" syntax adherence hack */
6432                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6433                                 p = evalvar(p + 1, flags | inquotes) + 1;
6434                                 goto start;
6435                         }
6436  addquote:
6437                         if (flags & QUOTES_ESC) {
6438                                 p--;
6439                                 length++;
6440                                 startloc++;
6441                         }
6442                         break;
6443                 case CTLESC:
6444                         startloc++;
6445                         length++;
6446
6447                         /*
6448                          * Quoted parameter expansion pattern: remove quote
6449                          * unless inside inner quotes or we have a literal
6450                          * backslash.
6451                          */
6452                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6453                             EXP_QPAT && *p != '\\')
6454                                 break;
6455
6456                         goto addquote;
6457                 case CTLVAR:
6458                         TRACE(("argstr: evalvar('%s')\n", p));
6459                         p = evalvar(p, flags | inquotes);
6460                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6461                         goto start;
6462                 case CTLBACKQ:
6463                         expbackq(argbackq->n, flags | inquotes);
6464                         argbackq = argbackq->next;
6465                         goto start;
6466 #if ENABLE_FEATURE_SH_MATH
6467                 case CTLENDARI:
6468                         p--;
6469                         expari(flags | inquotes);
6470                         goto start;
6471 #endif
6472                 }
6473         }
6474  breakloop: ;
6475 }
6476
6477 static char *
6478 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6479                 char *pattern, int quotes, int zero)
6480 {
6481         char *loc, *loc2;
6482         char c;
6483
6484         loc = startp;
6485         loc2 = rmesc;
6486         do {
6487                 int match;
6488                 const char *s = loc2;
6489
6490                 c = *loc2;
6491                 if (zero) {
6492                         *loc2 = '\0';
6493                         s = rmesc;
6494                 }
6495                 match = pmatch(pattern, s);
6496
6497                 *loc2 = c;
6498                 if (match)
6499                         return loc;
6500                 if (quotes && (unsigned char)*loc == CTLESC)
6501                         loc++;
6502                 loc++;
6503                 loc2++;
6504         } while (c);
6505         return NULL;
6506 }
6507
6508 static char *
6509 scanright(char *startp, char *rmesc, char *rmescend,
6510                 char *pattern, int quotes, int match_at_start)
6511 {
6512 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6513         int try2optimize = match_at_start;
6514 #endif
6515         int esc = 0;
6516         char *loc;
6517         char *loc2;
6518
6519         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6520          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6521          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6522          * Logic:
6523          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6524          * and on each iteration they go back two/one char until they reach the beginning.
6525          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6526          */
6527         /* TODO: document in what other circumstances we are called. */
6528
6529         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6530                 int match;
6531                 char c = *loc2;
6532                 const char *s = loc2;
6533                 if (match_at_start) {
6534                         *loc2 = '\0';
6535                         s = rmesc;
6536                 }
6537                 match = pmatch(pattern, s);
6538                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6539                 *loc2 = c;
6540                 if (match)
6541                         return loc;
6542 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6543                 if (try2optimize) {
6544                         /* Maybe we can optimize this:
6545                          * if pattern ends with unescaped *, we can avoid checking
6546                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6547                          * it won't match truncated "raw_value_of_" strings too.
6548                          */
6549                         unsigned plen = strlen(pattern);
6550                         /* Does it end with "*"? */
6551                         if (plen != 0 && pattern[--plen] == '*') {
6552                                 /* "xxxx*" is not escaped */
6553                                 /* "xxx\*" is escaped */
6554                                 /* "xx\\*" is not escaped */
6555                                 /* "x\\\*" is escaped */
6556                                 int slashes = 0;
6557                                 while (plen != 0 && pattern[--plen] == '\\')
6558                                         slashes++;
6559                                 if (!(slashes & 1))
6560                                         break; /* ends with unescaped "*" */
6561                         }
6562                         try2optimize = 0;
6563                 }
6564 #endif
6565                 loc--;
6566                 if (quotes) {
6567                         if (--esc < 0) {
6568                                 esc = esclen(startp, loc);
6569                         }
6570                         if (esc % 2) {
6571                                 esc--;
6572                                 loc--;
6573                         }
6574                 }
6575         }
6576         return NULL;
6577 }
6578
6579 static void varunset(const char *, const char *, const char *, int) NORETURN;
6580 static void
6581 varunset(const char *end, const char *var, const char *umsg, int varflags)
6582 {
6583         const char *msg;
6584         const char *tail;
6585
6586         tail = nullstr;
6587         msg = "parameter not set";
6588         if (umsg) {
6589                 if ((unsigned char)*end == CTLENDVAR) {
6590                         if (varflags & VSNUL)
6591                                 tail = " or null";
6592                 } else {
6593                         msg = umsg;
6594                 }
6595         }
6596         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6597 }
6598
6599 static const char *
6600 subevalvar(char *p, char *varname, int strloc, int subtype,
6601                 int startloc, int varflags, int flag)
6602 {
6603         struct nodelist *saveargbackq = argbackq;
6604         int quotes = flag & QUOTES_ESC;
6605         char *startp;
6606         char *loc;
6607         char *rmesc, *rmescend;
6608         char *str;
6609         int amount, resetloc;
6610         IF_BASH_PATTERN_SUBST(int workloc;)
6611         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6612         int zero;
6613         char *(*scan)(char*, char*, char*, char*, int, int);
6614
6615         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6616         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6617
6618         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6619                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6620         );
6621         STPUTC('\0', expdest);
6622         argbackq = saveargbackq;
6623         startp = (char *)stackblock() + startloc;
6624
6625         switch (subtype) {
6626         case VSASSIGN:
6627                 setvar0(varname, startp);
6628                 amount = startp - expdest;
6629                 STADJUST(amount, expdest);
6630                 return startp;
6631
6632         case VSQUESTION:
6633                 varunset(p, varname, startp, varflags);
6634                 /* NOTREACHED */
6635
6636 #if BASH_SUBSTR
6637         case VSSUBSTR: {
6638                 int pos, len, orig_len;
6639                 char *colon;
6640
6641                 loc = str = stackblock() + strloc;
6642
6643 # if !ENABLE_FEATURE_SH_MATH
6644 #  define ash_arith number
6645 # endif
6646                 /* Read POS in ${var:POS:LEN} */
6647                 colon = strchr(loc, ':');
6648                 if (colon) *colon = '\0';
6649                 pos = ash_arith(loc);
6650                 if (colon) *colon = ':';
6651
6652                 /* Read LEN in ${var:POS:LEN} */
6653                 len = str - startp - 1;
6654                 /* *loc != '\0', guaranteed by parser */
6655                 if (quotes) {
6656                         char *ptr;
6657
6658                         /* Adjust the length by the number of escapes */
6659                         for (ptr = startp; ptr < (str - 1); ptr++) {
6660                                 if ((unsigned char)*ptr == CTLESC) {
6661                                         len--;
6662                                         ptr++;
6663                                 }
6664                         }
6665                 }
6666                 orig_len = len;
6667                 if (*loc++ == ':') {
6668                         /* ${var::LEN} */
6669                         len = ash_arith(loc);
6670                 } else {
6671                         /* Skip POS in ${var:POS:LEN} */
6672                         len = orig_len;
6673                         while (*loc && *loc != ':') {
6674                                 loc++;
6675                         }
6676                         if (*loc++ == ':') {
6677                                 len = ash_arith(loc);
6678                         }
6679                 }
6680 #  undef ash_arith
6681
6682                 if (pos < 0) {
6683                         /* ${VAR:$((-n)):l} starts n chars from the end */
6684                         pos = orig_len + pos;
6685                 }
6686                 if ((unsigned)pos >= orig_len) {
6687                         /* apart from obvious ${VAR:999999:l},
6688                          * covers ${VAR:$((-9999999)):l} - result is ""
6689                          * (bash compat)
6690                          */
6691                         pos = 0;
6692                         len = 0;
6693                 }
6694                 if (len < 0) {
6695                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6696                         len = (orig_len - pos) + len;
6697                 }
6698                 if ((unsigned)len > (orig_len - pos))
6699                         len = orig_len - pos;
6700
6701                 for (str = startp; pos; str++, pos--) {
6702                         if (quotes && (unsigned char)*str == CTLESC)
6703                                 str++;
6704                 }
6705                 for (loc = startp; len; len--) {
6706                         if (quotes && (unsigned char)*str == CTLESC)
6707                                 *loc++ = *str++;
6708                         *loc++ = *str++;
6709                 }
6710                 *loc = '\0';
6711                 amount = loc - expdest;
6712                 STADJUST(amount, expdest);
6713                 return loc;
6714         }
6715 #endif /* BASH_SUBSTR */
6716         }
6717
6718         resetloc = expdest - (char *)stackblock();
6719
6720 #if BASH_PATTERN_SUBST
6721         /* We'll comeback here if we grow the stack while handling
6722          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6723          * stack will need rebasing, and we'll need to remove our work
6724          * areas each time
6725          */
6726  restart:
6727 #endif
6728
6729         amount = expdest - ((char *)stackblock() + resetloc);
6730         STADJUST(-amount, expdest);
6731         startp = (char *)stackblock() + startloc;
6732
6733         rmesc = startp;
6734         rmescend = (char *)stackblock() + strloc;
6735         if (quotes) {
6736                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6737                 if (rmesc != startp) {
6738                         rmescend = expdest;
6739                         startp = (char *)stackblock() + startloc;
6740                 }
6741         }
6742         rmescend--;
6743         str = (char *)stackblock() + strloc;
6744         /*
6745          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6746          * The result is a_\_z_c (not a\_\_z_c)!
6747          *
6748          * The search pattern and replace string treat backslashes differently!
6749          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6750          * and string.  It's only used on the first call.
6751          */
6752         preglob(str, IF_BASH_PATTERN_SUBST(
6753                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6754                         RMESCAPE_SLASH : ) 0);
6755
6756 #if BASH_PATTERN_SUBST
6757         workloc = expdest - (char *)stackblock();
6758         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6759                 int len;
6760                 char *idx, *end;
6761
6762                 if (!repl) {
6763                         repl = strchr(str, CTLESC);
6764                         if (repl)
6765                                 *repl++ = '\0';
6766                         else
6767                                 repl = nullstr;
6768                 }
6769                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6770
6771                 /* If there's no pattern to match, return the expansion unmolested */
6772                 if (str[0] == '\0')
6773                         return NULL;
6774
6775                 len = 0;
6776                 idx = startp;
6777                 end = str - 1;
6778                 while (idx < end) {
6779  try_to_match:
6780                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6781                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6782                         if (!loc) {
6783                                 /* No match, advance */
6784                                 char *restart_detect = stackblock();
6785  skip_matching:
6786                                 STPUTC(*idx, expdest);
6787                                 if (quotes && (unsigned char)*idx == CTLESC) {
6788                                         idx++;
6789                                         len++;
6790                                         STPUTC(*idx, expdest);
6791                                 }
6792                                 if (stackblock() != restart_detect)
6793                                         goto restart;
6794                                 idx++;
6795                                 len++;
6796                                 rmesc++;
6797                                 /* continue; - prone to quadratic behavior, smarter code: */
6798                                 if (idx >= end)
6799                                         break;
6800                                 if (str[0] == '*') {
6801                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6802                                          * it would never match "ong_string" etc, no point in trying.
6803                                          */
6804                                         goto skip_matching;
6805                                 }
6806                                 goto try_to_match;
6807                         }
6808
6809                         if (subtype == VSREPLACEALL) {
6810                                 while (idx < loc) {
6811                                         if (quotes && (unsigned char)*idx == CTLESC)
6812                                                 idx++;
6813                                         idx++;
6814                                         rmesc++;
6815                                 }
6816                         } else {
6817                                 idx = loc;
6818                         }
6819
6820                         //bb_error_msg("repl:'%s'", repl);
6821                         for (loc = (char*)repl; *loc; loc++) {
6822                                 char *restart_detect = stackblock();
6823                                 if (quotes && *loc == '\\') {
6824                                         STPUTC(CTLESC, expdest);
6825                                         len++;
6826                                 }
6827                                 STPUTC(*loc, expdest);
6828                                 if (stackblock() != restart_detect)
6829                                         goto restart;
6830                                 len++;
6831                         }
6832
6833                         if (subtype == VSREPLACE) {
6834                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6835                                 while (*idx) {
6836                                         char *restart_detect = stackblock();
6837                                         STPUTC(*idx, expdest);
6838                                         if (stackblock() != restart_detect)
6839                                                 goto restart;
6840                                         len++;
6841                                         idx++;
6842                                 }
6843                                 break;
6844                         }
6845                 }
6846
6847                 /* We've put the replaced text into a buffer at workloc, now
6848                  * move it to the right place and adjust the stack.
6849                  */
6850                 STPUTC('\0', expdest);
6851                 startp = (char *)stackblock() + startloc;
6852                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6853                 //bb_error_msg("startp:'%s'", startp);
6854                 amount = expdest - (startp + len);
6855                 STADJUST(-amount, expdest);
6856                 return startp;
6857         }
6858 #endif /* BASH_PATTERN_SUBST */
6859
6860         subtype -= VSTRIMRIGHT;
6861 #if DEBUG
6862         if (subtype < 0 || subtype > 7)
6863                 abort();
6864 #endif
6865         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6866         zero = subtype >> 1;
6867         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6868         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6869
6870         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6871         if (loc) {
6872                 if (zero) {
6873                         memmove(startp, loc, str - loc);
6874                         loc = startp + (str - loc) - 1;
6875                 }
6876                 *loc = '\0';
6877                 amount = loc - expdest;
6878                 STADJUST(amount, expdest);
6879         }
6880         return loc;
6881 }
6882
6883 /*
6884  * Add the value of a specialized variable to the stack string.
6885  * name parameter (examples):
6886  * ash -c 'echo $1'      name:'1='
6887  * ash -c 'echo $qwe'    name:'qwe='
6888  * ash -c 'echo $$'      name:'$='
6889  * ash -c 'echo ${$}'    name:'$='
6890  * ash -c 'echo ${$##q}' name:'$=q'
6891  * ash -c 'echo ${#$}'   name:'$='
6892  * note: examples with bad shell syntax:
6893  * ash -c 'echo ${#$1}'  name:'$=1'
6894  * ash -c 'echo ${#1#}'  name:'1=#'
6895  */
6896 static NOINLINE ssize_t
6897 varvalue(char *name, int varflags, int flags, int *quotedp)
6898 {
6899         const char *p;
6900         int num;
6901         int i;
6902         ssize_t len = 0;
6903         int sep;
6904         int quoted = *quotedp;
6905         int subtype = varflags & VSTYPE;
6906         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6907         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6908         int syntax;
6909
6910         sep = (flags & EXP_FULL) << CHAR_BIT;
6911         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6912
6913         switch (*name) {
6914         case '$':
6915                 num = rootpid;
6916                 goto numvar;
6917         case '?':
6918                 num = exitstatus;
6919                 goto numvar;
6920         case '#':
6921                 num = shellparam.nparam;
6922                 goto numvar;
6923         case '!':
6924                 num = backgndpid;
6925                 if (num == 0)
6926                         return -1;
6927  numvar:
6928                 len = cvtnum(num);
6929                 goto check_1char_name;
6930         case '-':
6931                 expdest = makestrspace(NOPTS, expdest);
6932                 for (i = NOPTS - 1; i >= 0; i--) {
6933                         if (optlist[i]) {
6934                                 USTPUTC(optletters(i), expdest);
6935                                 len++;
6936                         }
6937                 }
6938  check_1char_name:
6939 #if 0
6940                 /* handles cases similar to ${#$1} */
6941                 if (name[2] != '\0')
6942                         raise_error_syntax("bad substitution");
6943 #endif
6944                 break;
6945         case '@':
6946                 if (quoted && sep)
6947                         goto param;
6948                 /* fall through */
6949         case '*': {
6950                 char **ap;
6951                 char sepc;
6952
6953                 if (quoted)
6954                         sep = 0;
6955                 sep |= ifsset() ? ifsval()[0] : ' ';
6956  param:
6957                 sepc = sep;
6958                 *quotedp = !sepc;
6959                 ap = shellparam.p;
6960                 if (!ap)
6961                         return -1;
6962                 while ((p = *ap++) != NULL) {
6963                         len += strtodest(p, syntax, quotes);
6964
6965                         if (*ap && sep) {
6966                                 len++;
6967                                 memtodest(&sepc, 1, syntax, quotes);
6968                         }
6969                 }
6970                 break;
6971         } /* case '*' */
6972         case '0':
6973         case '1':
6974         case '2':
6975         case '3':
6976         case '4':
6977         case '5':
6978         case '6':
6979         case '7':
6980         case '8':
6981         case '9':
6982                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6983                 if (num < 0 || num > shellparam.nparam)
6984                         return -1;
6985                 p = num ? shellparam.p[num - 1] : arg0;
6986                 goto value;
6987         default:
6988                 /* NB: name has form "VAR=..." */
6989                 p = lookupvar(name);
6990  value:
6991                 if (!p)
6992                         return -1;
6993
6994                 len = strtodest(p, syntax, quotes);
6995 #if ENABLE_UNICODE_SUPPORT
6996                 if (subtype == VSLENGTH && len > 0) {
6997                         reinit_unicode_for_ash();
6998                         if (unicode_status == UNICODE_ON) {
6999                                 STADJUST(-len, expdest);
7000                                 discard = 0;
7001                                 len = unicode_strlen(p);
7002                         }
7003                 }
7004 #endif
7005                 break;
7006         }
7007
7008         if (discard)
7009                 STADJUST(-len, expdest);
7010         return len;
7011 }
7012
7013 /*
7014  * Expand a variable, and return a pointer to the next character in the
7015  * input string.
7016  */
7017 static char *
7018 evalvar(char *p, int flag)
7019 {
7020         char varflags;
7021         char subtype;
7022         int quoted;
7023         char easy;
7024         char *var;
7025         int patloc;
7026         int startloc;
7027         ssize_t varlen;
7028
7029         varflags = (unsigned char) *p++;
7030         subtype = varflags & VSTYPE;
7031
7032         if (!subtype)
7033                 raise_error_syntax("bad substitution");
7034
7035         quoted = flag & EXP_QUOTED;
7036         var = p;
7037         easy = (!quoted || (*var == '@' && shellparam.nparam));
7038         startloc = expdest - (char *)stackblock();
7039         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7040
7041  again:
7042         varlen = varvalue(var, varflags, flag, &quoted);
7043         if (varflags & VSNUL)
7044                 varlen--;
7045
7046         if (subtype == VSPLUS) {
7047                 varlen = -1 - varlen;
7048                 goto vsplus;
7049         }
7050
7051         if (subtype == VSMINUS) {
7052  vsplus:
7053                 if (varlen < 0) {
7054                         argstr(
7055                                 p,
7056                                 flag | EXP_TILDE | EXP_WORD
7057                         );
7058                         goto end;
7059                 }
7060                 goto record;
7061         }
7062
7063         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7064                 if (varlen >= 0)
7065                         goto record;
7066
7067                 subevalvar(p, var, 0, subtype, startloc, varflags,
7068                            flag & ~QUOTES_ESC);
7069                 varflags &= ~VSNUL;
7070                 /*
7071                  * Remove any recorded regions beyond
7072                  * start of variable
7073                  */
7074                 removerecordregions(startloc);
7075                 goto again;
7076         }
7077
7078         if (varlen < 0 && uflag)
7079                 varunset(p, var, 0, 0);
7080
7081         if (subtype == VSLENGTH) {
7082                 cvtnum(varlen > 0 ? varlen : 0);
7083                 goto record;
7084         }
7085
7086         if (subtype == VSNORMAL) {
7087  record:
7088                 if (!easy)
7089                         goto end;
7090                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7091                 goto end;
7092         }
7093
7094 #if DEBUG
7095         switch (subtype) {
7096         case VSTRIMLEFT:
7097         case VSTRIMLEFTMAX:
7098         case VSTRIMRIGHT:
7099         case VSTRIMRIGHTMAX:
7100 #if BASH_SUBSTR
7101         case VSSUBSTR:
7102 #endif
7103 #if BASH_PATTERN_SUBST
7104         case VSREPLACE:
7105         case VSREPLACEALL:
7106 #endif
7107                 break;
7108         default:
7109                 abort();
7110         }
7111 #endif
7112
7113         if (varlen >= 0) {
7114                 /*
7115                  * Terminate the string and start recording the pattern
7116                  * right after it
7117                  */
7118                 STPUTC('\0', expdest);
7119                 patloc = expdest - (char *)stackblock();
7120                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7121                                 startloc, varflags, flag)) {
7122                         int amount = expdest - (
7123                                 (char *)stackblock() + patloc - 1
7124                         );
7125                         STADJUST(-amount, expdest);
7126                 }
7127                 /* Remove any recorded regions beyond start of variable */
7128                 removerecordregions(startloc);
7129                 goto record;
7130         }
7131
7132  end:
7133         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7134                 int nesting = 1;
7135                 for (;;) {
7136                         unsigned char c = *p++;
7137                         if (c == CTLESC)
7138                                 p++;
7139                         else if (c == CTLBACKQ) {
7140                                 if (varlen >= 0)
7141                                         argbackq = argbackq->next;
7142                         } else if (c == CTLVAR) {
7143                                 if ((*p++ & VSTYPE) != VSNORMAL)
7144                                         nesting++;
7145                         } else if (c == CTLENDVAR) {
7146                                 if (--nesting == 0)
7147                                         break;
7148                         }
7149                 }
7150         }
7151         return p;
7152 }
7153
7154 /*
7155  * Add a file name to the list.
7156  */
7157 static void
7158 addfname(const char *name)
7159 {
7160         struct strlist *sp;
7161
7162         sp = stzalloc(sizeof(*sp));
7163         sp->text = sstrdup(name);
7164         *exparg.lastp = sp;
7165         exparg.lastp = &sp->next;
7166 }
7167
7168 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7169 static int
7170 hasmeta(const char *p)
7171 {
7172         static const char chars[] ALIGN1 = {
7173                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7174         };
7175
7176         for (;;) {
7177                 p = strpbrk(p, chars);
7178                 if (!p)
7179                         break;
7180                 switch ((unsigned char) *p) {
7181                 case CTLQUOTEMARK:
7182                         for (;;) {
7183                                 p++;
7184                                 if (*p == CTLQUOTEMARK)
7185                                         break;
7186                                 if (*p == CTLESC)
7187                                         p++;
7188                                 if (*p == '\0') /* huh? */
7189                                         return 0;
7190                         }
7191                         break;
7192                 case '\\':
7193                 case CTLESC:
7194                         p++;
7195                         if (*p == '\0')
7196                                 return 0;
7197                         break;
7198                 case '[':
7199                         if (!strchr(p + 1, ']')) {
7200                                 /* It's not a properly closed [] pattern,
7201                                  * but other metas may follow. Continue checking.
7202                                  * my[file* _is_ globbed by bash
7203                                  * and matches filenames like "my[file1".
7204                                  */
7205                                 break;
7206                         }
7207                         /* fallthrough */
7208                 default:
7209                 /* case '*': */
7210                 /* case '?': */
7211                         return 1;
7212                 }
7213                 p++;
7214         }
7215
7216         return 0;
7217 }
7218
7219 /* If we want to use glob() from libc... */
7220 #if !ENABLE_ASH_INTERNAL_GLOB
7221
7222 /* Add the result of glob() to the list */
7223 static void
7224 addglob(const glob_t *pglob)
7225 {
7226         char **p = pglob->gl_pathv;
7227
7228         do {
7229                 addfname(*p);
7230         } while (*++p);
7231 }
7232 static void
7233 expandmeta(struct strlist *str /*, int flag*/)
7234 {
7235         /* TODO - EXP_REDIR */
7236
7237         while (str) {
7238                 char *p;
7239                 glob_t pglob;
7240                 int i;
7241
7242                 if (fflag)
7243                         goto nometa;
7244
7245                 if (!hasmeta(str->text))
7246                         goto nometa;
7247
7248                 INT_OFF;
7249                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7250 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7251 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7252 //
7253 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7254 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7255 // Which means you need to unescape the string, right? Not so fast:
7256 // if there _is_ a file named "file\?" (with backslash), it is returned
7257 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7258 // You DON'T KNOW by looking at the result whether you need to unescape it.
7259 //
7260 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7261 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7262 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7263 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7264 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7265 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7266                 i = glob(p, 0, NULL, &pglob);
7267                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7268                 if (p != str->text)
7269                         free(p);
7270                 switch (i) {
7271                 case 0:
7272 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7273                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7274                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7275                                 goto nometa2;
7276 #endif
7277                         addglob(&pglob);
7278                         globfree(&pglob);
7279                         INT_ON;
7280                         break;
7281                 case GLOB_NOMATCH:
7282  //nometa2:
7283                         globfree(&pglob);
7284                         INT_ON;
7285  nometa:
7286                         *exparg.lastp = str;
7287                         rmescapes(str->text, 0);
7288                         exparg.lastp = &str->next;
7289                         break;
7290                 default:        /* GLOB_NOSPACE */
7291                         globfree(&pglob);
7292                         INT_ON;
7293                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7294                 }
7295                 str = str->next;
7296         }
7297 }
7298
7299 #else
7300 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7301
7302 /*
7303  * Do metacharacter (i.e. *, ?, [...]) expansion.
7304  */
7305 static void
7306 expmeta(char *expdir, char *enddir, char *name)
7307 {
7308         char *p;
7309         const char *cp;
7310         char *start;
7311         char *endname;
7312         int metaflag;
7313         struct stat statb;
7314         DIR *dirp;
7315         struct dirent *dp;
7316         int atend;
7317         int matchdot;
7318         int esc;
7319
7320         metaflag = 0;
7321         start = name;
7322         for (p = name; esc = 0, *p; p += esc + 1) {
7323                 if (*p == '*' || *p == '?')
7324                         metaflag = 1;
7325                 else if (*p == '[') {
7326                         char *q = p + 1;
7327                         if (*q == '!')
7328                                 q++;
7329                         for (;;) {
7330                                 if (*q == '\\')
7331                                         q++;
7332                                 if (*q == '/' || *q == '\0')
7333                                         break;
7334                                 if (*++q == ']') {
7335                                         metaflag = 1;
7336                                         break;
7337                                 }
7338                         }
7339                 } else {
7340                         if (*p == '\\')
7341                                 esc++;
7342                         if (p[esc] == '/') {
7343                                 if (metaflag)
7344                                         break;
7345                                 start = p + esc + 1;
7346                         }
7347                 }
7348         }
7349         if (metaflag == 0) {    /* we've reached the end of the file name */
7350                 if (enddir != expdir)
7351                         metaflag++;
7352                 p = name;
7353                 do {
7354                         if (*p == '\\')
7355                                 p++;
7356                         *enddir++ = *p;
7357                 } while (*p++);
7358                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7359                         addfname(expdir);
7360                 return;
7361         }
7362         endname = p;
7363         if (name < start) {
7364                 p = name;
7365                 do {
7366                         if (*p == '\\')
7367                                 p++;
7368                         *enddir++ = *p++;
7369                 } while (p < start);
7370         }
7371         if (enddir == expdir) {
7372                 cp = ".";
7373         } else if (enddir == expdir + 1 && *expdir == '/') {
7374                 cp = "/";
7375         } else {
7376                 cp = expdir;
7377                 enddir[-1] = '\0';
7378         }
7379         dirp = opendir(cp);
7380         if (dirp == NULL)
7381                 return;
7382         if (enddir != expdir)
7383                 enddir[-1] = '/';
7384         if (*endname == 0) {
7385                 atend = 1;
7386         } else {
7387                 atend = 0;
7388                 *endname = '\0';
7389                 endname += esc + 1;
7390         }
7391         matchdot = 0;
7392         p = start;
7393         if (*p == '\\')
7394                 p++;
7395         if (*p == '.')
7396                 matchdot++;
7397         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7398                 if (dp->d_name[0] == '.' && !matchdot)
7399                         continue;
7400                 if (pmatch(start, dp->d_name)) {
7401                         if (atend) {
7402                                 strcpy(enddir, dp->d_name);
7403                                 addfname(expdir);
7404                         } else {
7405                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7406                                         continue;
7407                                 p[-1] = '/';
7408                                 expmeta(expdir, p, endname);
7409                         }
7410                 }
7411         }
7412         closedir(dirp);
7413         if (!atend)
7414                 endname[-esc - 1] = esc ? '\\' : '/';
7415 }
7416
7417 static struct strlist *
7418 msort(struct strlist *list, int len)
7419 {
7420         struct strlist *p, *q = NULL;
7421         struct strlist **lpp;
7422         int half;
7423         int n;
7424
7425         if (len <= 1)
7426                 return list;
7427         half = len >> 1;
7428         p = list;
7429         for (n = half; --n >= 0;) {
7430                 q = p;
7431                 p = p->next;
7432         }
7433         q->next = NULL;                 /* terminate first half of list */
7434         q = msort(list, half);          /* sort first half of list */
7435         p = msort(p, len - half);               /* sort second half */
7436         lpp = &list;
7437         for (;;) {
7438 #if ENABLE_LOCALE_SUPPORT
7439                 if (strcoll(p->text, q->text) < 0)
7440 #else
7441                 if (strcmp(p->text, q->text) < 0)
7442 #endif
7443                                                 {
7444                         *lpp = p;
7445                         lpp = &p->next;
7446                         p = *lpp;
7447                         if (p == NULL) {
7448                                 *lpp = q;
7449                                 break;
7450                         }
7451                 } else {
7452                         *lpp = q;
7453                         lpp = &q->next;
7454                         q = *lpp;
7455                         if (q == NULL) {
7456                                 *lpp = p;
7457                                 break;
7458                         }
7459                 }
7460         }
7461         return list;
7462 }
7463
7464 /*
7465  * Sort the results of file name expansion.  It calculates the number of
7466  * strings to sort and then calls msort (short for merge sort) to do the
7467  * work.
7468  */
7469 static struct strlist *
7470 expsort(struct strlist *str)
7471 {
7472         int len;
7473         struct strlist *sp;
7474
7475         len = 0;
7476         for (sp = str; sp; sp = sp->next)
7477                 len++;
7478         return msort(str, len);
7479 }
7480
7481 static void
7482 expandmeta(struct strlist *str /*, int flag*/)
7483 {
7484         /* TODO - EXP_REDIR */
7485
7486         while (str) {
7487                 char *expdir;
7488                 struct strlist **savelastp;
7489                 struct strlist *sp;
7490                 char *p;
7491
7492                 if (fflag)
7493                         goto nometa;
7494                 if (!hasmeta(str->text))
7495                         goto nometa;
7496                 savelastp = exparg.lastp;
7497
7498                 INT_OFF;
7499                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7500                 {
7501                         int i = strlen(str->text);
7502 //BUGGY estimation of how long expanded name can be
7503                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7504                 }
7505                 expmeta(expdir, expdir, p);
7506                 free(expdir);
7507                 if (p != str->text)
7508                         free(p);
7509                 INT_ON;
7510                 if (exparg.lastp == savelastp) {
7511                         /*
7512                          * no matches
7513                          */
7514  nometa:
7515                         *exparg.lastp = str;
7516                         rmescapes(str->text, 0);
7517                         exparg.lastp = &str->next;
7518                 } else {
7519                         *exparg.lastp = NULL;
7520                         *savelastp = sp = expsort(*savelastp);
7521                         while (sp->next != NULL)
7522                                 sp = sp->next;
7523                         exparg.lastp = &sp->next;
7524                 }
7525                 str = str->next;
7526         }
7527 }
7528 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7529
7530 /*
7531  * Perform variable substitution and command substitution on an argument,
7532  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7533  * perform splitting and file name expansion.  When arglist is NULL, perform
7534  * here document expansion.
7535  */
7536 static void
7537 expandarg(union node *arg, struct arglist *arglist, int flag)
7538 {
7539         struct strlist *sp;
7540         char *p;
7541
7542         argbackq = arg->narg.backquote;
7543         STARTSTACKSTR(expdest);
7544         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7545         argstr(arg->narg.text, flag);
7546         p = _STPUTC('\0', expdest);
7547         expdest = p - 1;
7548         if (arglist == NULL) {
7549                 /* here document expanded */
7550                 goto out;
7551         }
7552         p = grabstackstr(p);
7553         TRACE(("expandarg: p:'%s'\n", p));
7554         exparg.lastp = &exparg.list;
7555         /*
7556          * TODO - EXP_REDIR
7557          */
7558         if (flag & EXP_FULL) {
7559                 ifsbreakup(p, &exparg);
7560                 *exparg.lastp = NULL;
7561                 exparg.lastp = &exparg.list;
7562                 expandmeta(exparg.list /*, flag*/);
7563         } else {
7564                 sp = stzalloc(sizeof(*sp));
7565                 sp->text = p;
7566                 *exparg.lastp = sp;
7567                 exparg.lastp = &sp->next;
7568         }
7569         *exparg.lastp = NULL;
7570         if (exparg.list) {
7571                 *arglist->lastp = exparg.list;
7572                 arglist->lastp = exparg.lastp;
7573         }
7574
7575  out:
7576         ifsfree();
7577 }
7578
7579 /*
7580  * Expand shell variables and backquotes inside a here document.
7581  */
7582 static void
7583 expandhere(union node *arg, int fd)
7584 {
7585         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7586         full_write(fd, stackblock(), expdest - (char *)stackblock());
7587 }
7588
7589 /*
7590  * Returns true if the pattern matches the string.
7591  */
7592 static int
7593 patmatch(char *pattern, const char *string)
7594 {
7595         char *p = preglob(pattern, 0);
7596         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7597         return pmatch(p, string);
7598 }
7599
7600 /*
7601  * See if a pattern matches in a case statement.
7602  */
7603 static int
7604 casematch(union node *pattern, char *val)
7605 {
7606         struct stackmark smark;
7607         int result;
7608
7609         setstackmark(&smark);
7610         argbackq = pattern->narg.backquote;
7611         STARTSTACKSTR(expdest);
7612         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7613         STACKSTRNUL(expdest);
7614         ifsfree();
7615         result = patmatch(stackblock(), val);
7616         popstackmark(&smark);
7617         return result;
7618 }
7619
7620
7621 /* ============ find_command */
7622
7623 struct builtincmd {
7624         const char *name;
7625         int (*builtin)(int, char **) FAST_FUNC;
7626         /* unsigned flags; */
7627 };
7628 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7629 /* "regular" builtins always take precedence over commands,
7630  * regardless of PATH=....%builtin... position */
7631 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7632 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7633
7634 struct cmdentry {
7635         smallint cmdtype;       /* CMDxxx */
7636         union param {
7637                 int index;
7638                 /* index >= 0 for commands without path (slashes) */
7639                 /* (TODO: what exactly does the value mean? PATH position?) */
7640                 /* index == -1 for commands with slashes */
7641                 /* index == (-2 - applet_no) for NOFORK applets */
7642                 const struct builtincmd *cmd;
7643                 struct funcnode *func;
7644         } u;
7645 };
7646 /* values of cmdtype */
7647 #define CMDUNKNOWN      -1      /* no entry in table for command */
7648 #define CMDNORMAL       0       /* command is an executable program */
7649 #define CMDFUNCTION     1       /* command is a shell function */
7650 #define CMDBUILTIN      2       /* command is a shell builtin */
7651
7652 /* action to find_command() */
7653 #define DO_ERR          0x01    /* prints errors */
7654 #define DO_ABS          0x02    /* checks absolute paths */
7655 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7656 #define DO_ALTPATH      0x08    /* using alternate path */
7657 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7658
7659 static void find_command(char *, struct cmdentry *, int, const char *);
7660
7661
7662 /* ============ Hashing commands */
7663
7664 /*
7665  * When commands are first encountered, they are entered in a hash table.
7666  * This ensures that a full path search will not have to be done for them
7667  * on each invocation.
7668  *
7669  * We should investigate converting to a linear search, even though that
7670  * would make the command name "hash" a misnomer.
7671  */
7672
7673 struct tblentry {
7674         struct tblentry *next;  /* next entry in hash chain */
7675         union param param;      /* definition of builtin function */
7676         smallint cmdtype;       /* CMDxxx */
7677         char rehash;            /* if set, cd done since entry created */
7678         char cmdname[1];        /* name of command */
7679 };
7680
7681 static struct tblentry **cmdtable;
7682 #define INIT_G_cmdtable() do { \
7683         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7684 } while (0)
7685
7686 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7687
7688
7689 static void
7690 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7691 {
7692 #if ENABLE_FEATURE_SH_STANDALONE
7693         if (applet_no >= 0) {
7694                 if (APPLET_IS_NOEXEC(applet_no)) {
7695                         clearenv();
7696                         while (*envp)
7697                                 putenv(*envp++);
7698                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7699                         run_applet_no_and_exit(applet_no, cmd, argv);
7700                 }
7701                 /* re-exec ourselves with the new arguments */
7702                 execve(bb_busybox_exec_path, argv, envp);
7703                 /* If they called chroot or otherwise made the binary no longer
7704                  * executable, fall through */
7705         }
7706 #endif
7707
7708  repeat:
7709 #ifdef SYSV
7710         do {
7711                 execve(cmd, argv, envp);
7712         } while (errno == EINTR);
7713 #else
7714         execve(cmd, argv, envp);
7715 #endif
7716         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7717                 /* Run "cmd" as a shell script:
7718                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7719                  * "If the execve() function fails with ENOEXEC, the shell
7720                  * shall execute a command equivalent to having a shell invoked
7721                  * with the command name as its first operand,
7722                  * with any remaining arguments passed to the new shell"
7723                  *
7724                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7725                  * just call ourselves.
7726                  *
7727                  * Note that bash reads ~80 chars of the file, and if it sees
7728                  * a zero byte before it sees newline, it doesn't try to
7729                  * interpret it, but fails with "cannot execute binary file"
7730                  * message and exit code 126. For one, this prevents attempts
7731                  * to interpret foreign ELF binaries as shell scripts.
7732                  */
7733                 argv[0] = (char*) cmd;
7734                 cmd = bb_busybox_exec_path;
7735                 /* NB: this is only possible because all callers of shellexec()
7736                  * ensure that the argv[-1] slot exists!
7737                  */
7738                 argv--;
7739                 argv[0] = (char*) "ash";
7740                 goto repeat;
7741         }
7742 }
7743
7744 /*
7745  * Exec a program.  Never returns.  If you change this routine, you may
7746  * have to change the find_command routine as well.
7747  * argv[-1] must exist and be writable! See tryexec() for why.
7748  */
7749 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7750 static void shellexec(char *prog, char **argv, const char *path, int idx)
7751 {
7752         char *cmdname;
7753         int e;
7754         char **envp;
7755         int exerrno;
7756         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7757
7758         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7759         if (strchr(prog, '/') != NULL
7760 #if ENABLE_FEATURE_SH_STANDALONE
7761          || (applet_no = find_applet_by_name(prog)) >= 0
7762 #endif
7763         ) {
7764                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7765                 if (applet_no >= 0) {
7766                         /* We tried execing ourself, but it didn't work.
7767                          * Maybe /proc/self/exe doesn't exist?
7768                          * Try $PATH search.
7769                          */
7770                         goto try_PATH;
7771                 }
7772                 e = errno;
7773         } else {
7774  try_PATH:
7775                 e = ENOENT;
7776                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7777                         if (--idx < 0 && pathopt == NULL) {
7778                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7779                                 if (errno != ENOENT && errno != ENOTDIR)
7780                                         e = errno;
7781                         }
7782                         stunalloc(cmdname);
7783                 }
7784         }
7785
7786         /* Map to POSIX errors */
7787         switch (e) {
7788         case EACCES:
7789                 exerrno = 126;
7790                 break;
7791         case ENOENT:
7792                 exerrno = 127;
7793                 break;
7794         default:
7795                 exerrno = 2;
7796                 break;
7797         }
7798         exitstatus = exerrno;
7799         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7800                 prog, e, suppress_int));
7801         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7802         /* NOTREACHED */
7803 }
7804
7805 static void
7806 printentry(struct tblentry *cmdp)
7807 {
7808         int idx;
7809         const char *path;
7810         char *name;
7811
7812         idx = cmdp->param.index;
7813         path = pathval();
7814         do {
7815                 name = path_advance(&path, cmdp->cmdname);
7816                 stunalloc(name);
7817         } while (--idx >= 0);
7818         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7819 }
7820
7821 /*
7822  * Clear out command entries.  The argument specifies the first entry in
7823  * PATH which has changed.
7824  */
7825 static void
7826 clearcmdentry(int firstchange)
7827 {
7828         struct tblentry **tblp;
7829         struct tblentry **pp;
7830         struct tblentry *cmdp;
7831
7832         INT_OFF;
7833         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7834                 pp = tblp;
7835                 while ((cmdp = *pp) != NULL) {
7836                         if ((cmdp->cmdtype == CMDNORMAL &&
7837                              cmdp->param.index >= firstchange)
7838                          || (cmdp->cmdtype == CMDBUILTIN &&
7839                              builtinloc >= firstchange)
7840                         ) {
7841                                 *pp = cmdp->next;
7842                                 free(cmdp);
7843                         } else {
7844                                 pp = &cmdp->next;
7845                         }
7846                 }
7847         }
7848         INT_ON;
7849 }
7850
7851 /*
7852  * Locate a command in the command hash table.  If "add" is nonzero,
7853  * add the command to the table if it is not already present.  The
7854  * variable "lastcmdentry" is set to point to the address of the link
7855  * pointing to the entry, so that delete_cmd_entry can delete the
7856  * entry.
7857  *
7858  * Interrupts must be off if called with add != 0.
7859  */
7860 static struct tblentry **lastcmdentry;
7861
7862 static struct tblentry *
7863 cmdlookup(const char *name, int add)
7864 {
7865         unsigned int hashval;
7866         const char *p;
7867         struct tblentry *cmdp;
7868         struct tblentry **pp;
7869
7870         p = name;
7871         hashval = (unsigned char)*p << 4;
7872         while (*p)
7873                 hashval += (unsigned char)*p++;
7874         hashval &= 0x7FFF;
7875         pp = &cmdtable[hashval % CMDTABLESIZE];
7876         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7877                 if (strcmp(cmdp->cmdname, name) == 0)
7878                         break;
7879                 pp = &cmdp->next;
7880         }
7881         if (add && cmdp == NULL) {
7882                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7883                                 + strlen(name)
7884                                 /* + 1 - already done because
7885                                  * tblentry::cmdname is char[1] */);
7886                 /*cmdp->next = NULL; - ckzalloc did it */
7887                 cmdp->cmdtype = CMDUNKNOWN;
7888                 strcpy(cmdp->cmdname, name);
7889         }
7890         lastcmdentry = pp;
7891         return cmdp;
7892 }
7893
7894 /*
7895  * Delete the command entry returned on the last lookup.
7896  */
7897 static void
7898 delete_cmd_entry(void)
7899 {
7900         struct tblentry *cmdp;
7901
7902         INT_OFF;
7903         cmdp = *lastcmdentry;
7904         *lastcmdentry = cmdp->next;
7905         if (cmdp->cmdtype == CMDFUNCTION)
7906                 freefunc(cmdp->param.func);
7907         free(cmdp);
7908         INT_ON;
7909 }
7910
7911 /*
7912  * Add a new command entry, replacing any existing command entry for
7913  * the same name - except special builtins.
7914  */
7915 static void
7916 addcmdentry(char *name, struct cmdentry *entry)
7917 {
7918         struct tblentry *cmdp;
7919
7920         cmdp = cmdlookup(name, 1);
7921         if (cmdp->cmdtype == CMDFUNCTION) {
7922                 freefunc(cmdp->param.func);
7923         }
7924         cmdp->cmdtype = entry->cmdtype;
7925         cmdp->param = entry->u;
7926         cmdp->rehash = 0;
7927 }
7928
7929 static int FAST_FUNC
7930 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7931 {
7932         struct tblentry **pp;
7933         struct tblentry *cmdp;
7934         int c;
7935         struct cmdentry entry;
7936         char *name;
7937
7938         if (nextopt("r") != '\0') {
7939                 clearcmdentry(0);
7940                 return 0;
7941         }
7942
7943         if (*argptr == NULL) {
7944                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7945                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7946                                 if (cmdp->cmdtype == CMDNORMAL)
7947                                         printentry(cmdp);
7948                         }
7949                 }
7950                 return 0;
7951         }
7952
7953         c = 0;
7954         while ((name = *argptr) != NULL) {
7955                 cmdp = cmdlookup(name, 0);
7956                 if (cmdp != NULL
7957                  && (cmdp->cmdtype == CMDNORMAL
7958                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7959                 ) {
7960                         delete_cmd_entry();
7961                 }
7962                 find_command(name, &entry, DO_ERR, pathval());
7963                 if (entry.cmdtype == CMDUNKNOWN)
7964                         c = 1;
7965                 argptr++;
7966         }
7967         return c;
7968 }
7969
7970 /*
7971  * Called when a cd is done.  Marks all commands so the next time they
7972  * are executed they will be rehashed.
7973  */
7974 static void
7975 hashcd(void)
7976 {
7977         struct tblentry **pp;
7978         struct tblentry *cmdp;
7979
7980         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7981                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7982                         if (cmdp->cmdtype == CMDNORMAL
7983                          || (cmdp->cmdtype == CMDBUILTIN
7984                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7985                              && builtinloc > 0)
7986                         ) {
7987                                 cmdp->rehash = 1;
7988                         }
7989                 }
7990         }
7991 }
7992
7993 /*
7994  * Fix command hash table when PATH changed.
7995  * Called before PATH is changed.  The argument is the new value of PATH;
7996  * pathval() still returns the old value at this point.
7997  * Called with interrupts off.
7998  */
7999 static void FAST_FUNC
8000 changepath(const char *new)
8001 {
8002         const char *old;
8003         int firstchange;
8004         int idx;
8005         int idx_bltin;
8006
8007         old = pathval();
8008         firstchange = 9999;     /* assume no change */
8009         idx = 0;
8010         idx_bltin = -1;
8011         for (;;) {
8012                 if (*old != *new) {
8013                         firstchange = idx;
8014                         if ((*old == '\0' && *new == ':')
8015                          || (*old == ':' && *new == '\0')
8016                         ) {
8017                                 firstchange++;
8018                         }
8019                         old = new;      /* ignore subsequent differences */
8020                 }
8021                 if (*new == '\0')
8022                         break;
8023                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8024                         idx_bltin = idx;
8025                 if (*new == ':')
8026                         idx++;
8027                 new++;
8028                 old++;
8029         }
8030         if (builtinloc < 0 && idx_bltin >= 0)
8031                 builtinloc = idx_bltin;             /* zap builtins */
8032         if (builtinloc >= 0 && idx_bltin < 0)
8033                 firstchange = 0;
8034         clearcmdentry(firstchange);
8035         builtinloc = idx_bltin;
8036 }
8037 enum {
8038         TEOF,
8039         TNL,
8040         TREDIR,
8041         TWORD,
8042         TSEMI,
8043         TBACKGND,
8044         TAND,
8045         TOR,
8046         TPIPE,
8047         TLP,
8048         TRP,
8049         TENDCASE,
8050         TENDBQUOTE,
8051         TNOT,
8052         TCASE,
8053         TDO,
8054         TDONE,
8055         TELIF,
8056         TELSE,
8057         TESAC,
8058         TFI,
8059         TFOR,
8060 #if BASH_FUNCTION
8061         TFUNCTION,
8062 #endif
8063         TIF,
8064         TIN,
8065         TTHEN,
8066         TUNTIL,
8067         TWHILE,
8068         TBEGIN,
8069         TEND
8070 };
8071 typedef smallint token_id_t;
8072
8073 /* Nth bit indicates if token marks the end of a list */
8074 enum {
8075         tokendlist = 0
8076         /*  0 */ | (1u << TEOF)
8077         /*  1 */ | (0u << TNL)
8078         /*  2 */ | (0u << TREDIR)
8079         /*  3 */ | (0u << TWORD)
8080         /*  4 */ | (0u << TSEMI)
8081         /*  5 */ | (0u << TBACKGND)
8082         /*  6 */ | (0u << TAND)
8083         /*  7 */ | (0u << TOR)
8084         /*  8 */ | (0u << TPIPE)
8085         /*  9 */ | (0u << TLP)
8086         /* 10 */ | (1u << TRP)
8087         /* 11 */ | (1u << TENDCASE)
8088         /* 12 */ | (1u << TENDBQUOTE)
8089         /* 13 */ | (0u << TNOT)
8090         /* 14 */ | (0u << TCASE)
8091         /* 15 */ | (1u << TDO)
8092         /* 16 */ | (1u << TDONE)
8093         /* 17 */ | (1u << TELIF)
8094         /* 18 */ | (1u << TELSE)
8095         /* 19 */ | (1u << TESAC)
8096         /* 20 */ | (1u << TFI)
8097         /* 21 */ | (0u << TFOR)
8098 #if BASH_FUNCTION
8099         /* 22 */ | (0u << TFUNCTION)
8100 #endif
8101         /* 23 */ | (0u << TIF)
8102         /* 24 */ | (0u << TIN)
8103         /* 25 */ | (1u << TTHEN)
8104         /* 26 */ | (0u << TUNTIL)
8105         /* 27 */ | (0u << TWHILE)
8106         /* 28 */ | (0u << TBEGIN)
8107         /* 29 */ | (1u << TEND)
8108         , /* thus far 29 bits used */
8109 };
8110
8111 static const char *const tokname_array[] = {
8112         "end of file",
8113         "newline",
8114         "redirection",
8115         "word",
8116         ";",
8117         "&",
8118         "&&",
8119         "||",
8120         "|",
8121         "(",
8122         ")",
8123         ";;",
8124         "`",
8125 #define KWDOFFSET 13
8126         /* the following are keywords */
8127         "!",
8128         "case",
8129         "do",
8130         "done",
8131         "elif",
8132         "else",
8133         "esac",
8134         "fi",
8135         "for",
8136 #if BASH_FUNCTION
8137         "function",
8138 #endif
8139         "if",
8140         "in",
8141         "then",
8142         "until",
8143         "while",
8144         "{",
8145         "}",
8146 };
8147
8148 /* Wrapper around strcmp for qsort/bsearch/... */
8149 static int
8150 pstrcmp(const void *a, const void *b)
8151 {
8152         return strcmp((char*)a, *(char**)b);
8153 }
8154
8155 static const char *const *
8156 findkwd(const char *s)
8157 {
8158         return bsearch(s, tokname_array + KWDOFFSET,
8159                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8160                         sizeof(tokname_array[0]), pstrcmp);
8161 }
8162
8163 /*
8164  * Locate and print what a word is...
8165  */
8166 static int
8167 describe_command(char *command, const char *path, int describe_command_verbose)
8168 {
8169         struct cmdentry entry;
8170 #if ENABLE_ASH_ALIAS
8171         const struct alias *ap;
8172 #endif
8173
8174         path = path ? path : pathval();
8175
8176         if (describe_command_verbose) {
8177                 out1str(command);
8178         }
8179
8180         /* First look at the keywords */
8181         if (findkwd(command)) {
8182                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8183                 goto out;
8184         }
8185
8186 #if ENABLE_ASH_ALIAS
8187         /* Then look at the aliases */
8188         ap = lookupalias(command, 0);
8189         if (ap != NULL) {
8190                 if (!describe_command_verbose) {
8191                         out1str("alias ");
8192                         printalias(ap);
8193                         return 0;
8194                 }
8195                 out1fmt(" is an alias for %s", ap->val);
8196                 goto out;
8197         }
8198 #endif
8199         /* Brute force */
8200         find_command(command, &entry, DO_ABS, path);
8201
8202         switch (entry.cmdtype) {
8203         case CMDNORMAL: {
8204                 int j = entry.u.index;
8205                 char *p;
8206                 if (j < 0) {
8207                         p = command;
8208                 } else {
8209                         do {
8210                                 p = path_advance(&path, command);
8211                                 stunalloc(p);
8212                         } while (--j >= 0);
8213                 }
8214                 if (describe_command_verbose) {
8215                         out1fmt(" is %s", p);
8216                 } else {
8217                         out1str(p);
8218                 }
8219                 break;
8220         }
8221
8222         case CMDFUNCTION:
8223                 if (describe_command_verbose) {
8224                         out1str(" is a shell function");
8225                 } else {
8226                         out1str(command);
8227                 }
8228                 break;
8229
8230         case CMDBUILTIN:
8231                 if (describe_command_verbose) {
8232                         out1fmt(" is a %sshell builtin",
8233                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8234                                         "special " : nullstr
8235                         );
8236                 } else {
8237                         out1str(command);
8238                 }
8239                 break;
8240
8241         default:
8242                 if (describe_command_verbose) {
8243                         out1str(": not found\n");
8244                 }
8245                 return 127;
8246         }
8247  out:
8248         out1str("\n");
8249         return 0;
8250 }
8251
8252 static int FAST_FUNC
8253 typecmd(int argc UNUSED_PARAM, char **argv)
8254 {
8255         int i = 1;
8256         int err = 0;
8257         int verbose = 1;
8258
8259         /* type -p ... ? (we don't bother checking for 'p') */
8260         if (argv[1] && argv[1][0] == '-') {
8261                 i++;
8262                 verbose = 0;
8263         }
8264         while (argv[i]) {
8265                 err |= describe_command(argv[i++], NULL, verbose);
8266         }
8267         return err;
8268 }
8269
8270 #if ENABLE_ASH_CMDCMD
8271 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8272 static char **
8273 parse_command_args(char **argv, const char **path)
8274 {
8275         char *cp, c;
8276
8277         for (;;) {
8278                 cp = *++argv;
8279                 if (!cp)
8280                         return NULL;
8281                 if (*cp++ != '-')
8282                         break;
8283                 c = *cp++;
8284                 if (!c)
8285                         break;
8286                 if (c == '-' && !*cp) {
8287                         if (!*++argv)
8288                                 return NULL;
8289                         break;
8290                 }
8291                 do {
8292                         switch (c) {
8293                         case 'p':
8294                                 *path = bb_default_path;
8295                                 break;
8296                         default:
8297                                 /* run 'typecmd' for other options */
8298                                 return NULL;
8299                         }
8300                         c = *cp++;
8301                 } while (c);
8302         }
8303         return argv;
8304 }
8305
8306 static int FAST_FUNC
8307 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8308 {
8309         char *cmd;
8310         int c;
8311         enum {
8312                 VERIFY_BRIEF = 1,
8313                 VERIFY_VERBOSE = 2,
8314         } verify = 0;
8315         const char *path = NULL;
8316
8317         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8318          * never reaches this function.
8319          */
8320
8321         while ((c = nextopt("pvV")) != '\0')
8322                 if (c == 'V')
8323                         verify |= VERIFY_VERBOSE;
8324                 else if (c == 'v')
8325                         /*verify |= VERIFY_BRIEF*/;
8326 #if DEBUG
8327                 else if (c != 'p')
8328                         abort();
8329 #endif
8330                 else
8331                         path = bb_default_path;
8332
8333         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8334         cmd = *argptr;
8335         if (/*verify && */ cmd)
8336                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8337
8338         return 0;
8339 }
8340 #endif
8341
8342
8343 /*static int funcblocksize;     // size of structures in function */
8344 /*static int funcstringsize;    // size of strings in node */
8345 static void *funcblock;         /* block to allocate function from */
8346 static char *funcstring_end;    /* end of block to allocate strings from */
8347
8348 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8349         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8350         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8351         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8352         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8353         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8354         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8355         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8356         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8357         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8358         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8359         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8360         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8361         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8362         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8363         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8364         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8365         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8366 #if BASH_REDIR_OUTPUT
8367         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8368 #endif
8369         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8370         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8371         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8372         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8373         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8374         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8375         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8376         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8377         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8378 };
8379
8380 static int calcsize(int funcblocksize, union node *n);
8381
8382 static int
8383 sizenodelist(int funcblocksize, struct nodelist *lp)
8384 {
8385         while (lp) {
8386                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8387                 funcblocksize = calcsize(funcblocksize, lp->n);
8388                 lp = lp->next;
8389         }
8390         return funcblocksize;
8391 }
8392
8393 static int
8394 calcsize(int funcblocksize, union node *n)
8395 {
8396         if (n == NULL)
8397                 return funcblocksize;
8398         funcblocksize += nodesize[n->type];
8399         switch (n->type) {
8400         case NCMD:
8401                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8402                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8403                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8404                 break;
8405         case NPIPE:
8406                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8407                 break;
8408         case NREDIR:
8409         case NBACKGND:
8410         case NSUBSHELL:
8411                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8412                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8413                 break;
8414         case NAND:
8415         case NOR:
8416         case NSEMI:
8417         case NWHILE:
8418         case NUNTIL:
8419                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8420                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8421                 break;
8422         case NIF:
8423                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8424                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8425                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8426                 break;
8427         case NFOR:
8428                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8429                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8430                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8431                 break;
8432         case NCASE:
8433                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8434                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8435                 break;
8436         case NCLIST:
8437                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8438                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8439                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8440                 break;
8441         case NDEFUN:
8442         case NARG:
8443                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8444                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8445                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8446                 break;
8447         case NTO:
8448 #if BASH_REDIR_OUTPUT
8449         case NTO2:
8450 #endif
8451         case NCLOBBER:
8452         case NFROM:
8453         case NFROMTO:
8454         case NAPPEND:
8455                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8456                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8457                 break;
8458         case NTOFD:
8459         case NFROMFD:
8460                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8461                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8462         break;
8463         case NHERE:
8464         case NXHERE:
8465                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8466                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8467                 break;
8468         case NNOT:
8469                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8470                 break;
8471         };
8472         return funcblocksize;
8473 }
8474
8475 static char *
8476 nodeckstrdup(char *s)
8477 {
8478         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8479         return strcpy(funcstring_end, s);
8480 }
8481
8482 static union node *copynode(union node *);
8483
8484 static struct nodelist *
8485 copynodelist(struct nodelist *lp)
8486 {
8487         struct nodelist *start;
8488         struct nodelist **lpp;
8489
8490         lpp = &start;
8491         while (lp) {
8492                 *lpp = funcblock;
8493                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8494                 (*lpp)->n = copynode(lp->n);
8495                 lp = lp->next;
8496                 lpp = &(*lpp)->next;
8497         }
8498         *lpp = NULL;
8499         return start;
8500 }
8501
8502 static union node *
8503 copynode(union node *n)
8504 {
8505         union node *new;
8506
8507         if (n == NULL)
8508                 return NULL;
8509         new = funcblock;
8510         funcblock = (char *) funcblock + nodesize[n->type];
8511
8512         switch (n->type) {
8513         case NCMD:
8514                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8515                 new->ncmd.args = copynode(n->ncmd.args);
8516                 new->ncmd.assign = copynode(n->ncmd.assign);
8517                 break;
8518         case NPIPE:
8519                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8520                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8521                 break;
8522         case NREDIR:
8523         case NBACKGND:
8524         case NSUBSHELL:
8525                 new->nredir.redirect = copynode(n->nredir.redirect);
8526                 new->nredir.n = copynode(n->nredir.n);
8527                 break;
8528         case NAND:
8529         case NOR:
8530         case NSEMI:
8531         case NWHILE:
8532         case NUNTIL:
8533                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8534                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8535                 break;
8536         case NIF:
8537                 new->nif.elsepart = copynode(n->nif.elsepart);
8538                 new->nif.ifpart = copynode(n->nif.ifpart);
8539                 new->nif.test = copynode(n->nif.test);
8540                 break;
8541         case NFOR:
8542                 new->nfor.var = nodeckstrdup(n->nfor.var);
8543                 new->nfor.body = copynode(n->nfor.body);
8544                 new->nfor.args = copynode(n->nfor.args);
8545                 break;
8546         case NCASE:
8547                 new->ncase.cases = copynode(n->ncase.cases);
8548                 new->ncase.expr = copynode(n->ncase.expr);
8549                 break;
8550         case NCLIST:
8551                 new->nclist.body = copynode(n->nclist.body);
8552                 new->nclist.pattern = copynode(n->nclist.pattern);
8553                 new->nclist.next = copynode(n->nclist.next);
8554                 break;
8555         case NDEFUN:
8556         case NARG:
8557                 new->narg.backquote = copynodelist(n->narg.backquote);
8558                 new->narg.text = nodeckstrdup(n->narg.text);
8559                 new->narg.next = copynode(n->narg.next);
8560                 break;
8561         case NTO:
8562 #if BASH_REDIR_OUTPUT
8563         case NTO2:
8564 #endif
8565         case NCLOBBER:
8566         case NFROM:
8567         case NFROMTO:
8568         case NAPPEND:
8569                 new->nfile.fname = copynode(n->nfile.fname);
8570                 new->nfile.fd = n->nfile.fd;
8571                 new->nfile.next = copynode(n->nfile.next);
8572                 break;
8573         case NTOFD:
8574         case NFROMFD:
8575                 new->ndup.vname = copynode(n->ndup.vname);
8576                 new->ndup.dupfd = n->ndup.dupfd;
8577                 new->ndup.fd = n->ndup.fd;
8578                 new->ndup.next = copynode(n->ndup.next);
8579                 break;
8580         case NHERE:
8581         case NXHERE:
8582                 new->nhere.doc = copynode(n->nhere.doc);
8583                 new->nhere.fd = n->nhere.fd;
8584                 new->nhere.next = copynode(n->nhere.next);
8585                 break;
8586         case NNOT:
8587                 new->nnot.com = copynode(n->nnot.com);
8588                 break;
8589         };
8590         new->type = n->type;
8591         return new;
8592 }
8593
8594 /*
8595  * Make a copy of a parse tree.
8596  */
8597 static struct funcnode *
8598 copyfunc(union node *n)
8599 {
8600         struct funcnode *f;
8601         size_t blocksize;
8602
8603         /*funcstringsize = 0;*/
8604         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8605         f = ckzalloc(blocksize /* + funcstringsize */);
8606         funcblock = (char *) f + offsetof(struct funcnode, n);
8607         funcstring_end = (char *) f + blocksize;
8608         copynode(n);
8609         /* f->count = 0; - ckzalloc did it */
8610         return f;
8611 }
8612
8613 /*
8614  * Define a shell function.
8615  */
8616 static void
8617 defun(union node *func)
8618 {
8619         struct cmdentry entry;
8620
8621         INT_OFF;
8622         entry.cmdtype = CMDFUNCTION;
8623         entry.u.func = copyfunc(func);
8624         addcmdentry(func->narg.text, &entry);
8625         INT_ON;
8626 }
8627
8628 /* Reasons for skipping commands (see comment on breakcmd routine) */
8629 #define SKIPBREAK      (1 << 0)
8630 #define SKIPCONT       (1 << 1)
8631 #define SKIPFUNC       (1 << 2)
8632 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8633 static int skipcount;           /* number of levels to skip */
8634 static int funcnest;            /* depth of function calls */
8635 static int loopnest;            /* current loop nesting level */
8636
8637 /* Forward decl way out to parsing code - dotrap needs it */
8638 static int evalstring(char *s, int flags);
8639
8640 /* Called to execute a trap.
8641  * Single callsite - at the end of evaltree().
8642  * If we return non-zero, evaltree raises EXEXIT exception.
8643  *
8644  * Perhaps we should avoid entering new trap handlers
8645  * while we are executing a trap handler. [is it a TODO?]
8646  */
8647 static void
8648 dotrap(void)
8649 {
8650         uint8_t *g;
8651         int sig;
8652         uint8_t last_status;
8653
8654         if (!pending_sig)
8655                 return;
8656
8657         last_status = exitstatus;
8658         pending_sig = 0;
8659         barrier();
8660
8661         TRACE(("dotrap entered\n"));
8662         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8663                 char *p;
8664
8665                 if (!*g)
8666                         continue;
8667
8668                 if (evalskip) {
8669                         pending_sig = sig;
8670                         break;
8671                 }
8672
8673                 p = trap[sig];
8674                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8675                  * don't upset it by resetting gotsig[SIGINT-1] */
8676                 if (sig == SIGINT && !p)
8677                         continue;
8678
8679                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8680                 *g = 0;
8681                 if (!p)
8682                         continue;
8683                 evalstring(p, 0);
8684         }
8685         exitstatus = last_status;
8686         TRACE(("dotrap returns\n"));
8687 }
8688
8689 /* forward declarations - evaluation is fairly recursive business... */
8690 static int evalloop(union node *, int);
8691 static int evalfor(union node *, int);
8692 static int evalcase(union node *, int);
8693 static int evalsubshell(union node *, int);
8694 static void expredir(union node *);
8695 static int evalpipe(union node *, int);
8696 static int evalcommand(union node *, int);
8697 static int evalbltin(const struct builtincmd *, int, char **, int);
8698 static void prehash(union node *);
8699
8700 /*
8701  * Evaluate a parse tree.  The value is left in the global variable
8702  * exitstatus.
8703  */
8704 static int
8705 evaltree(union node *n, int flags)
8706 {
8707         int checkexit = 0;
8708         int (*evalfn)(union node *, int);
8709         int status = 0;
8710
8711         if (n == NULL) {
8712                 TRACE(("evaltree(NULL) called\n"));
8713                 goto out;
8714         }
8715         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8716
8717         dotrap();
8718
8719         switch (n->type) {
8720         default:
8721 #if DEBUG
8722                 out1fmt("Node type = %d\n", n->type);
8723                 fflush_all();
8724                 break;
8725 #endif
8726         case NNOT:
8727                 status = !evaltree(n->nnot.com, EV_TESTED);
8728                 goto setstatus;
8729         case NREDIR:
8730                 expredir(n->nredir.redirect);
8731                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8732                 if (!status) {
8733                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8734                 }
8735                 if (n->nredir.redirect)
8736                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8737                 goto setstatus;
8738         case NCMD:
8739                 evalfn = evalcommand;
8740  checkexit:
8741                 if (eflag && !(flags & EV_TESTED))
8742                         checkexit = ~0;
8743                 goto calleval;
8744         case NFOR:
8745                 evalfn = evalfor;
8746                 goto calleval;
8747         case NWHILE:
8748         case NUNTIL:
8749                 evalfn = evalloop;
8750                 goto calleval;
8751         case NSUBSHELL:
8752         case NBACKGND:
8753                 evalfn = evalsubshell;
8754                 goto checkexit;
8755         case NPIPE:
8756                 evalfn = evalpipe;
8757                 goto checkexit;
8758         case NCASE:
8759                 evalfn = evalcase;
8760                 goto calleval;
8761         case NAND:
8762         case NOR:
8763         case NSEMI: {
8764
8765 #if NAND + 1 != NOR
8766 #error NAND + 1 != NOR
8767 #endif
8768 #if NOR + 1 != NSEMI
8769 #error NOR + 1 != NSEMI
8770 #endif
8771                 unsigned is_or = n->type - NAND;
8772                 status = evaltree(
8773                         n->nbinary.ch1,
8774                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8775                 );
8776                 if ((!status) == is_or || evalskip)
8777                         break;
8778                 n = n->nbinary.ch2;
8779  evaln:
8780                 evalfn = evaltree;
8781  calleval:
8782                 status = evalfn(n, flags);
8783                 goto setstatus;
8784         }
8785         case NIF:
8786                 status = evaltree(n->nif.test, EV_TESTED);
8787                 if (evalskip)
8788                         break;
8789                 if (!status) {
8790                         n = n->nif.ifpart;
8791                         goto evaln;
8792                 }
8793                 if (n->nif.elsepart) {
8794                         n = n->nif.elsepart;
8795                         goto evaln;
8796                 }
8797                 status = 0;
8798                 goto setstatus;
8799         case NDEFUN:
8800                 defun(n);
8801                 /* Not necessary. To test it:
8802                  * "false; f() { qwerty; }; echo $?" should print 0.
8803                  */
8804                 /* status = 0; */
8805  setstatus:
8806                 exitstatus = status;
8807                 break;
8808         }
8809  out:
8810         /* Order of checks below is important:
8811          * signal handlers trigger before exit caused by "set -e".
8812          */
8813         dotrap();
8814
8815         if (checkexit & status)
8816                 raise_exception(EXEXIT);
8817         if (flags & EV_EXIT)
8818                 raise_exception(EXEXIT);
8819
8820         TRACE(("leaving evaltree (no interrupts)\n"));
8821         return exitstatus;
8822 }
8823
8824 static int
8825 skiploop(void)
8826 {
8827         int skip = evalskip;
8828
8829         switch (skip) {
8830         case 0:
8831                 break;
8832         case SKIPBREAK:
8833         case SKIPCONT:
8834                 if (--skipcount <= 0) {
8835                         evalskip = 0;
8836                         break;
8837                 }
8838                 skip = SKIPBREAK;
8839                 break;
8840         }
8841         return skip;
8842 }
8843
8844 static int
8845 evalloop(union node *n, int flags)
8846 {
8847         int skip;
8848         int status;
8849
8850         loopnest++;
8851         status = 0;
8852         flags &= EV_TESTED;
8853         do {
8854                 int i;
8855
8856                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8857                 skip = skiploop();
8858                 if (skip == SKIPFUNC)
8859                         status = i;
8860                 if (skip)
8861                         continue;
8862                 if (n->type != NWHILE)
8863                         i = !i;
8864                 if (i != 0)
8865                         break;
8866                 status = evaltree(n->nbinary.ch2, flags);
8867                 skip = skiploop();
8868         } while (!(skip & ~SKIPCONT));
8869         loopnest--;
8870
8871         return status;
8872 }
8873
8874 static int
8875 evalfor(union node *n, int flags)
8876 {
8877         struct arglist arglist;
8878         union node *argp;
8879         struct strlist *sp;
8880         struct stackmark smark;
8881         int status = 0;
8882
8883         setstackmark(&smark);
8884         arglist.list = NULL;
8885         arglist.lastp = &arglist.list;
8886         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8887                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8888         }
8889         *arglist.lastp = NULL;
8890
8891         loopnest++;
8892         flags &= EV_TESTED;
8893         for (sp = arglist.list; sp; sp = sp->next) {
8894                 setvar0(n->nfor.var, sp->text);
8895                 status = evaltree(n->nfor.body, flags);
8896                 if (skiploop() & ~SKIPCONT)
8897                         break;
8898         }
8899         loopnest--;
8900         popstackmark(&smark);
8901
8902         return status;
8903 }
8904
8905 static int
8906 evalcase(union node *n, int flags)
8907 {
8908         union node *cp;
8909         union node *patp;
8910         struct arglist arglist;
8911         struct stackmark smark;
8912         int status = 0;
8913
8914         setstackmark(&smark);
8915         arglist.list = NULL;
8916         arglist.lastp = &arglist.list;
8917         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8918         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8919                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8920                         if (casematch(patp, arglist.list->text)) {
8921                                 /* Ensure body is non-empty as otherwise
8922                                  * EV_EXIT may prevent us from setting the
8923                                  * exit status.
8924                                  */
8925                                 if (evalskip == 0 && cp->nclist.body) {
8926                                         status = evaltree(cp->nclist.body, flags);
8927                                 }
8928                                 goto out;
8929                         }
8930                 }
8931         }
8932  out:
8933         popstackmark(&smark);
8934
8935         return status;
8936 }
8937
8938 /*
8939  * Kick off a subshell to evaluate a tree.
8940  */
8941 static int
8942 evalsubshell(union node *n, int flags)
8943 {
8944         struct job *jp;
8945         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8946         int status;
8947
8948         expredir(n->nredir.redirect);
8949         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8950                 goto nofork;
8951         INT_OFF;
8952         if (backgnd == FORK_FG)
8953                 get_tty_state();
8954         jp = makejob(/*n,*/ 1);
8955         if (forkshell(jp, n, backgnd) == 0) {
8956                 /* child */
8957                 INT_ON;
8958                 flags |= EV_EXIT;
8959                 if (backgnd)
8960                         flags &= ~EV_TESTED;
8961  nofork:
8962                 redirect(n->nredir.redirect, 0);
8963                 evaltreenr(n->nredir.n, flags);
8964                 /* never returns */
8965         }
8966         /* parent */
8967         status = 0;
8968         if (backgnd == FORK_FG)
8969                 status = waitforjob(jp);
8970         INT_ON;
8971         return status;
8972 }
8973
8974 /*
8975  * Compute the names of the files in a redirection list.
8976  */
8977 static void fixredir(union node *, const char *, int);
8978 static void
8979 expredir(union node *n)
8980 {
8981         union node *redir;
8982
8983         for (redir = n; redir; redir = redir->nfile.next) {
8984                 struct arglist fn;
8985
8986                 fn.list = NULL;
8987                 fn.lastp = &fn.list;
8988                 switch (redir->type) {
8989                 case NFROMTO:
8990                 case NFROM:
8991                 case NTO:
8992 #if BASH_REDIR_OUTPUT
8993                 case NTO2:
8994 #endif
8995                 case NCLOBBER:
8996                 case NAPPEND:
8997                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8998                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
8999 #if BASH_REDIR_OUTPUT
9000  store_expfname:
9001 #endif
9002 #if 0
9003 // By the design of stack allocator, the loop of this kind:
9004 //      while true; do while true; do break; done </dev/null; done
9005 // will look like a memory leak: ash plans to free expfname's
9006 // of "/dev/null" as soon as it finishes running the loop
9007 // (in this case, never).
9008 // This "fix" is wrong:
9009                         if (redir->nfile.expfname)
9010                                 stunalloc(redir->nfile.expfname);
9011 // It results in corrupted state of stacked allocations.
9012 #endif
9013                         redir->nfile.expfname = fn.list->text;
9014                         break;
9015                 case NFROMFD:
9016                 case NTOFD: /* >& */
9017                         if (redir->ndup.vname) {
9018                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9019                                 if (fn.list == NULL)
9020                                         ash_msg_and_raise_error("redir error");
9021 #if BASH_REDIR_OUTPUT
9022 //FIXME: we used expandarg with different args!
9023                                 if (!isdigit_str9(fn.list->text)) {
9024                                         /* >&file, not >&fd */
9025                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9026                                                 ash_msg_and_raise_error("redir error");
9027                                         redir->type = NTO2;
9028                                         goto store_expfname;
9029                                 }
9030 #endif
9031                                 fixredir(redir, fn.list->text, 1);
9032                         }
9033                         break;
9034                 }
9035         }
9036 }
9037
9038 /*
9039  * Evaluate a pipeline.  All the processes in the pipeline are children
9040  * of the process creating the pipeline.  (This differs from some versions
9041  * of the shell, which make the last process in a pipeline the parent
9042  * of all the rest.)
9043  */
9044 static int
9045 evalpipe(union node *n, int flags)
9046 {
9047         struct job *jp;
9048         struct nodelist *lp;
9049         int pipelen;
9050         int prevfd;
9051         int pip[2];
9052         int status = 0;
9053
9054         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9055         pipelen = 0;
9056         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9057                 pipelen++;
9058         flags |= EV_EXIT;
9059         INT_OFF;
9060         if (n->npipe.pipe_backgnd == 0)
9061                 get_tty_state();
9062         jp = makejob(/*n,*/ pipelen);
9063         prevfd = -1;
9064         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9065                 prehash(lp->n);
9066                 pip[1] = -1;
9067                 if (lp->next) {
9068                         if (pipe(pip) < 0) {
9069                                 close(prevfd);
9070                                 ash_msg_and_raise_error("pipe call failed");
9071                         }
9072                 }
9073                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9074                         /* child */
9075                         INT_ON;
9076                         if (pip[1] >= 0) {
9077                                 close(pip[0]);
9078                         }
9079                         if (prevfd > 0) {
9080                                 dup2(prevfd, 0);
9081                                 close(prevfd);
9082                         }
9083                         if (pip[1] > 1) {
9084                                 dup2(pip[1], 1);
9085                                 close(pip[1]);
9086                         }
9087                         evaltreenr(lp->n, flags);
9088                         /* never returns */
9089                 }
9090                 /* parent */
9091                 if (prevfd >= 0)
9092                         close(prevfd);
9093                 prevfd = pip[0];
9094                 /* Don't want to trigger debugging */
9095                 if (pip[1] != -1)
9096                         close(pip[1]);
9097         }
9098         if (n->npipe.pipe_backgnd == 0) {
9099                 status = waitforjob(jp);
9100                 TRACE(("evalpipe:  job done exit status %d\n", status));
9101         }
9102         INT_ON;
9103
9104         return status;
9105 }
9106
9107 /*
9108  * Controls whether the shell is interactive or not.
9109  */
9110 static void
9111 setinteractive(int on)
9112 {
9113         static smallint is_interactive;
9114
9115         if (++on == is_interactive)
9116                 return;
9117         is_interactive = on;
9118         setsignal(SIGINT);
9119         setsignal(SIGQUIT);
9120         setsignal(SIGTERM);
9121 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9122         if (is_interactive > 1) {
9123                 /* Looks like they want an interactive shell */
9124                 static smallint did_banner;
9125
9126                 if (!did_banner) {
9127                         /* note: ash and hush share this string */
9128                         out1fmt("\n\n%s %s\n"
9129                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9130                                 "\n",
9131                                 bb_banner,
9132                                 "built-in shell (ash)"
9133                         );
9134                         did_banner = 1;
9135                 }
9136         }
9137 #endif
9138 }
9139
9140 static void
9141 optschanged(void)
9142 {
9143 #if DEBUG
9144         opentrace();
9145 #endif
9146         setinteractive(iflag);
9147         setjobctl(mflag);
9148 #if ENABLE_FEATURE_EDITING_VI
9149         if (viflag)
9150                 line_input_state->flags |= VI_MODE;
9151         else
9152                 line_input_state->flags &= ~VI_MODE;
9153 #else
9154         viflag = 0; /* forcibly keep the option off */
9155 #endif
9156 }
9157
9158 struct localvar_list {
9159         struct localvar_list *next;
9160         struct localvar *lv;
9161 };
9162
9163 static struct localvar_list *localvar_stack;
9164
9165 /*
9166  * Called after a function returns.
9167  * Interrupts must be off.
9168  */
9169 static void
9170 poplocalvars(int keep)
9171 {
9172         struct localvar_list *ll;
9173         struct localvar *lvp, *next;
9174         struct var *vp;
9175
9176         INT_OFF;
9177         ll = localvar_stack;
9178         localvar_stack = ll->next;
9179
9180         next = ll->lv;
9181         free(ll);
9182
9183         while ((lvp = next) != NULL) {
9184                 next = lvp->next;
9185                 vp = lvp->vp;
9186                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9187                 if (keep) {
9188                         int bits = VSTRFIXED;
9189
9190                         if (lvp->flags != VUNSET) {
9191                                 if (vp->var_text == lvp->text)
9192                                         bits |= VTEXTFIXED;
9193                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9194                                         free((char*)lvp->text);
9195                         }
9196
9197                         vp->flags &= ~bits;
9198                         vp->flags |= (lvp->flags & bits);
9199
9200                         if ((vp->flags &
9201                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9202                                 unsetvar(vp->var_text);
9203                 } else if (vp == NULL) {        /* $- saved */
9204                         memcpy(optlist, lvp->text, sizeof(optlist));
9205                         free((char*)lvp->text);
9206                         optschanged();
9207                 } else if (lvp->flags == VUNSET) {
9208                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9209                         unsetvar(vp->var_text);
9210                 } else {
9211                         if (vp->var_func)
9212                                 vp->var_func(var_end(lvp->text));
9213                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9214                                 free((char*)vp->var_text);
9215                         vp->flags = lvp->flags;
9216                         vp->var_text = lvp->text;
9217                 }
9218                 free(lvp);
9219         }
9220         INT_ON;
9221 }
9222
9223 /*
9224  * Create a new localvar environment.
9225  */
9226 static struct localvar_list *
9227 pushlocalvars(void)
9228 {
9229         struct localvar_list *ll;
9230
9231         INT_OFF;
9232         ll = ckzalloc(sizeof(*ll));
9233         /*ll->lv = NULL; - zalloc did it */
9234         ll->next = localvar_stack;
9235         localvar_stack = ll;
9236         INT_ON;
9237
9238         return ll->next;
9239 }
9240
9241 static void
9242 unwindlocalvars(struct localvar_list *stop)
9243 {
9244         while (localvar_stack != stop)
9245                 poplocalvars(0);
9246 }
9247
9248 static int
9249 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9250 {
9251         volatile struct shparam saveparam;
9252         struct jmploc *volatile savehandler;
9253         struct jmploc jmploc;
9254         int e;
9255
9256         saveparam = shellparam;
9257         savehandler = exception_handler;
9258         e = setjmp(jmploc.loc);
9259         if (e) {
9260                 goto funcdone;
9261         }
9262         INT_OFF;
9263         exception_handler = &jmploc;
9264         shellparam.malloced = 0;
9265         func->count++;
9266         funcnest++;
9267         INT_ON;
9268         shellparam.nparam = argc - 1;
9269         shellparam.p = argv + 1;
9270 #if ENABLE_ASH_GETOPTS
9271         shellparam.optind = 1;
9272         shellparam.optoff = -1;
9273 #endif
9274         pushlocalvars();
9275         evaltree(func->n.narg.next, flags & EV_TESTED);
9276         poplocalvars(0);
9277  funcdone:
9278         INT_OFF;
9279         funcnest--;
9280         freefunc(func);
9281         freeparam(&shellparam);
9282         shellparam = saveparam;
9283         exception_handler = savehandler;
9284         INT_ON;
9285         evalskip &= ~SKIPFUNC;
9286         return e;
9287 }
9288
9289 /*
9290  * Make a variable a local variable.  When a variable is made local, it's
9291  * value and flags are saved in a localvar structure.  The saved values
9292  * will be restored when the shell function returns.  We handle the name
9293  * "-" as a special case: it makes changes to "set +-options" local
9294  * (options will be restored on return from the function).
9295  */
9296 static void
9297 mklocal(char *name)
9298 {
9299         struct localvar *lvp;
9300         struct var **vpp;
9301         struct var *vp;
9302         char *eq = strchr(name, '=');
9303
9304         INT_OFF;
9305         /* Cater for duplicate "local". Examples:
9306          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9307          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9308          */
9309         lvp = localvar_stack->lv;
9310         while (lvp) {
9311                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9312                         if (eq)
9313                                 setvareq(name, 0);
9314                         /* else:
9315                          * it's a duplicate "local VAR" declaration, do nothing
9316                          */
9317                         goto ret;
9318                 }
9319                 lvp = lvp->next;
9320         }
9321
9322         lvp = ckzalloc(sizeof(*lvp));
9323         if (LONE_DASH(name)) {
9324                 char *p;
9325                 p = ckmalloc(sizeof(optlist));
9326                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9327                 vp = NULL;
9328         } else {
9329                 vpp = hashvar(name);
9330                 vp = *findvar(vpp, name);
9331                 if (vp == NULL) {
9332                         /* variable did not exist yet */
9333                         if (eq)
9334                                 vp = setvareq(name, VSTRFIXED);
9335                         else
9336                                 vp = setvar(name, NULL, VSTRFIXED);
9337                         lvp->flags = VUNSET;
9338                 } else {
9339                         lvp->text = vp->var_text;
9340                         lvp->flags = vp->flags;
9341                         /* make sure neither "struct var" nor string gets freed
9342                          * during (un)setting:
9343                          */
9344                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9345                         if (eq)
9346                                 setvareq(name, 0);
9347                         else
9348                                 /* "local VAR" unsets VAR: */
9349                                 setvar0(name, NULL);
9350                 }
9351         }
9352         lvp->vp = vp;
9353         lvp->next = localvar_stack->lv;
9354         localvar_stack->lv = lvp;
9355  ret:
9356         INT_ON;
9357 }
9358
9359 /*
9360  * The "local" command.
9361  */
9362 static int FAST_FUNC
9363 localcmd(int argc UNUSED_PARAM, char **argv)
9364 {
9365         char *name;
9366
9367         if (!localvar_stack)
9368                 ash_msg_and_raise_error("not in a function");
9369
9370         argv = argptr;
9371         while ((name = *argv++) != NULL) {
9372                 mklocal(name);
9373         }
9374         return 0;
9375 }
9376
9377 static int FAST_FUNC
9378 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9379 {
9380         return 1;
9381 }
9382
9383 static int FAST_FUNC
9384 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9385 {
9386         return 0;
9387 }
9388
9389 static int FAST_FUNC
9390 execcmd(int argc UNUSED_PARAM, char **argv)
9391 {
9392         optionarg = NULL;
9393         while (nextopt("a:") != '\0')
9394                 /* nextopt() sets optionarg to "-a ARGV0" */;
9395
9396         argv = argptr;
9397         if (argv[0]) {
9398                 char *prog;
9399
9400                 iflag = 0;              /* exit on error */
9401                 mflag = 0;
9402                 optschanged();
9403                 /* We should set up signals for "exec CMD"
9404                  * the same way as for "CMD" without "exec".
9405                  * But optschanged->setinteractive->setsignal
9406                  * still thought we are a root shell. Therefore, for example,
9407                  * SIGQUIT is still set to IGN. Fix it:
9408                  */
9409                 shlvl++;
9410                 setsignal(SIGQUIT);
9411                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9412                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9413                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9414
9415                 prog = argv[0];
9416                 if (optionarg)
9417                         argv[0] = optionarg;
9418                 shellexec(prog, argv, pathval(), 0);
9419                 /* NOTREACHED */
9420         }
9421         return 0;
9422 }
9423
9424 /*
9425  * The return command.
9426  */
9427 static int FAST_FUNC
9428 returncmd(int argc UNUSED_PARAM, char **argv)
9429 {
9430         /*
9431          * If called outside a function, do what ksh does;
9432          * skip the rest of the file.
9433          */
9434         evalskip = SKIPFUNC;
9435         return argv[1] ? number(argv[1]) : exitstatus;
9436 }
9437
9438 /* Forward declarations for builtintab[] */
9439 static int breakcmd(int, char **) FAST_FUNC;
9440 static int dotcmd(int, char **) FAST_FUNC;
9441 static int evalcmd(int, char **, int) FAST_FUNC;
9442 static int exitcmd(int, char **) FAST_FUNC;
9443 static int exportcmd(int, char **) FAST_FUNC;
9444 #if ENABLE_ASH_GETOPTS
9445 static int getoptscmd(int, char **) FAST_FUNC;
9446 #endif
9447 #if ENABLE_ASH_HELP
9448 static int helpcmd(int, char **) FAST_FUNC;
9449 #endif
9450 #if MAX_HISTORY
9451 static int historycmd(int, char **) FAST_FUNC;
9452 #endif
9453 #if ENABLE_FEATURE_SH_MATH
9454 static int letcmd(int, char **) FAST_FUNC;
9455 #endif
9456 static int readcmd(int, char **) FAST_FUNC;
9457 static int setcmd(int, char **) FAST_FUNC;
9458 static int shiftcmd(int, char **) FAST_FUNC;
9459 static int timescmd(int, char **) FAST_FUNC;
9460 static int trapcmd(int, char **) FAST_FUNC;
9461 static int umaskcmd(int, char **) FAST_FUNC;
9462 static int unsetcmd(int, char **) FAST_FUNC;
9463 static int ulimitcmd(int, char **) FAST_FUNC;
9464
9465 #define BUILTIN_NOSPEC          "0"
9466 #define BUILTIN_SPECIAL         "1"
9467 #define BUILTIN_REGULAR         "2"
9468 #define BUILTIN_SPEC_REG        "3"
9469 #define BUILTIN_ASSIGN          "4"
9470 #define BUILTIN_SPEC_ASSG       "5"
9471 #define BUILTIN_REG_ASSG        "6"
9472 #define BUILTIN_SPEC_REG_ASSG   "7"
9473
9474 /* Stubs for calling non-FAST_FUNC's */
9475 #if ENABLE_ASH_ECHO
9476 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9477 #endif
9478 #if ENABLE_ASH_PRINTF
9479 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9480 #endif
9481 #if ENABLE_ASH_TEST || BASH_TEST2
9482 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9483 #endif
9484
9485 /* Keep these in proper order since it is searched via bsearch() */
9486 static const struct builtincmd builtintab[] = {
9487         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9488         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9489 #if ENABLE_ASH_TEST
9490         { BUILTIN_REGULAR       "["       , testcmd    },
9491 #endif
9492 #if BASH_TEST2
9493         { BUILTIN_REGULAR       "[["      , testcmd    },
9494 #endif
9495 #if ENABLE_ASH_ALIAS
9496         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9497 #endif
9498 #if JOBS
9499         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9500 #endif
9501         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9502         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9503         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9504 #if ENABLE_ASH_CMDCMD
9505         { BUILTIN_REGULAR       "command" , commandcmd },
9506 #endif
9507         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9508 #if ENABLE_ASH_ECHO
9509         { BUILTIN_REGULAR       "echo"    , echocmd    },
9510 #endif
9511         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9512         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9513         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9514         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9515         { BUILTIN_REGULAR       "false"   , falsecmd   },
9516 #if JOBS
9517         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9518 #endif
9519 #if ENABLE_ASH_GETOPTS
9520         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9521 #endif
9522         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9523 #if ENABLE_ASH_HELP
9524         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9525 #endif
9526 #if MAX_HISTORY
9527         { BUILTIN_NOSPEC        "history" , historycmd },
9528 #endif
9529 #if JOBS
9530         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9531         { BUILTIN_REGULAR       "kill"    , killcmd    },
9532 #endif
9533 #if ENABLE_FEATURE_SH_MATH
9534         { BUILTIN_NOSPEC        "let"     , letcmd     },
9535 #endif
9536         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9537 #if ENABLE_ASH_PRINTF
9538         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9539 #endif
9540         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9541         { BUILTIN_REGULAR       "read"    , readcmd    },
9542         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9543         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9544         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9545         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9546 #if BASH_SOURCE
9547         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9548 #endif
9549 #if ENABLE_ASH_TEST
9550         { BUILTIN_REGULAR       "test"    , testcmd    },
9551 #endif
9552         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9553         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9554         { BUILTIN_REGULAR       "true"    , truecmd    },
9555         { BUILTIN_NOSPEC        "type"    , typecmd    },
9556         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9557         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9558 #if ENABLE_ASH_ALIAS
9559         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9560 #endif
9561         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9562         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9563 };
9564
9565 /* Should match the above table! */
9566 #define COMMANDCMD (builtintab + \
9567         /* . : */       2 + \
9568         /* [ */         1 * ENABLE_ASH_TEST + \
9569         /* [[ */        1 * BASH_TEST2 + \
9570         /* alias */     1 * ENABLE_ASH_ALIAS + \
9571         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9572         /* break cd cddir  */   3)
9573 #define EVALCMD (COMMANDCMD + \
9574         /* command */   1 * ENABLE_ASH_CMDCMD + \
9575         /* continue */  1 + \
9576         /* echo */      1 * ENABLE_ASH_ECHO + \
9577         0)
9578 #define EXECCMD (EVALCMD + \
9579         /* eval */      1)
9580
9581 /*
9582  * Search the table of builtin commands.
9583  */
9584 static int
9585 pstrcmp1(const void *a, const void *b)
9586 {
9587         return strcmp((char*)a, *(char**)b + 1);
9588 }
9589 static struct builtincmd *
9590 find_builtin(const char *name)
9591 {
9592         struct builtincmd *bp;
9593
9594         bp = bsearch(
9595                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9596                 pstrcmp1
9597         );
9598         return bp;
9599 }
9600
9601 /*
9602  * Execute a simple command.
9603  */
9604 static int
9605 isassignment(const char *p)
9606 {
9607         const char *q = endofname(p);
9608         if (p == q)
9609                 return 0;
9610         return *q == '=';
9611 }
9612 static int FAST_FUNC
9613 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9614 {
9615         /* Preserve exitstatus of a previous possible redirection
9616          * as POSIX mandates */
9617         return back_exitstatus;
9618 }
9619 static int
9620 evalcommand(union node *cmd, int flags)
9621 {
9622         static const struct builtincmd null_bltin = {
9623                 "\0\0", bltincmd /* why three NULs? */
9624         };
9625         struct localvar_list *localvar_stop;
9626         struct stackmark smark;
9627         union node *argp;
9628         struct arglist arglist;
9629         struct arglist varlist;
9630         char **argv;
9631         int argc;
9632         const struct strlist *sp;
9633         struct cmdentry cmdentry;
9634         struct job *jp;
9635         char *lastarg;
9636         const char *path;
9637         int spclbltin;
9638         int status;
9639         char **nargv;
9640         struct builtincmd *bcmd;
9641         smallint cmd_is_exec;
9642         smallint pseudovarflag = 0;
9643
9644         /* First expand the arguments. */
9645         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9646         setstackmark(&smark);
9647         localvar_stop = pushlocalvars();
9648         back_exitstatus = 0;
9649
9650         cmdentry.cmdtype = CMDBUILTIN;
9651         cmdentry.u.cmd = &null_bltin;
9652         varlist.lastp = &varlist.list;
9653         *varlist.lastp = NULL;
9654         arglist.lastp = &arglist.list;
9655         *arglist.lastp = NULL;
9656
9657         argc = 0;
9658         if (cmd->ncmd.args) {
9659                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9660                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9661         }
9662
9663         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9664                 struct strlist **spp;
9665
9666                 spp = arglist.lastp;
9667                 if (pseudovarflag && isassignment(argp->narg.text))
9668                         expandarg(argp, &arglist, EXP_VARTILDE);
9669                 else
9670                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9671
9672                 for (sp = *spp; sp; sp = sp->next)
9673                         argc++;
9674         }
9675
9676         /* Reserve one extra spot at the front for shellexec. */
9677         nargv = stalloc(sizeof(char *) * (argc + 2));
9678         argv = ++nargv;
9679         for (sp = arglist.list; sp; sp = sp->next) {
9680                 TRACE(("evalcommand arg: %s\n", sp->text));
9681                 *nargv++ = sp->text;
9682         }
9683         *nargv = NULL;
9684
9685         lastarg = NULL;
9686         if (iflag && funcnest == 0 && argc > 0)
9687                 lastarg = nargv[-1];
9688
9689         preverrout_fd = 2;
9690         expredir(cmd->ncmd.redirect);
9691         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9692
9693         path = vpath.var_text;
9694         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9695                 struct strlist **spp;
9696                 char *p;
9697
9698                 spp = varlist.lastp;
9699                 expandarg(argp, &varlist, EXP_VARTILDE);
9700
9701                 mklocal((*spp)->text);
9702
9703                 /*
9704                  * Modify the command lookup path, if a PATH= assignment
9705                  * is present
9706                  */
9707                 p = (*spp)->text;
9708                 if (varcmp(p, path) == 0)
9709                         path = p;
9710         }
9711
9712         /* Print the command if xflag is set. */
9713         if (xflag) {
9714                 const char *pfx = "";
9715
9716                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9717
9718                 sp = varlist.list;
9719                 while (sp) {
9720                         char *varval = sp->text;
9721                         char *eq = strchrnul(varval, '=');
9722                         if (*eq)
9723                                 eq++;
9724                         fdprintf(preverrout_fd, "%s%.*s%s",
9725                                 pfx,
9726                                 (int)(eq - varval), varval,
9727                                 maybe_single_quote(eq)
9728                         );
9729                         sp = sp->next;
9730                         pfx = " ";
9731                 }
9732
9733                 sp = arglist.list;
9734                 while (sp) {
9735                         fdprintf(preverrout_fd, "%s%s",
9736                                 pfx,
9737                                 /* always quote if matches reserved word: */
9738                                 findkwd(sp->text)
9739                                 ? single_quote(sp->text)
9740                                 : maybe_single_quote(sp->text)
9741                         );
9742                         sp = sp->next;
9743                         pfx = " ";
9744                 }
9745                 safe_write(preverrout_fd, "\n", 1);
9746         }
9747
9748         cmd_is_exec = 0;
9749         spclbltin = -1;
9750
9751         /* Now locate the command. */
9752         if (argc) {
9753                 int cmd_flag = DO_ERR;
9754 #if ENABLE_ASH_CMDCMD
9755                 const char *oldpath = path + 5;
9756 #endif
9757                 path += 5;
9758                 for (;;) {
9759                         find_command(argv[0], &cmdentry, cmd_flag, path);
9760                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9761                                 flush_stdout_stderr();
9762                                 status = 127;
9763                                 goto bail;
9764                         }
9765
9766                         /* implement bltin and command here */
9767                         if (cmdentry.cmdtype != CMDBUILTIN)
9768                                 break;
9769                         if (spclbltin < 0)
9770                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9771                         if (cmdentry.u.cmd == EXECCMD)
9772                                 cmd_is_exec = 1;
9773 #if ENABLE_ASH_CMDCMD
9774                         if (cmdentry.u.cmd == COMMANDCMD) {
9775                                 path = oldpath;
9776                                 nargv = parse_command_args(argv, &path);
9777                                 if (!nargv)
9778                                         break;
9779                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9780                                  * nargv => "PROG". path is updated if -p.
9781                                  */
9782                                 argc -= nargv - argv;
9783                                 argv = nargv;
9784                                 cmd_flag |= DO_NOFUNC;
9785                         } else
9786 #endif
9787                                 break;
9788                 }
9789         }
9790
9791         if (status) {
9792  bail:
9793                 exitstatus = status;
9794
9795                 /* We have a redirection error. */
9796                 if (spclbltin > 0)
9797                         raise_exception(EXERROR);
9798
9799                 goto out;
9800         }
9801
9802         /* Execute the command. */
9803         switch (cmdentry.cmdtype) {
9804         default: {
9805
9806 #if ENABLE_FEATURE_SH_NOFORK
9807 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9808  *     around run_nofork_applet() call.
9809  * (2) Should this check also be done in forkshell()?
9810  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9811  */
9812                 /* find_command() encodes applet_no as (-2 - applet_no) */
9813                 int applet_no = (- cmdentry.u.index - 2);
9814                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9815                         listsetvar(varlist.list, VEXPORT|VSTACK);
9816                         /* run <applet>_main() */
9817                         status = run_nofork_applet(applet_no, argv);
9818                         break;
9819                 }
9820 #endif
9821                 /* Can we avoid forking off? For example, very last command
9822                  * in a script or a subshell does not need forking,
9823                  * we can just exec it.
9824                  */
9825                 if (!(flags & EV_EXIT) || may_have_traps) {
9826                         /* No, forking off a child is necessary */
9827                         INT_OFF;
9828                         get_tty_state();
9829                         jp = makejob(/*cmd,*/ 1);
9830                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9831                                 /* parent */
9832                                 status = waitforjob(jp);
9833                                 INT_ON;
9834                                 TRACE(("forked child exited with %d\n", status));
9835                                 break;
9836                         }
9837                         /* child */
9838                         FORCE_INT_ON;
9839                         /* fall through to exec'ing external program */
9840                 }
9841                 listsetvar(varlist.list, VEXPORT|VSTACK);
9842                 shellexec(argv[0], argv, path, cmdentry.u.index);
9843                 /* NOTREACHED */
9844         } /* default */
9845         case CMDBUILTIN:
9846                 if (spclbltin > 0 || argc == 0) {
9847                         poplocalvars(1);
9848                         if (cmd_is_exec && argc > 1)
9849                                 listsetvar(varlist.list, VEXPORT);
9850                 }
9851
9852                 /* Tight loop with builtins only:
9853                  * "while kill -0 $child; do true; done"
9854                  * will never exit even if $child died, unless we do this
9855                  * to reap the zombie and make kill detect that it's gone: */
9856                 dowait(DOWAIT_NONBLOCK, NULL);
9857
9858                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9859                         if (exception_type == EXERROR && spclbltin <= 0) {
9860                                 FORCE_INT_ON;
9861                                 goto readstatus;
9862                         }
9863  raise:
9864                         longjmp(exception_handler->loc, 1);
9865                 }
9866                 goto readstatus;
9867
9868         case CMDFUNCTION:
9869                 poplocalvars(1);
9870                 /* See above for the rationale */
9871                 dowait(DOWAIT_NONBLOCK, NULL);
9872                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9873                         goto raise;
9874  readstatus:
9875                 status = exitstatus;
9876                 break;
9877         } /* switch */
9878
9879  out:
9880         if (cmd->ncmd.redirect)
9881                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9882         unwindlocalvars(localvar_stop);
9883         if (lastarg) {
9884                 /* dsl: I think this is intended to be used to support
9885                  * '_' in 'vi' command mode during line editing...
9886                  * However I implemented that within libedit itself.
9887                  */
9888                 setvar0("_", lastarg);
9889         }
9890         popstackmark(&smark);
9891
9892         return status;
9893 }
9894
9895 static int
9896 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9897 {
9898         char *volatile savecmdname;
9899         struct jmploc *volatile savehandler;
9900         struct jmploc jmploc;
9901         int status;
9902         int i;
9903
9904         savecmdname = commandname;
9905         savehandler = exception_handler;
9906         i = setjmp(jmploc.loc);
9907         if (i)
9908                 goto cmddone;
9909         exception_handler = &jmploc;
9910         commandname = argv[0];
9911         argptr = argv + 1;
9912         optptr = NULL;                  /* initialize nextopt */
9913         if (cmd == EVALCMD)
9914                 status = evalcmd(argc, argv, flags);
9915         else
9916                 status = (*cmd->builtin)(argc, argv);
9917         flush_stdout_stderr();
9918         status |= ferror(stdout);
9919         exitstatus = status;
9920  cmddone:
9921         clearerr(stdout);
9922         commandname = savecmdname;
9923         exception_handler = savehandler;
9924
9925         return i;
9926 }
9927
9928 static int
9929 goodname(const char *p)
9930 {
9931         return endofname(p)[0] == '\0';
9932 }
9933
9934
9935 /*
9936  * Search for a command.  This is called before we fork so that the
9937  * location of the command will be available in the parent as well as
9938  * the child.  The check for "goodname" is an overly conservative
9939  * check that the name will not be subject to expansion.
9940  */
9941 static void
9942 prehash(union node *n)
9943 {
9944         struct cmdentry entry;
9945
9946         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9947                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9948 }
9949
9950
9951 /* ============ Builtin commands
9952  *
9953  * Builtin commands whose functions are closely tied to evaluation
9954  * are implemented here.
9955  */
9956
9957 /*
9958  * Handle break and continue commands.  Break, continue, and return are
9959  * all handled by setting the evalskip flag.  The evaluation routines
9960  * above all check this flag, and if it is set they start skipping
9961  * commands rather than executing them.  The variable skipcount is
9962  * the number of loops to break/continue, or the number of function
9963  * levels to return.  (The latter is always 1.)  It should probably
9964  * be an error to break out of more loops than exist, but it isn't
9965  * in the standard shell so we don't make it one here.
9966  */
9967 static int FAST_FUNC
9968 breakcmd(int argc UNUSED_PARAM, char **argv)
9969 {
9970         int n = argv[1] ? number(argv[1]) : 1;
9971
9972         if (n <= 0)
9973                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9974         if (n > loopnest)
9975                 n = loopnest;
9976         if (n > 0) {
9977                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9978                 skipcount = n;
9979         }
9980         return 0;
9981 }
9982
9983
9984 /*
9985  * This implements the input routines used by the parser.
9986  */
9987
9988 enum {
9989         INPUT_PUSH_FILE = 1,
9990         INPUT_NOFILE_OK = 2,
9991 };
9992
9993 static smallint checkkwd;
9994 /* values of checkkwd variable */
9995 #define CHKALIAS        0x1
9996 #define CHKKWD          0x2
9997 #define CHKNL           0x4
9998
9999 /*
10000  * Push a string back onto the input at this current parsefile level.
10001  * We handle aliases this way.
10002  */
10003 #if !ENABLE_ASH_ALIAS
10004 #define pushstring(s, ap) pushstring(s)
10005 #endif
10006 static void
10007 pushstring(char *s, struct alias *ap)
10008 {
10009         struct strpush *sp;
10010         int len;
10011
10012         len = strlen(s);
10013         INT_OFF;
10014         if (g_parsefile->strpush) {
10015                 sp = ckzalloc(sizeof(*sp));
10016                 sp->prev = g_parsefile->strpush;
10017         } else {
10018                 sp = &(g_parsefile->basestrpush);
10019         }
10020         g_parsefile->strpush = sp;
10021         sp->prev_string = g_parsefile->next_to_pgetc;
10022         sp->prev_left_in_line = g_parsefile->left_in_line;
10023         sp->unget = g_parsefile->unget;
10024         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10025 #if ENABLE_ASH_ALIAS
10026         sp->ap = ap;
10027         if (ap) {
10028                 ap->flag |= ALIASINUSE;
10029                 sp->string = s;
10030         }
10031 #endif
10032         g_parsefile->next_to_pgetc = s;
10033         g_parsefile->left_in_line = len;
10034         g_parsefile->unget = 0;
10035         INT_ON;
10036 }
10037
10038 static void
10039 popstring(void)
10040 {
10041         struct strpush *sp = g_parsefile->strpush;
10042
10043         INT_OFF;
10044 #if ENABLE_ASH_ALIAS
10045         if (sp->ap) {
10046                 if (g_parsefile->next_to_pgetc[-1] == ' '
10047                  || g_parsefile->next_to_pgetc[-1] == '\t'
10048                 ) {
10049                         checkkwd |= CHKALIAS;
10050                 }
10051                 if (sp->string != sp->ap->val) {
10052                         free(sp->string);
10053                 }
10054                 sp->ap->flag &= ~ALIASINUSE;
10055                 if (sp->ap->flag & ALIASDEAD) {
10056                         unalias(sp->ap->name);
10057                 }
10058         }
10059 #endif
10060         g_parsefile->next_to_pgetc = sp->prev_string;
10061         g_parsefile->left_in_line = sp->prev_left_in_line;
10062         g_parsefile->unget = sp->unget;
10063         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10064         g_parsefile->strpush = sp->prev;
10065         if (sp != &(g_parsefile->basestrpush))
10066                 free(sp);
10067         INT_ON;
10068 }
10069
10070 static int
10071 preadfd(void)
10072 {
10073         int nr;
10074         char *buf = g_parsefile->buf;
10075
10076         g_parsefile->next_to_pgetc = buf;
10077 #if ENABLE_FEATURE_EDITING
10078  retry:
10079         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10080                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10081         else {
10082                 int timeout = -1;
10083 # if ENABLE_ASH_IDLE_TIMEOUT
10084                 if (iflag) {
10085                         const char *tmout_var = lookupvar("TMOUT");
10086                         if (tmout_var) {
10087                                 timeout = atoi(tmout_var) * 1000;
10088                                 if (timeout <= 0)
10089                                         timeout = -1;
10090                         }
10091                 }
10092 # endif
10093 # if ENABLE_FEATURE_TAB_COMPLETION
10094                 line_input_state->path_lookup = pathval();
10095 # endif
10096                 reinit_unicode_for_ash();
10097                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10098                 if (nr == 0) {
10099                         /* ^C pressed, "convert" to SIGINT */
10100                         write(STDOUT_FILENO, "^C", 2);
10101                         if (trap[SIGINT]) {
10102                                 buf[0] = '\n';
10103                                 buf[1] = '\0';
10104                                 raise(SIGINT);
10105                                 return 1;
10106                         }
10107                         exitstatus = 128 + SIGINT;
10108                         bb_putchar('\n');
10109                         goto retry;
10110                 }
10111                 if (nr < 0) {
10112                         if (errno == 0) {
10113                                 /* Ctrl+D pressed */
10114                                 nr = 0;
10115                         }
10116 # if ENABLE_ASH_IDLE_TIMEOUT
10117                         else if (errno == EAGAIN && timeout > 0) {
10118                                 puts("\007timed out waiting for input: auto-logout");
10119                                 exitshell();
10120                         }
10121 # endif
10122                 }
10123         }
10124 #else
10125         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10126 #endif
10127
10128 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10129         if (nr < 0) {
10130                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10131                         int flags = fcntl(0, F_GETFL);
10132                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10133                                 flags &= ~O_NONBLOCK;
10134                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10135                                         out2str("sh: turning off NDELAY mode\n");
10136                                         goto retry;
10137                                 }
10138                         }
10139                 }
10140         }
10141 #endif
10142         return nr;
10143 }
10144
10145 /*
10146  * Refill the input buffer and return the next input character:
10147  *
10148  * 1) If a string was pushed back on the input, pop it;
10149  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10150  *    or we are reading from a string so we can't refill the buffer,
10151  *    return EOF.
10152  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10153  * 4) Process input up to the next newline, deleting nul characters.
10154  */
10155 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10156 #define pgetc_debug(...) ((void)0)
10157 static int pgetc(void);
10158 static int
10159 preadbuffer(void)
10160 {
10161         char *q;
10162         int more;
10163
10164         if (g_parsefile->strpush) {
10165 #if ENABLE_ASH_ALIAS
10166                 if (g_parsefile->left_in_line == -1
10167                  && g_parsefile->strpush->ap
10168                  && g_parsefile->next_to_pgetc[-1] != ' '
10169                  && g_parsefile->next_to_pgetc[-1] != '\t'
10170                 ) {
10171                         pgetc_debug("preadbuffer PEOA");
10172                         return PEOA;
10173                 }
10174 #endif
10175                 popstring();
10176                 return pgetc();
10177         }
10178         /* on both branches above g_parsefile->left_in_line < 0.
10179          * "pgetc" needs refilling.
10180          */
10181
10182         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10183          * pungetc() may increment it a few times.
10184          * Assuming it won't increment it to less than -90.
10185          */
10186         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10187                 pgetc_debug("preadbuffer PEOF1");
10188                 /* even in failure keep left_in_line and next_to_pgetc
10189                  * in lock step, for correct multi-layer pungetc.
10190                  * left_in_line was decremented before preadbuffer(),
10191                  * must inc next_to_pgetc: */
10192                 g_parsefile->next_to_pgetc++;
10193                 return PEOF;
10194         }
10195
10196         more = g_parsefile->left_in_buffer;
10197         if (more <= 0) {
10198                 flush_stdout_stderr();
10199  again:
10200                 more = preadfd();
10201                 if (more <= 0) {
10202                         /* don't try reading again */
10203                         g_parsefile->left_in_line = -99;
10204                         pgetc_debug("preadbuffer PEOF2");
10205                         g_parsefile->next_to_pgetc++;
10206                         return PEOF;
10207                 }
10208         }
10209
10210         /* Find out where's the end of line.
10211          * Set g_parsefile->left_in_line
10212          * and g_parsefile->left_in_buffer acordingly.
10213          * NUL chars are deleted.
10214          */
10215         q = g_parsefile->next_to_pgetc;
10216         for (;;) {
10217                 char c;
10218
10219                 more--;
10220
10221                 c = *q;
10222                 if (c == '\0') {
10223                         memmove(q, q + 1, more);
10224                 } else {
10225                         q++;
10226                         if (c == '\n') {
10227                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10228                                 break;
10229                         }
10230                 }
10231
10232                 if (more <= 0) {
10233                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10234                         if (g_parsefile->left_in_line < 0)
10235                                 goto again;
10236                         break;
10237                 }
10238         }
10239         g_parsefile->left_in_buffer = more;
10240
10241         if (vflag) {
10242                 char save = *q;
10243                 *q = '\0';
10244                 out2str(g_parsefile->next_to_pgetc);
10245                 *q = save;
10246         }
10247
10248         pgetc_debug("preadbuffer at %d:%p'%s'",
10249                         g_parsefile->left_in_line,
10250                         g_parsefile->next_to_pgetc,
10251                         g_parsefile->next_to_pgetc);
10252         return (unsigned char)*g_parsefile->next_to_pgetc++;
10253 }
10254
10255 static void
10256 nlprompt(void)
10257 {
10258         g_parsefile->linno++;
10259         setprompt_if(doprompt, 2);
10260 }
10261 static void
10262 nlnoprompt(void)
10263 {
10264         g_parsefile->linno++;
10265         needprompt = doprompt;
10266 }
10267
10268 static int
10269 pgetc(void)
10270 {
10271         int c;
10272
10273         pgetc_debug("pgetc at %d:%p'%s'",
10274                         g_parsefile->left_in_line,
10275                         g_parsefile->next_to_pgetc,
10276                         g_parsefile->next_to_pgetc);
10277         if (g_parsefile->unget)
10278                 return g_parsefile->lastc[--g_parsefile->unget];
10279
10280         if (--g_parsefile->left_in_line >= 0)
10281                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10282         else
10283                 c = preadbuffer();
10284
10285         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10286         g_parsefile->lastc[0] = c;
10287
10288         return c;
10289 }
10290
10291 #if ENABLE_ASH_ALIAS
10292 static int
10293 pgetc_without_PEOA(void)
10294 {
10295         int c;
10296         do {
10297                 pgetc_debug("pgetc at %d:%p'%s'",
10298                                 g_parsefile->left_in_line,
10299                                 g_parsefile->next_to_pgetc,
10300                                 g_parsefile->next_to_pgetc);
10301                 c = pgetc();
10302         } while (c == PEOA);
10303         return c;
10304 }
10305 #else
10306 # define pgetc_without_PEOA() pgetc()
10307 #endif
10308
10309 /*
10310  * Read a line from the script.
10311  */
10312 static char *
10313 pfgets(char *line, int len)
10314 {
10315         char *p = line;
10316         int nleft = len;
10317         int c;
10318
10319         while (--nleft > 0) {
10320                 c = pgetc_without_PEOA();
10321                 if (c == PEOF) {
10322                         if (p == line)
10323                                 return NULL;
10324                         break;
10325                 }
10326                 *p++ = c;
10327                 if (c == '\n')
10328                         break;
10329         }
10330         *p = '\0';
10331         return line;
10332 }
10333
10334 /*
10335  * Undo a call to pgetc.  Only two characters may be pushed back.
10336  * PEOF may be pushed back.
10337  */
10338 static void
10339 pungetc(void)
10340 {
10341         g_parsefile->unget++;
10342 }
10343
10344 /* This one eats backslash+newline */
10345 static int
10346 pgetc_eatbnl(void)
10347 {
10348         int c;
10349
10350         while ((c = pgetc()) == '\\') {
10351                 if (pgetc() != '\n') {
10352                         pungetc();
10353                         break;
10354                 }
10355
10356                 nlprompt();
10357         }
10358
10359         return c;
10360 }
10361
10362 /*
10363  * To handle the "." command, a stack of input files is used.  Pushfile
10364  * adds a new entry to the stack and popfile restores the previous level.
10365  */
10366 static void
10367 pushfile(void)
10368 {
10369         struct parsefile *pf;
10370
10371         pf = ckzalloc(sizeof(*pf));
10372         pf->prev = g_parsefile;
10373         pf->pf_fd = -1;
10374         /*pf->strpush = NULL; - ckzalloc did it */
10375         /*pf->basestrpush.prev = NULL;*/
10376         /*pf->unget = 0;*/
10377         g_parsefile = pf;
10378 }
10379
10380 static void
10381 popfile(void)
10382 {
10383         struct parsefile *pf = g_parsefile;
10384
10385         if (pf == &basepf)
10386                 return;
10387
10388         INT_OFF;
10389         if (pf->pf_fd >= 0)
10390                 close(pf->pf_fd);
10391         free(pf->buf);
10392         while (pf->strpush)
10393                 popstring();
10394         g_parsefile = pf->prev;
10395         free(pf);
10396         INT_ON;
10397 }
10398
10399 /*
10400  * Return to top level.
10401  */
10402 static void
10403 popallfiles(void)
10404 {
10405         while (g_parsefile != &basepf)
10406                 popfile();
10407 }
10408
10409 /*
10410  * Close the file(s) that the shell is reading commands from.  Called
10411  * after a fork is done.
10412  */
10413 static void
10414 closescript(void)
10415 {
10416         popallfiles();
10417         if (g_parsefile->pf_fd > 0) {
10418                 close(g_parsefile->pf_fd);
10419                 g_parsefile->pf_fd = 0;
10420         }
10421 }
10422
10423 /*
10424  * Like setinputfile, but takes an open file descriptor.  Call this with
10425  * interrupts off.
10426  */
10427 static void
10428 setinputfd(int fd, int push)
10429 {
10430         if (push) {
10431                 pushfile();
10432                 g_parsefile->buf = NULL;
10433         }
10434         g_parsefile->pf_fd = fd;
10435         if (g_parsefile->buf == NULL)
10436                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10437         g_parsefile->left_in_buffer = 0;
10438         g_parsefile->left_in_line = 0;
10439         g_parsefile->linno = 1;
10440 }
10441
10442 /*
10443  * Set the input to take input from a file.  If push is set, push the
10444  * old input onto the stack first.
10445  */
10446 static int
10447 setinputfile(const char *fname, int flags)
10448 {
10449         int fd;
10450
10451         INT_OFF;
10452         fd = open(fname, O_RDONLY);
10453         if (fd < 0) {
10454                 if (flags & INPUT_NOFILE_OK)
10455                         goto out;
10456                 exitstatus = 127;
10457                 ash_msg_and_raise_error("can't open '%s'", fname);
10458         }
10459         if (fd < 10)
10460                 fd = savefd(fd);
10461         else
10462                 close_on_exec_on(fd);
10463         setinputfd(fd, flags & INPUT_PUSH_FILE);
10464  out:
10465         INT_ON;
10466         return fd;
10467 }
10468
10469 /*
10470  * Like setinputfile, but takes input from a string.
10471  */
10472 static void
10473 setinputstring(char *string)
10474 {
10475         INT_OFF;
10476         pushfile();
10477         g_parsefile->next_to_pgetc = string;
10478         g_parsefile->left_in_line = strlen(string);
10479         g_parsefile->buf = NULL;
10480         g_parsefile->linno = 1;
10481         INT_ON;
10482 }
10483
10484
10485 /*
10486  * Routines to check for mail.
10487  */
10488
10489 #if ENABLE_ASH_MAIL
10490
10491 /* Hash of mtimes of mailboxes */
10492 static unsigned mailtime_hash;
10493 /* Set if MAIL or MAILPATH is changed. */
10494 static smallint mail_var_path_changed;
10495
10496 /*
10497  * Print appropriate message(s) if mail has arrived.
10498  * If mail_var_path_changed is set,
10499  * then the value of MAIL has mail_var_path_changed,
10500  * so we just update the values.
10501  */
10502 static void
10503 chkmail(void)
10504 {
10505         const char *mpath;
10506         char *p;
10507         char *q;
10508         unsigned new_hash;
10509         struct stackmark smark;
10510         struct stat statb;
10511
10512         setstackmark(&smark);
10513         mpath = mpathset() ? mpathval() : mailval();
10514         new_hash = 0;
10515         for (;;) {
10516                 p = path_advance(&mpath, nullstr);
10517                 if (p == NULL)
10518                         break;
10519                 if (*p == '\0')
10520                         continue;
10521                 for (q = p; *q; q++)
10522                         continue;
10523 #if DEBUG
10524                 if (q[-1] != '/')
10525                         abort();
10526 #endif
10527                 q[-1] = '\0';                   /* delete trailing '/' */
10528                 if (stat(p, &statb) < 0) {
10529                         continue;
10530                 }
10531                 /* Very simplistic "hash": just a sum of all mtimes */
10532                 new_hash += (unsigned)statb.st_mtime;
10533         }
10534         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10535                 if (mailtime_hash != 0)
10536                         out2str("you have mail\n");
10537                 mailtime_hash = new_hash;
10538         }
10539         mail_var_path_changed = 0;
10540         popstackmark(&smark);
10541 }
10542
10543 static void FAST_FUNC
10544 changemail(const char *val UNUSED_PARAM)
10545 {
10546         mail_var_path_changed = 1;
10547 }
10548
10549 #endif /* ASH_MAIL */
10550
10551
10552 /* ============ ??? */
10553
10554 /*
10555  * Set the shell parameters.
10556  */
10557 static void
10558 setparam(char **argv)
10559 {
10560         char **newparam;
10561         char **ap;
10562         int nparam;
10563
10564         for (nparam = 0; argv[nparam]; nparam++)
10565                 continue;
10566         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10567         while (*argv) {
10568                 *ap++ = ckstrdup(*argv++);
10569         }
10570         *ap = NULL;
10571         freeparam(&shellparam);
10572         shellparam.malloced = 1;
10573         shellparam.nparam = nparam;
10574         shellparam.p = newparam;
10575 #if ENABLE_ASH_GETOPTS
10576         shellparam.optind = 1;
10577         shellparam.optoff = -1;
10578 #endif
10579 }
10580
10581 /*
10582  * Process shell options.  The global variable argptr contains a pointer
10583  * to the argument list; we advance it past the options.
10584  *
10585  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10586  * For a non-interactive shell, an error condition encountered
10587  * by a special built-in ... shall cause the shell to write a diagnostic message
10588  * to standard error and exit as shown in the following table:
10589  * Error                                           Special Built-In
10590  * ...
10591  * Utility syntax error (option or operand error)  Shall exit
10592  * ...
10593  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10594  * we see that bash does not do that (set "finishes" with error code 1 instead,
10595  * and shell continues), and people rely on this behavior!
10596  * Testcase:
10597  * set -o barfoo 2>/dev/null
10598  * echo $?
10599  *
10600  * Oh well. Let's mimic that.
10601  */
10602 static int
10603 plus_minus_o(char *name, int val)
10604 {
10605         int i;
10606
10607         if (name) {
10608                 for (i = 0; i < NOPTS; i++) {
10609                         if (strcmp(name, optnames(i)) == 0) {
10610                                 optlist[i] = val;
10611                                 return 0;
10612                         }
10613                 }
10614                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10615                 return 1;
10616         }
10617         for (i = 0; i < NOPTS; i++) {
10618                 if (val) {
10619                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10620                 } else {
10621                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10622                 }
10623         }
10624         return 0;
10625 }
10626 static void
10627 setoption(int flag, int val)
10628 {
10629         int i;
10630
10631         for (i = 0; i < NOPTS; i++) {
10632                 if (optletters(i) == flag) {
10633                         optlist[i] = val;
10634                         return;
10635                 }
10636         }
10637         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10638         /* NOTREACHED */
10639 }
10640 static int
10641 options(int cmdline)
10642 {
10643         char *p;
10644         int val;
10645         int c;
10646
10647         if (cmdline)
10648                 minusc = NULL;
10649         while ((p = *argptr) != NULL) {
10650                 c = *p++;
10651                 if (c != '-' && c != '+')
10652                         break;
10653                 argptr++;
10654                 val = 0; /* val = 0 if c == '+' */
10655                 if (c == '-') {
10656                         val = 1;
10657                         if (p[0] == '\0' || LONE_DASH(p)) {
10658                                 if (!cmdline) {
10659                                         /* "-" means turn off -x and -v */
10660                                         if (p[0] == '\0')
10661                                                 xflag = vflag = 0;
10662                                         /* "--" means reset params */
10663                                         else if (*argptr == NULL)
10664                                                 setparam(argptr);
10665                                 }
10666                                 break;    /* "-" or "--" terminates options */
10667                         }
10668                 }
10669                 /* first char was + or - */
10670                 while ((c = *p++) != '\0') {
10671                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10672                         if (c == 'c' && cmdline) {
10673                                 minusc = p;     /* command is after shell args */
10674                         } else if (c == 'o') {
10675                                 if (plus_minus_o(*argptr, val)) {
10676                                         /* it already printed err message */
10677                                         return 1; /* error */
10678                                 }
10679                                 if (*argptr)
10680                                         argptr++;
10681                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10682                                 isloginsh = 1;
10683                         /* bash does not accept +-login, we also won't */
10684                         } else if (cmdline && val && (c == '-')) { /* long options */
10685                                 if (strcmp(p, "login") == 0)
10686                                         isloginsh = 1;
10687                                 break;
10688                         } else {
10689                                 setoption(c, val);
10690                         }
10691                 }
10692         }
10693         return 0;
10694 }
10695
10696 /*
10697  * The shift builtin command.
10698  */
10699 static int FAST_FUNC
10700 shiftcmd(int argc UNUSED_PARAM, char **argv)
10701 {
10702         int n;
10703         char **ap1, **ap2;
10704
10705         n = 1;
10706         if (argv[1])
10707                 n = number(argv[1]);
10708         if (n > shellparam.nparam)
10709                 n = 0; /* bash compat, was = shellparam.nparam; */
10710         INT_OFF;
10711         shellparam.nparam -= n;
10712         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10713                 if (shellparam.malloced)
10714                         free(*ap1);
10715         }
10716         ap2 = shellparam.p;
10717         while ((*ap2++ = *ap1++) != NULL)
10718                 continue;
10719 #if ENABLE_ASH_GETOPTS
10720         shellparam.optind = 1;
10721         shellparam.optoff = -1;
10722 #endif
10723         INT_ON;
10724         return 0;
10725 }
10726
10727 /*
10728  * POSIX requires that 'set' (but not export or readonly) output the
10729  * variables in lexicographic order - by the locale's collating order (sigh).
10730  * Maybe we could keep them in an ordered balanced binary tree
10731  * instead of hashed lists.
10732  * For now just roll 'em through qsort for printing...
10733  */
10734 static int
10735 showvars(const char *sep_prefix, int on, int off)
10736 {
10737         const char *sep;
10738         char **ep, **epend;
10739
10740         ep = listvars(on, off, &epend);
10741         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10742
10743         sep = *sep_prefix ? " " : sep_prefix;
10744
10745         for (; ep < epend; ep++) {
10746                 const char *p;
10747                 const char *q;
10748
10749                 p = strchrnul(*ep, '=');
10750                 q = nullstr;
10751                 if (*p)
10752                         q = single_quote(++p);
10753                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10754         }
10755         return 0;
10756 }
10757
10758 /*
10759  * The set command builtin.
10760  */
10761 static int FAST_FUNC
10762 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10763 {
10764         int retval;
10765
10766         if (!argv[1])
10767                 return showvars(nullstr, 0, VUNSET);
10768
10769         INT_OFF;
10770         retval = options(/*cmdline:*/ 0);
10771         if (retval == 0) { /* if no parse error... */
10772                 optschanged();
10773                 if (*argptr != NULL) {
10774                         setparam(argptr);
10775                 }
10776         }
10777         INT_ON;
10778         return retval;
10779 }
10780
10781 #if ENABLE_ASH_RANDOM_SUPPORT
10782 static void FAST_FUNC
10783 change_random(const char *value)
10784 {
10785         uint32_t t;
10786
10787         if (value == NULL) {
10788                 /* "get", generate */
10789                 t = next_random(&random_gen);
10790                 /* set without recursion */
10791                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10792                 vrandom.flags &= ~VNOFUNC;
10793         } else {
10794                 /* set/reset */
10795                 t = strtoul(value, NULL, 10);
10796                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10797         }
10798 }
10799 #endif
10800
10801 #if ENABLE_ASH_GETOPTS
10802 static int
10803 getopts(char *optstr, char *optvar, char **optfirst)
10804 {
10805         char *p, *q;
10806         char c = '?';
10807         int done = 0;
10808         char sbuf[2];
10809         char **optnext;
10810         int ind = shellparam.optind;
10811         int off = shellparam.optoff;
10812
10813         sbuf[1] = '\0';
10814
10815         shellparam.optind = -1;
10816         optnext = optfirst + ind - 1;
10817
10818         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10819                 p = NULL;
10820         else
10821                 p = optnext[-1] + off;
10822         if (p == NULL || *p == '\0') {
10823                 /* Current word is done, advance */
10824                 p = *optnext;
10825                 if (p == NULL || *p != '-' || *++p == '\0') {
10826  atend:
10827                         p = NULL;
10828                         done = 1;
10829                         goto out;
10830                 }
10831                 optnext++;
10832                 if (LONE_DASH(p))        /* check for "--" */
10833                         goto atend;
10834         }
10835
10836         c = *p++;
10837         for (q = optstr; *q != c;) {
10838                 if (*q == '\0') {
10839                         if (optstr[0] == ':') {
10840                                 sbuf[0] = c;
10841                                 /*sbuf[1] = '\0'; - already is */
10842                                 setvar0("OPTARG", sbuf);
10843                         } else {
10844                                 fprintf(stderr, "Illegal option -%c\n", c);
10845                                 unsetvar("OPTARG");
10846                         }
10847                         c = '?';
10848                         goto out;
10849                 }
10850                 if (*++q == ':')
10851                         q++;
10852         }
10853
10854         if (*++q == ':') {
10855                 if (*p == '\0' && (p = *optnext) == NULL) {
10856                         if (optstr[0] == ':') {
10857                                 sbuf[0] = c;
10858                                 /*sbuf[1] = '\0'; - already is */
10859                                 setvar0("OPTARG", sbuf);
10860                                 c = ':';
10861                         } else {
10862                                 fprintf(stderr, "No arg for -%c option\n", c);
10863                                 unsetvar("OPTARG");
10864                                 c = '?';
10865                         }
10866                         goto out;
10867                 }
10868
10869                 if (p == *optnext)
10870                         optnext++;
10871                 setvar0("OPTARG", p);
10872                 p = NULL;
10873         } else
10874                 setvar0("OPTARG", nullstr);
10875  out:
10876         ind = optnext - optfirst + 1;
10877         setvar("OPTIND", itoa(ind), VNOFUNC);
10878         sbuf[0] = c;
10879         /*sbuf[1] = '\0'; - already is */
10880         setvar0(optvar, sbuf);
10881
10882         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10883         shellparam.optind = ind;
10884
10885         return done;
10886 }
10887
10888 /*
10889  * The getopts builtin.  Shellparam.optnext points to the next argument
10890  * to be processed.  Shellparam.optptr points to the next character to
10891  * be processed in the current argument.  If shellparam.optnext is NULL,
10892  * then it's the first time getopts has been called.
10893  */
10894 static int FAST_FUNC
10895 getoptscmd(int argc, char **argv)
10896 {
10897         char **optbase;
10898
10899         if (argc < 3)
10900                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10901         if (argc == 3) {
10902                 optbase = shellparam.p;
10903                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10904                         shellparam.optind = 1;
10905                         shellparam.optoff = -1;
10906                 }
10907         } else {
10908                 optbase = &argv[3];
10909                 if ((unsigned)shellparam.optind > argc - 2) {
10910                         shellparam.optind = 1;
10911                         shellparam.optoff = -1;
10912                 }
10913         }
10914
10915         return getopts(argv[1], argv[2], optbase);
10916 }
10917 #endif /* ASH_GETOPTS */
10918
10919
10920 /* ============ Shell parser */
10921
10922 struct heredoc {
10923         struct heredoc *next;   /* next here document in list */
10924         union node *here;       /* redirection node */
10925         char *eofmark;          /* string indicating end of input */
10926         smallint striptabs;     /* if set, strip leading tabs */
10927 };
10928
10929 static smallint tokpushback;           /* last token pushed back */
10930 static smallint quoteflag;             /* set if (part of) last token was quoted */
10931 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10932 static struct heredoc *heredoclist;    /* list of here documents to read */
10933 static char *wordtext;                 /* text of last word returned by readtoken */
10934 static struct nodelist *backquotelist;
10935 static union node *redirnode;
10936 static struct heredoc *heredoc;
10937
10938 static const char *
10939 tokname(char *buf, int tok)
10940 {
10941         if (tok < TSEMI)
10942                 return tokname_array[tok];
10943         sprintf(buf, "\"%s\"", tokname_array[tok]);
10944         return buf;
10945 }
10946
10947 /* raise_error_unexpected_syntax:
10948  * Called when an unexpected token is read during the parse.  The argument
10949  * is the token that is expected, or -1 if more than one type of token can
10950  * occur at this point.
10951  */
10952 static void raise_error_unexpected_syntax(int) NORETURN;
10953 static void
10954 raise_error_unexpected_syntax(int token)
10955 {
10956         char msg[64];
10957         char buf[16];
10958         int l;
10959
10960         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10961         if (token >= 0)
10962                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10963         raise_error_syntax(msg);
10964         /* NOTREACHED */
10965 }
10966
10967 #define EOFMARKLEN 79
10968
10969 /* parsing is heavily cross-recursive, need these forward decls */
10970 static union node *andor(void);
10971 static union node *pipeline(void);
10972 static union node *parse_command(void);
10973 static void parseheredoc(void);
10974 static int peektoken(void);
10975 static int readtoken(void);
10976
10977 static union node *
10978 list(int nlflag)
10979 {
10980         union node *n1, *n2, *n3;
10981         int tok;
10982
10983         n1 = NULL;
10984         for (;;) {
10985                 switch (peektoken()) {
10986                 case TNL:
10987                         if (!(nlflag & 1))
10988                                 break;
10989                         parseheredoc();
10990                         return n1;
10991
10992                 case TEOF:
10993                         if (!n1 && (nlflag & 1))
10994                                 n1 = NODE_EOF;
10995                         parseheredoc();
10996                         return n1;
10997                 }
10998
10999                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11000                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11001                         return n1;
11002                 nlflag |= 2;
11003
11004                 n2 = andor();
11005                 tok = readtoken();
11006                 if (tok == TBACKGND) {
11007                         if (n2->type == NPIPE) {
11008                                 n2->npipe.pipe_backgnd = 1;
11009                         } else {
11010                                 if (n2->type != NREDIR) {
11011                                         n3 = stzalloc(sizeof(struct nredir));
11012                                         n3->nredir.n = n2;
11013                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11014                                         n2 = n3;
11015                                 }
11016                                 n2->type = NBACKGND;
11017                         }
11018                 }
11019                 if (n1 == NULL) {
11020                         n1 = n2;
11021                 } else {
11022                         n3 = stzalloc(sizeof(struct nbinary));
11023                         n3->type = NSEMI;
11024                         n3->nbinary.ch1 = n1;
11025                         n3->nbinary.ch2 = n2;
11026                         n1 = n3;
11027                 }
11028                 switch (tok) {
11029                 case TNL:
11030                 case TEOF:
11031                         tokpushback = 1;
11032                         /* fall through */
11033                 case TBACKGND:
11034                 case TSEMI:
11035                         break;
11036                 default:
11037                         if ((nlflag & 1))
11038                                 raise_error_unexpected_syntax(-1);
11039                         tokpushback = 1;
11040                         return n1;
11041                 }
11042         }
11043 }
11044
11045 static union node *
11046 andor(void)
11047 {
11048         union node *n1, *n2, *n3;
11049         int t;
11050
11051         n1 = pipeline();
11052         for (;;) {
11053                 t = readtoken();
11054                 if (t == TAND) {
11055                         t = NAND;
11056                 } else if (t == TOR) {
11057                         t = NOR;
11058                 } else {
11059                         tokpushback = 1;
11060                         return n1;
11061                 }
11062                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11063                 n2 = pipeline();
11064                 n3 = stzalloc(sizeof(struct nbinary));
11065                 n3->type = t;
11066                 n3->nbinary.ch1 = n1;
11067                 n3->nbinary.ch2 = n2;
11068                 n1 = n3;
11069         }
11070 }
11071
11072 static union node *
11073 pipeline(void)
11074 {
11075         union node *n1, *n2, *pipenode;
11076         struct nodelist *lp, *prev;
11077         int negate;
11078
11079         negate = 0;
11080         TRACE(("pipeline: entered\n"));
11081         if (readtoken() == TNOT) {
11082                 negate = !negate;
11083                 checkkwd = CHKKWD | CHKALIAS;
11084         } else
11085                 tokpushback = 1;
11086         n1 = parse_command();
11087         if (readtoken() == TPIPE) {
11088                 pipenode = stzalloc(sizeof(struct npipe));
11089                 pipenode->type = NPIPE;
11090                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11091                 lp = stzalloc(sizeof(struct nodelist));
11092                 pipenode->npipe.cmdlist = lp;
11093                 lp->n = n1;
11094                 do {
11095                         prev = lp;
11096                         lp = stzalloc(sizeof(struct nodelist));
11097                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11098                         lp->n = parse_command();
11099                         prev->next = lp;
11100                 } while (readtoken() == TPIPE);
11101                 lp->next = NULL;
11102                 n1 = pipenode;
11103         }
11104         tokpushback = 1;
11105         if (negate) {
11106                 n2 = stzalloc(sizeof(struct nnot));
11107                 n2->type = NNOT;
11108                 n2->nnot.com = n1;
11109                 return n2;
11110         }
11111         return n1;
11112 }
11113
11114 static union node *
11115 makename(void)
11116 {
11117         union node *n;
11118
11119         n = stzalloc(sizeof(struct narg));
11120         n->type = NARG;
11121         /*n->narg.next = NULL; - stzalloc did it */
11122         n->narg.text = wordtext;
11123         n->narg.backquote = backquotelist;
11124         return n;
11125 }
11126
11127 static void
11128 fixredir(union node *n, const char *text, int err)
11129 {
11130         int fd;
11131
11132         TRACE(("Fix redir %s %d\n", text, err));
11133         if (!err)
11134                 n->ndup.vname = NULL;
11135
11136         fd = bb_strtou(text, NULL, 10);
11137         if (!errno && fd >= 0)
11138                 n->ndup.dupfd = fd;
11139         else if (LONE_DASH(text))
11140                 n->ndup.dupfd = -1;
11141         else {
11142                 if (err)
11143                         raise_error_syntax("bad fd number");
11144                 n->ndup.vname = makename();
11145         }
11146 }
11147
11148 /*
11149  * Returns true if the text contains nothing to expand (no dollar signs
11150  * or backquotes).
11151  */
11152 static int
11153 noexpand(const char *text)
11154 {
11155         unsigned char c;
11156
11157         while ((c = *text++) != '\0') {
11158                 if (c == CTLQUOTEMARK)
11159                         continue;
11160                 if (c == CTLESC)
11161                         text++;
11162                 else if (SIT(c, BASESYNTAX) == CCTL)
11163                         return 0;
11164         }
11165         return 1;
11166 }
11167
11168 static void
11169 parsefname(void)
11170 {
11171         union node *n = redirnode;
11172
11173         if (readtoken() != TWORD)
11174                 raise_error_unexpected_syntax(-1);
11175         if (n->type == NHERE) {
11176                 struct heredoc *here = heredoc;
11177                 struct heredoc *p;
11178                 int i;
11179
11180                 if (quoteflag == 0)
11181                         n->type = NXHERE;
11182                 TRACE(("Here document %d\n", n->type));
11183                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11184                         raise_error_syntax("illegal eof marker for << redirection");
11185                 rmescapes(wordtext, 0);
11186                 here->eofmark = wordtext;
11187                 here->next = NULL;
11188                 if (heredoclist == NULL)
11189                         heredoclist = here;
11190                 else {
11191                         for (p = heredoclist; p->next; p = p->next)
11192                                 continue;
11193                         p->next = here;
11194                 }
11195         } else if (n->type == NTOFD || n->type == NFROMFD) {
11196                 fixredir(n, wordtext, 0);
11197         } else {
11198                 n->nfile.fname = makename();
11199         }
11200 }
11201
11202 static union node *
11203 simplecmd(void)
11204 {
11205         union node *args, **app;
11206         union node *n = NULL;
11207         union node *vars, **vpp;
11208         union node **rpp, *redir;
11209         int savecheckkwd;
11210 #if BASH_TEST2
11211         smallint double_brackets_flag = 0;
11212 #endif
11213         IF_BASH_FUNCTION(smallint function_flag = 0;)
11214
11215         args = NULL;
11216         app = &args;
11217         vars = NULL;
11218         vpp = &vars;
11219         redir = NULL;
11220         rpp = &redir;
11221
11222         savecheckkwd = CHKALIAS;
11223         for (;;) {
11224                 int t;
11225                 checkkwd = savecheckkwd;
11226                 t = readtoken();
11227                 switch (t) {
11228 #if BASH_FUNCTION
11229                 case TFUNCTION:
11230                         if (peektoken() != TWORD)
11231                                 raise_error_unexpected_syntax(TWORD);
11232                         function_flag = 1;
11233                         break;
11234 #endif
11235 #if BASH_TEST2
11236                 case TAND: /* "&&" */
11237                 case TOR: /* "||" */
11238                         if (!double_brackets_flag) {
11239                                 tokpushback = 1;
11240                                 goto out;
11241                         }
11242                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11243 #endif
11244                 case TWORD:
11245                         n = stzalloc(sizeof(struct narg));
11246                         n->type = NARG;
11247                         /*n->narg.next = NULL; - stzalloc did it */
11248                         n->narg.text = wordtext;
11249 #if BASH_TEST2
11250                         if (strcmp("[[", wordtext) == 0)
11251                                 double_brackets_flag = 1;
11252                         else if (strcmp("]]", wordtext) == 0)
11253                                 double_brackets_flag = 0;
11254 #endif
11255                         n->narg.backquote = backquotelist;
11256                         if (savecheckkwd && isassignment(wordtext)) {
11257                                 *vpp = n;
11258                                 vpp = &n->narg.next;
11259                         } else {
11260                                 *app = n;
11261                                 app = &n->narg.next;
11262                                 savecheckkwd = 0;
11263                         }
11264 #if BASH_FUNCTION
11265                         if (function_flag) {
11266                                 checkkwd = CHKNL | CHKKWD;
11267                                 switch (peektoken()) {
11268                                 case TBEGIN:
11269                                 case TIF:
11270                                 case TCASE:
11271                                 case TUNTIL:
11272                                 case TWHILE:
11273                                 case TFOR:
11274                                         goto do_func;
11275                                 case TLP:
11276                                         function_flag = 0;
11277                                         break;
11278                                 case TWORD:
11279                                         if (strcmp("[[", wordtext) == 0)
11280                                                 goto do_func;
11281                                         /* fall through */
11282                                 default:
11283                                         raise_error_unexpected_syntax(-1);
11284                                 }
11285                         }
11286 #endif
11287                         break;
11288                 case TREDIR:
11289                         *rpp = n = redirnode;
11290                         rpp = &n->nfile.next;
11291                         parsefname();   /* read name of redirection file */
11292                         break;
11293                 case TLP:
11294  IF_BASH_FUNCTION(do_func:)
11295                         if (args && app == &args->narg.next
11296                          && !vars && !redir
11297                         ) {
11298                                 struct builtincmd *bcmd;
11299                                 const char *name;
11300
11301                                 /* We have a function */
11302                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11303                                         raise_error_unexpected_syntax(TRP);
11304                                 name = n->narg.text;
11305                                 if (!goodname(name)
11306                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11307                                 ) {
11308                                         raise_error_syntax("bad function name");
11309                                 }
11310                                 n->type = NDEFUN;
11311                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11312                                 n->narg.next = parse_command();
11313                                 return n;
11314                         }
11315                         IF_BASH_FUNCTION(function_flag = 0;)
11316                         /* fall through */
11317                 default:
11318                         tokpushback = 1;
11319                         goto out;
11320                 }
11321         }
11322  out:
11323         *app = NULL;
11324         *vpp = NULL;
11325         *rpp = NULL;
11326         n = stzalloc(sizeof(struct ncmd));
11327         n->type = NCMD;
11328         n->ncmd.args = args;
11329         n->ncmd.assign = vars;
11330         n->ncmd.redirect = redir;
11331         return n;
11332 }
11333
11334 static union node *
11335 parse_command(void)
11336 {
11337         union node *n1, *n2;
11338         union node *ap, **app;
11339         union node *cp, **cpp;
11340         union node *redir, **rpp;
11341         union node **rpp2;
11342         int t;
11343
11344         redir = NULL;
11345         rpp2 = &redir;
11346
11347         switch (readtoken()) {
11348         default:
11349                 raise_error_unexpected_syntax(-1);
11350                 /* NOTREACHED */
11351         case TIF:
11352                 n1 = stzalloc(sizeof(struct nif));
11353                 n1->type = NIF;
11354                 n1->nif.test = list(0);
11355                 if (readtoken() != TTHEN)
11356                         raise_error_unexpected_syntax(TTHEN);
11357                 n1->nif.ifpart = list(0);
11358                 n2 = n1;
11359                 while (readtoken() == TELIF) {
11360                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11361                         n2 = n2->nif.elsepart;
11362                         n2->type = NIF;
11363                         n2->nif.test = list(0);
11364                         if (readtoken() != TTHEN)
11365                                 raise_error_unexpected_syntax(TTHEN);
11366                         n2->nif.ifpart = list(0);
11367                 }
11368                 if (lasttoken == TELSE)
11369                         n2->nif.elsepart = list(0);
11370                 else {
11371                         n2->nif.elsepart = NULL;
11372                         tokpushback = 1;
11373                 }
11374                 t = TFI;
11375                 break;
11376         case TWHILE:
11377         case TUNTIL: {
11378                 int got;
11379                 n1 = stzalloc(sizeof(struct nbinary));
11380                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11381                 n1->nbinary.ch1 = list(0);
11382                 got = readtoken();
11383                 if (got != TDO) {
11384                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11385                                         got == TWORD ? wordtext : ""));
11386                         raise_error_unexpected_syntax(TDO);
11387                 }
11388                 n1->nbinary.ch2 = list(0);
11389                 t = TDONE;
11390                 break;
11391         }
11392         case TFOR:
11393                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11394                         raise_error_syntax("bad for loop variable");
11395                 n1 = stzalloc(sizeof(struct nfor));
11396                 n1->type = NFOR;
11397                 n1->nfor.var = wordtext;
11398                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11399                 if (readtoken() == TIN) {
11400                         app = &ap;
11401                         while (readtoken() == TWORD) {
11402                                 n2 = stzalloc(sizeof(struct narg));
11403                                 n2->type = NARG;
11404                                 /*n2->narg.next = NULL; - stzalloc did it */
11405                                 n2->narg.text = wordtext;
11406                                 n2->narg.backquote = backquotelist;
11407                                 *app = n2;
11408                                 app = &n2->narg.next;
11409                         }
11410                         *app = NULL;
11411                         n1->nfor.args = ap;
11412                         if (lasttoken != TNL && lasttoken != TSEMI)
11413                                 raise_error_unexpected_syntax(-1);
11414                 } else {
11415                         n2 = stzalloc(sizeof(struct narg));
11416                         n2->type = NARG;
11417                         /*n2->narg.next = NULL; - stzalloc did it */
11418                         n2->narg.text = (char *)dolatstr;
11419                         /*n2->narg.backquote = NULL;*/
11420                         n1->nfor.args = n2;
11421                         /*
11422                          * Newline or semicolon here is optional (but note
11423                          * that the original Bourne shell only allowed NL).
11424                          */
11425                         if (lasttoken != TSEMI)
11426                                 tokpushback = 1;
11427                 }
11428                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11429                 if (readtoken() != TDO)
11430                         raise_error_unexpected_syntax(TDO);
11431                 n1->nfor.body = list(0);
11432                 t = TDONE;
11433                 break;
11434         case TCASE:
11435                 n1 = stzalloc(sizeof(struct ncase));
11436                 n1->type = NCASE;
11437                 if (readtoken() != TWORD)
11438                         raise_error_unexpected_syntax(TWORD);
11439                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11440                 n2->type = NARG;
11441                 /*n2->narg.next = NULL; - stzalloc did it */
11442                 n2->narg.text = wordtext;
11443                 n2->narg.backquote = backquotelist;
11444                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11445                 if (readtoken() != TIN)
11446                         raise_error_unexpected_syntax(TIN);
11447                 cpp = &n1->ncase.cases;
11448  next_case:
11449                 checkkwd = CHKNL | CHKKWD;
11450                 t = readtoken();
11451                 while (t != TESAC) {
11452                         if (lasttoken == TLP)
11453                                 readtoken();
11454                         *cpp = cp = stzalloc(sizeof(struct nclist));
11455                         cp->type = NCLIST;
11456                         app = &cp->nclist.pattern;
11457                         for (;;) {
11458                                 *app = ap = stzalloc(sizeof(struct narg));
11459                                 ap->type = NARG;
11460                                 /*ap->narg.next = NULL; - stzalloc did it */
11461                                 ap->narg.text = wordtext;
11462                                 ap->narg.backquote = backquotelist;
11463                                 if (readtoken() != TPIPE)
11464                                         break;
11465                                 app = &ap->narg.next;
11466                                 readtoken();
11467                         }
11468                         //ap->narg.next = NULL;
11469                         if (lasttoken != TRP)
11470                                 raise_error_unexpected_syntax(TRP);
11471                         cp->nclist.body = list(2);
11472
11473                         cpp = &cp->nclist.next;
11474
11475                         checkkwd = CHKNL | CHKKWD;
11476                         t = readtoken();
11477                         if (t != TESAC) {
11478                                 if (t != TENDCASE)
11479                                         raise_error_unexpected_syntax(TENDCASE);
11480                                 goto next_case;
11481                         }
11482                 }
11483                 *cpp = NULL;
11484                 goto redir;
11485         case TLP:
11486                 n1 = stzalloc(sizeof(struct nredir));
11487                 n1->type = NSUBSHELL;
11488                 n1->nredir.n = list(0);
11489                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11490                 t = TRP;
11491                 break;
11492         case TBEGIN:
11493                 n1 = list(0);
11494                 t = TEND;
11495                 break;
11496         IF_BASH_FUNCTION(case TFUNCTION:)
11497         case TWORD:
11498         case TREDIR:
11499                 tokpushback = 1;
11500                 return simplecmd();
11501         }
11502
11503         if (readtoken() != t)
11504                 raise_error_unexpected_syntax(t);
11505
11506  redir:
11507         /* Now check for redirection which may follow command */
11508         checkkwd = CHKKWD | CHKALIAS;
11509         rpp = rpp2;
11510         while (readtoken() == TREDIR) {
11511                 *rpp = n2 = redirnode;
11512                 rpp = &n2->nfile.next;
11513                 parsefname();
11514         }
11515         tokpushback = 1;
11516         *rpp = NULL;
11517         if (redir) {
11518                 if (n1->type != NSUBSHELL) {
11519                         n2 = stzalloc(sizeof(struct nredir));
11520                         n2->type = NREDIR;
11521                         n2->nredir.n = n1;
11522                         n1 = n2;
11523                 }
11524                 n1->nredir.redirect = redir;
11525         }
11526         return n1;
11527 }
11528
11529 #if BASH_DOLLAR_SQUOTE
11530 static int
11531 decode_dollar_squote(void)
11532 {
11533         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11534         int c, cnt;
11535         char *p;
11536         char buf[4];
11537
11538         c = pgetc();
11539         p = strchr(C_escapes, c);
11540         if (p) {
11541                 buf[0] = c;
11542                 p = buf;
11543                 cnt = 3;
11544                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11545                         do {
11546                                 c = pgetc();
11547                                 *++p = c;
11548                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11549                         pungetc();
11550                 } else if (c == 'x') { /* \xHH */
11551                         do {
11552                                 c = pgetc();
11553                                 *++p = c;
11554                         } while (isxdigit(c) && --cnt);
11555                         pungetc();
11556                         if (cnt == 3) { /* \x but next char is "bad" */
11557                                 c = 'x';
11558                                 goto unrecognized;
11559                         }
11560                 } else { /* simple seq like \\ or \t */
11561                         p++;
11562                 }
11563                 *p = '\0';
11564                 p = buf;
11565                 c = bb_process_escape_sequence((void*)&p);
11566         } else { /* unrecognized "\z": print both chars unless ' or " */
11567                 if (c != '\'' && c != '"') {
11568  unrecognized:
11569                         c |= 0x100; /* "please encode \, then me" */
11570                 }
11571         }
11572         return c;
11573 }
11574 #endif
11575
11576 /*
11577  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11578  * is not NULL, read a here document.  In the latter case, eofmark is the
11579  * word which marks the end of the document and striptabs is true if
11580  * leading tabs should be stripped from the document.  The argument c
11581  * is the first character of the input token or document.
11582  *
11583  * Because C does not have internal subroutines, I have simulated them
11584  * using goto's to implement the subroutine linkage.  The following macros
11585  * will run code that appears at the end of readtoken1.
11586  */
11587 #define CHECKEND()      {goto checkend; checkend_return:;}
11588 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11589 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11590 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11591 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11592 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11593 static int
11594 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11595 {
11596         /* NB: syntax parameter fits into smallint */
11597         /* c parameter is an unsigned char or PEOF or PEOA */
11598         char *out;
11599         size_t len;
11600         char line[EOFMARKLEN + 1];
11601         struct nodelist *bqlist;
11602         smallint quotef;
11603         smallint dblquote;
11604         smallint oldstyle;
11605         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11606         smallint pssyntax;   /* we are expanding a prompt string */
11607         int varnest;         /* levels of variables expansion */
11608         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11609         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11610         int dqvarnest;       /* levels of variables expansion within double quotes */
11611
11612         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11613
11614         startlinno = g_parsefile->linno;
11615         bqlist = NULL;
11616         quotef = 0;
11617         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11618         pssyntax = (syntax == PSSYNTAX);
11619         if (pssyntax)
11620                 syntax = DQSYNTAX;
11621         dblquote = (syntax == DQSYNTAX);
11622         varnest = 0;
11623         IF_FEATURE_SH_MATH(arinest = 0;)
11624         IF_FEATURE_SH_MATH(parenlevel = 0;)
11625         dqvarnest = 0;
11626
11627         STARTSTACKSTR(out);
11628  loop:
11629         /* For each line, until end of word */
11630         CHECKEND();     /* set c to PEOF if at end of here document */
11631         for (;;) {      /* until end of line or end of word */
11632                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11633                 switch (SIT(c, syntax)) {
11634                 case CNL:       /* '\n' */
11635                         if (syntax == BASESYNTAX)
11636                                 goto endword;   /* exit outer loop */
11637                         USTPUTC(c, out);
11638                         nlprompt();
11639                         c = pgetc();
11640                         goto loop;              /* continue outer loop */
11641                 case CWORD:
11642                         USTPUTC(c, out);
11643                         break;
11644                 case CCTL:
11645 #if BASH_DOLLAR_SQUOTE
11646                         if (c == '\\' && bash_dollar_squote) {
11647                                 c = decode_dollar_squote();
11648                                 if (c == '\0') {
11649                                         /* skip $'\000', $'\x00' (like bash) */
11650                                         break;
11651                                 }
11652                                 if (c & 0x100) {
11653                                         /* Unknown escape. Encode as '\z' */
11654                                         c = (unsigned char)c;
11655                                         if (eofmark == NULL || dblquote)
11656                                                 USTPUTC(CTLESC, out);
11657                                         USTPUTC('\\', out);
11658                                 }
11659                         }
11660 #endif
11661                         if (eofmark == NULL || dblquote)
11662                                 USTPUTC(CTLESC, out);
11663                         USTPUTC(c, out);
11664                         break;
11665                 case CBACK:     /* backslash */
11666                         c = pgetc_without_PEOA();
11667                         if (c == PEOF) {
11668                                 USTPUTC(CTLESC, out);
11669                                 USTPUTC('\\', out);
11670                                 pungetc();
11671                         } else if (c == '\n') {
11672                                 nlprompt();
11673                         } else {
11674                                 if (c == '$' && pssyntax) {
11675                                         USTPUTC(CTLESC, out);
11676                                         USTPUTC('\\', out);
11677                                 }
11678                                 /* Backslash is retained if we are in "str" and next char isn't special */
11679                                 if (dblquote
11680                                  && c != '\\'
11681                                  && c != '`'
11682                                  && c != '$'
11683                                  && (c != '"' || eofmark != NULL)
11684                                 ) {
11685                                         USTPUTC('\\', out);
11686                                 }
11687                                 USTPUTC(CTLESC, out);
11688                                 USTPUTC(c, out);
11689                                 quotef = 1;
11690                         }
11691                         break;
11692                 case CSQUOTE:
11693                         syntax = SQSYNTAX;
11694  quotemark:
11695                         if (eofmark == NULL) {
11696                                 USTPUTC(CTLQUOTEMARK, out);
11697                         }
11698                         break;
11699                 case CDQUOTE:
11700                         syntax = DQSYNTAX;
11701                         dblquote = 1;
11702                         goto quotemark;
11703                 case CENDQUOTE:
11704                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11705                         if (eofmark != NULL && varnest == 0) {
11706                                 USTPUTC(c, out);
11707                         } else {
11708                                 if (dqvarnest == 0) {
11709                                         syntax = BASESYNTAX;
11710                                         dblquote = 0;
11711                                 }
11712                                 quotef = 1;
11713                                 goto quotemark;
11714                         }
11715                         break;
11716                 case CVAR:      /* '$' */
11717                         PARSESUB();             /* parse substitution */
11718                         break;
11719                 case CENDVAR:   /* '}' */
11720                         if (varnest > 0) {
11721                                 varnest--;
11722                                 if (dqvarnest > 0) {
11723                                         dqvarnest--;
11724                                 }
11725                                 c = CTLENDVAR;
11726                         }
11727                         USTPUTC(c, out);
11728                         break;
11729 #if ENABLE_FEATURE_SH_MATH
11730                 case CLP:       /* '(' in arithmetic */
11731                         parenlevel++;
11732                         USTPUTC(c, out);
11733                         break;
11734                 case CRP:       /* ')' in arithmetic */
11735                         if (parenlevel > 0) {
11736                                 parenlevel--;
11737                         } else {
11738                                 if (pgetc_eatbnl() == ')') {
11739                                         c = CTLENDARI;
11740                                         if (--arinest == 0) {
11741                                                 syntax = prevsyntax;
11742                                         }
11743                                 } else {
11744                                         /*
11745                                          * unbalanced parens
11746                                          * (don't 2nd guess - no error)
11747                                          */
11748                                         pungetc();
11749                                 }
11750                         }
11751                         USTPUTC(c, out);
11752                         break;
11753 #endif
11754                 case CBQUOTE:   /* '`' */
11755                         PARSEBACKQOLD();
11756                         break;
11757                 case CENDFILE:
11758                         goto endword;           /* exit outer loop */
11759                 case CIGN:
11760                         break;
11761                 default:
11762                         if (varnest == 0) {
11763 #if BASH_REDIR_OUTPUT
11764                                 if (c == '&') {
11765 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11766                                         if (pgetc() == '>')
11767                                                 c = 0x100 + '>'; /* flag &> */
11768                                         pungetc();
11769                                 }
11770 #endif
11771                                 goto endword;   /* exit outer loop */
11772                         }
11773                         IF_ASH_ALIAS(if (c != PEOA))
11774                                 USTPUTC(c, out);
11775                 }
11776                 c = pgetc();
11777         } /* for (;;) */
11778  endword:
11779
11780 #if ENABLE_FEATURE_SH_MATH
11781         if (syntax == ARISYNTAX)
11782                 raise_error_syntax("missing '))'");
11783 #endif
11784         if (syntax != BASESYNTAX && eofmark == NULL)
11785                 raise_error_syntax("unterminated quoted string");
11786         if (varnest != 0) {
11787                 startlinno = g_parsefile->linno;
11788                 /* { */
11789                 raise_error_syntax("missing '}'");
11790         }
11791         USTPUTC('\0', out);
11792         len = out - (char *)stackblock();
11793         out = stackblock();
11794         if (eofmark == NULL) {
11795                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11796                  && quotef == 0
11797                 ) {
11798                         if (isdigit_str9(out)) {
11799                                 PARSEREDIR(); /* passed as params: out, c */
11800                                 lasttoken = TREDIR;
11801                                 return lasttoken;
11802                         }
11803                         /* else: non-number X seen, interpret it
11804                          * as "NNNX>file" = "NNNX >file" */
11805                 }
11806                 pungetc();
11807         }
11808         quoteflag = quotef;
11809         backquotelist = bqlist;
11810         grabstackblock(len);
11811         wordtext = out;
11812         lasttoken = TWORD;
11813         return lasttoken;
11814 /* end of readtoken routine */
11815
11816 /*
11817  * Check to see whether we are at the end of the here document.  When this
11818  * is called, c is set to the first character of the next input line.  If
11819  * we are at the end of the here document, this routine sets the c to PEOF.
11820  */
11821 checkend: {
11822         if (eofmark) {
11823 #if ENABLE_ASH_ALIAS
11824                 if (c == PEOA)
11825                         c = pgetc_without_PEOA();
11826 #endif
11827                 if (striptabs) {
11828                         while (c == '\t') {
11829                                 c = pgetc_without_PEOA();
11830                         }
11831                 }
11832                 if (c == *eofmark) {
11833                         if (pfgets(line, sizeof(line)) != NULL) {
11834                                 char *p, *q;
11835                                 int cc;
11836
11837                                 p = line;
11838                                 for (q = eofmark + 1;; p++, q++) {
11839                                         cc = *p;
11840                                         if (cc == '\n')
11841                                                 cc = 0;
11842                                         if (!*q || cc != *q)
11843                                                 break;
11844                                 }
11845                                 if (cc == *q) {
11846                                         c = PEOF;
11847                                         nlnoprompt();
11848                                 } else {
11849                                         pushstring(line, NULL);
11850                                 }
11851                         }
11852                 }
11853         }
11854         goto checkend_return;
11855 }
11856
11857 /*
11858  * Parse a redirection operator.  The variable "out" points to a string
11859  * specifying the fd to be redirected.  The variable "c" contains the
11860  * first character of the redirection operator.
11861  */
11862 parseredir: {
11863         /* out is already checked to be a valid number or "" */
11864         int fd = (*out == '\0' ? -1 : atoi(out));
11865         union node *np;
11866
11867         np = stzalloc(sizeof(struct nfile));
11868         if (c == '>') {
11869                 np->nfile.fd = 1;
11870                 c = pgetc();
11871                 if (c == '>')
11872                         np->type = NAPPEND;
11873                 else if (c == '|')
11874                         np->type = NCLOBBER;
11875                 else if (c == '&')
11876                         np->type = NTOFD;
11877                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11878                 else {
11879                         np->type = NTO;
11880                         pungetc();
11881                 }
11882         }
11883 #if BASH_REDIR_OUTPUT
11884         else if (c == 0x100 + '>') { /* this flags &> redirection */
11885                 np->nfile.fd = 1;
11886                 pgetc(); /* this is '>', no need to check */
11887                 np->type = NTO2;
11888         }
11889 #endif
11890         else { /* c == '<' */
11891                 /*np->nfile.fd = 0; - stzalloc did it */
11892                 c = pgetc();
11893                 switch (c) {
11894                 case '<':
11895                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11896                                 np = stzalloc(sizeof(struct nhere));
11897                                 /*np->nfile.fd = 0; - stzalloc did it */
11898                         }
11899                         np->type = NHERE;
11900                         heredoc = stzalloc(sizeof(struct heredoc));
11901                         heredoc->here = np;
11902                         c = pgetc();
11903                         if (c == '-') {
11904                                 heredoc->striptabs = 1;
11905                         } else {
11906                                 /*heredoc->striptabs = 0; - stzalloc did it */
11907                                 pungetc();
11908                         }
11909                         break;
11910
11911                 case '&':
11912                         np->type = NFROMFD;
11913                         break;
11914
11915                 case '>':
11916                         np->type = NFROMTO;
11917                         break;
11918
11919                 default:
11920                         np->type = NFROM;
11921                         pungetc();
11922                         break;
11923                 }
11924         }
11925         if (fd >= 0)
11926                 np->nfile.fd = fd;
11927         redirnode = np;
11928         goto parseredir_return;
11929 }
11930
11931 /*
11932  * Parse a substitution.  At this point, we have read the dollar sign
11933  * and nothing else.
11934  */
11935
11936 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11937  * (assuming ascii char codes, as the original implementation did) */
11938 #define is_special(c) \
11939         (((unsigned)(c) - 33 < 32) \
11940                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11941 parsesub: {
11942         unsigned char subtype;
11943         int typeloc;
11944
11945         c = pgetc_eatbnl();
11946         if (c > 255 /* PEOA or PEOF */
11947          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11948         ) {
11949 #if BASH_DOLLAR_SQUOTE
11950                 if (syntax != DQSYNTAX && c == '\'')
11951                         bash_dollar_squote = 1;
11952                 else
11953 #endif
11954                         USTPUTC('$', out);
11955                 pungetc();
11956         } else if (c == '(') {
11957                 /* $(command) or $((arith)) */
11958                 if (pgetc_eatbnl() == '(') {
11959 #if ENABLE_FEATURE_SH_MATH
11960                         PARSEARITH();
11961 #else
11962                         raise_error_syntax("support for $((arith)) is disabled");
11963 #endif
11964                 } else {
11965                         pungetc();
11966                         PARSEBACKQNEW();
11967                 }
11968         } else {
11969                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11970                 USTPUTC(CTLVAR, out);
11971                 typeloc = out - (char *)stackblock();
11972                 STADJUST(1, out);
11973                 subtype = VSNORMAL;
11974                 if (c == '{') {
11975                         c = pgetc_eatbnl();
11976                         subtype = 0;
11977                 }
11978  varname:
11979                 if (is_name(c)) {
11980                         /* $[{[#]]NAME[}] */
11981                         do {
11982                                 STPUTC(c, out);
11983                                 c = pgetc_eatbnl();
11984                         } while (is_in_name(c));
11985                 } else if (isdigit(c)) {
11986                         /* $[{[#]]NUM[}] */
11987                         do {
11988                                 STPUTC(c, out);
11989                                 c = pgetc_eatbnl();
11990                         } while (isdigit(c));
11991                 } else if (is_special(c)) {
11992                         /* $[{[#]]<specialchar>[}] */
11993                         int cc = c;
11994
11995                         c = pgetc_eatbnl();
11996                         if (!subtype && cc == '#') {
11997                                 subtype = VSLENGTH;
11998                                 if (c == '_' || isalnum(c))
11999                                         goto varname;
12000                                 cc = c;
12001                                 c = pgetc_eatbnl();
12002                                 if (cc == '}' || c != '}') {
12003                                         pungetc();
12004                                         subtype = 0;
12005                                         c = cc;
12006                                         cc = '#';
12007                                 }
12008                         }
12009                         USTPUTC(cc, out);
12010                 } else {
12011                         goto badsub;
12012                 }
12013                 if (c != '}' && subtype == VSLENGTH) {
12014                         /* ${#VAR didn't end with } */
12015                         goto badsub;
12016                 }
12017
12018                 if (subtype == 0) {
12019                         static const char types[] ALIGN1 = "}-+?=";
12020                         /* ${VAR...} but not $VAR or ${#VAR} */
12021                         /* c == first char after VAR */
12022                         switch (c) {
12023                         case ':':
12024                                 c = pgetc_eatbnl();
12025 #if BASH_SUBSTR
12026                                 /* This check is only needed to not misinterpret
12027                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12028                                  * constructs.
12029                                  */
12030                                 if (!strchr(types, c)) {
12031                                         subtype = VSSUBSTR;
12032                                         pungetc();
12033                                         break; /* "goto badsub" is bigger (!) */
12034                                 }
12035 #endif
12036                                 subtype = VSNUL;
12037                                 /*FALLTHROUGH*/
12038                         default: {
12039                                 const char *p = strchr(types, c);
12040                                 if (p == NULL)
12041                                         break;
12042                                 subtype |= p - types + VSNORMAL;
12043                                 break;
12044                         }
12045                         case '%':
12046                         case '#': {
12047                                 int cc = c;
12048                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12049                                 c = pgetc_eatbnl();
12050                                 if (c != cc)
12051                                         goto badsub;
12052                                 subtype++;
12053                                 break;
12054                         }
12055 #if BASH_PATTERN_SUBST
12056                         case '/':
12057                                 /* ${v/[/]pattern/repl} */
12058 //TODO: encode pattern and repl separately.
12059 // Currently ${v/$var_with_slash/repl} is horribly broken
12060                                 subtype = VSREPLACE;
12061                                 c = pgetc_eatbnl();
12062                                 if (c != '/')
12063                                         goto badsub;
12064                                 subtype++; /* VSREPLACEALL */
12065                                 break;
12066 #endif
12067                         }
12068                 } else {
12069  badsub:
12070                         pungetc();
12071                 }
12072                 ((unsigned char *)stackblock())[typeloc] = subtype;
12073                 if (subtype != VSNORMAL) {
12074                         varnest++;
12075                         if (dblquote)
12076                                 dqvarnest++;
12077                 }
12078                 STPUTC('=', out);
12079         }
12080         goto parsesub_return;
12081 }
12082
12083 /*
12084  * Called to parse command substitutions.  Newstyle is set if the command
12085  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12086  * list of commands (passed by reference), and savelen is the number of
12087  * characters on the top of the stack which must be preserved.
12088  */
12089 parsebackq: {
12090         struct nodelist **nlpp;
12091         union node *n;
12092         char *str;
12093         size_t savelen;
12094         smallint saveprompt = 0;
12095
12096         str = NULL;
12097         savelen = out - (char *)stackblock();
12098         if (savelen > 0) {
12099                 /*
12100                  * FIXME: this can allocate very large block on stack and SEGV.
12101                  * Example:
12102                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12103                  * allocates 100kb for every command subst. With about
12104                  * a hundred command substitutions stack overflows.
12105                  * With larger prepended string, SEGV happens sooner.
12106                  */
12107                 str = alloca(savelen);
12108                 memcpy(str, stackblock(), savelen);
12109         }
12110
12111         if (oldstyle) {
12112                 /* We must read until the closing backquote, giving special
12113                  * treatment to some slashes, and then push the string and
12114                  * reread it as input, interpreting it normally.
12115                  */
12116                 char *pout;
12117                 size_t psavelen;
12118                 char *pstr;
12119
12120                 STARTSTACKSTR(pout);
12121                 for (;;) {
12122                         int pc;
12123
12124                         setprompt_if(needprompt, 2);
12125                         pc = pgetc();
12126                         switch (pc) {
12127                         case '`':
12128                                 goto done;
12129
12130                         case '\\':
12131                                 pc = pgetc();
12132                                 if (pc == '\n') {
12133                                         nlprompt();
12134                                         /*
12135                                          * If eating a newline, avoid putting
12136                                          * the newline into the new character
12137                                          * stream (via the STPUTC after the
12138                                          * switch).
12139                                          */
12140                                         continue;
12141                                 }
12142                                 if (pc != '\\' && pc != '`' && pc != '$'
12143                                  && (!dblquote || pc != '"')
12144                                 ) {
12145                                         STPUTC('\\', pout);
12146                                 }
12147                                 if (pc <= 255 /* not PEOA or PEOF */) {
12148                                         break;
12149                                 }
12150                                 /* fall through */
12151
12152                         case PEOF:
12153                         IF_ASH_ALIAS(case PEOA:)
12154                                 startlinno = g_parsefile->linno;
12155                                 raise_error_syntax("EOF in backquote substitution");
12156
12157                         case '\n':
12158                                 nlnoprompt();
12159                                 break;
12160
12161                         default:
12162                                 break;
12163                         }
12164                         STPUTC(pc, pout);
12165                 }
12166  done:
12167                 STPUTC('\0', pout);
12168                 psavelen = pout - (char *)stackblock();
12169                 if (psavelen > 0) {
12170                         pstr = grabstackstr(pout);
12171                         setinputstring(pstr);
12172                 }
12173         }
12174         nlpp = &bqlist;
12175         while (*nlpp)
12176                 nlpp = &(*nlpp)->next;
12177         *nlpp = stzalloc(sizeof(**nlpp));
12178         /* (*nlpp)->next = NULL; - stzalloc did it */
12179
12180         if (oldstyle) {
12181                 saveprompt = doprompt;
12182                 doprompt = 0;
12183         }
12184
12185         n = list(2);
12186
12187         if (oldstyle)
12188                 doprompt = saveprompt;
12189         else if (readtoken() != TRP)
12190                 raise_error_unexpected_syntax(TRP);
12191
12192         (*nlpp)->n = n;
12193         if (oldstyle) {
12194                 /*
12195                  * Start reading from old file again, ignoring any pushed back
12196                  * tokens left from the backquote parsing
12197                  */
12198                 popfile();
12199                 tokpushback = 0;
12200         }
12201         while (stackblocksize() <= savelen)
12202                 growstackblock();
12203         STARTSTACKSTR(out);
12204         if (str) {
12205                 memcpy(out, str, savelen);
12206                 STADJUST(savelen, out);
12207         }
12208         USTPUTC(CTLBACKQ, out);
12209         if (oldstyle)
12210                 goto parsebackq_oldreturn;
12211         goto parsebackq_newreturn;
12212 }
12213
12214 #if ENABLE_FEATURE_SH_MATH
12215 /*
12216  * Parse an arithmetic expansion (indicate start of one and set state)
12217  */
12218 parsearith: {
12219         if (++arinest == 1) {
12220                 prevsyntax = syntax;
12221                 syntax = ARISYNTAX;
12222         }
12223         USTPUTC(CTLARI, out);
12224         goto parsearith_return;
12225 }
12226 #endif
12227 } /* end of readtoken */
12228
12229 /*
12230  * Read the next input token.
12231  * If the token is a word, we set backquotelist to the list of cmds in
12232  *      backquotes.  We set quoteflag to true if any part of the word was
12233  *      quoted.
12234  * If the token is TREDIR, then we set redirnode to a structure containing
12235  *      the redirection.
12236  * In all cases, the variable startlinno is set to the number of the line
12237  *      on which the token starts.
12238  *
12239  * [Change comment:  here documents and internal procedures]
12240  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12241  *  word parsing code into a separate routine.  In this case, readtoken
12242  *  doesn't need to have any internal procedures, but parseword does.
12243  *  We could also make parseoperator in essence the main routine, and
12244  *  have parseword (readtoken1?) handle both words and redirection.]
12245  */
12246 #define NEW_xxreadtoken
12247 #ifdef NEW_xxreadtoken
12248 /* singles must be first! */
12249 static const char xxreadtoken_chars[7] ALIGN1 = {
12250         '\n', '(', ')', /* singles */
12251         '&', '|', ';',  /* doubles */
12252         0
12253 };
12254
12255 #define xxreadtoken_singles 3
12256 #define xxreadtoken_doubles 3
12257
12258 static const char xxreadtoken_tokens[] ALIGN1 = {
12259         TNL, TLP, TRP,          /* only single occurrence allowed */
12260         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12261         TEOF,                   /* corresponds to trailing nul */
12262         TAND, TOR, TENDCASE     /* if double occurrence */
12263 };
12264
12265 static int
12266 xxreadtoken(void)
12267 {
12268         int c;
12269
12270         if (tokpushback) {
12271                 tokpushback = 0;
12272                 return lasttoken;
12273         }
12274         setprompt_if(needprompt, 2);
12275         startlinno = g_parsefile->linno;
12276         for (;;) {                      /* until token or start of word found */
12277                 c = pgetc();
12278                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12279                         continue;
12280
12281                 if (c == '#') {
12282                         while ((c = pgetc()) != '\n' && c != PEOF)
12283                                 continue;
12284                         pungetc();
12285                 } else if (c == '\\') {
12286                         if (pgetc() != '\n') {
12287                                 pungetc();
12288                                 break; /* return readtoken1(...) */
12289                         }
12290                         nlprompt();
12291                 } else {
12292                         const char *p;
12293
12294                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12295                         if (c != PEOF) {
12296                                 if (c == '\n') {
12297                                         nlnoprompt();
12298                                 }
12299
12300                                 p = strchr(xxreadtoken_chars, c);
12301                                 if (p == NULL)
12302                                         break; /* return readtoken1(...) */
12303
12304                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12305                                         int cc = pgetc();
12306                                         if (cc == c) {    /* double occurrence? */
12307                                                 p += xxreadtoken_doubles + 1;
12308                                         } else {
12309                                                 pungetc();
12310 #if BASH_REDIR_OUTPUT
12311                                                 if (c == '&' && cc == '>') /* &> */
12312                                                         break; /* return readtoken1(...) */
12313 #endif
12314                                         }
12315                                 }
12316                         }
12317                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12318                         return lasttoken;
12319                 }
12320         } /* for (;;) */
12321
12322         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12323 }
12324 #else /* old xxreadtoken */
12325 #define RETURN(token)   return lasttoken = token
12326 static int
12327 xxreadtoken(void)
12328 {
12329         int c;
12330
12331         if (tokpushback) {
12332                 tokpushback = 0;
12333                 return lasttoken;
12334         }
12335         setprompt_if(needprompt, 2);
12336         startlinno = g_parsefile->linno;
12337         for (;;) {      /* until token or start of word found */
12338                 c = pgetc();
12339                 switch (c) {
12340                 case ' ': case '\t':
12341                 IF_ASH_ALIAS(case PEOA:)
12342                         continue;
12343                 case '#':
12344                         while ((c = pgetc()) != '\n' && c != PEOF)
12345                                 continue;
12346                         pungetc();
12347                         continue;
12348                 case '\\':
12349                         if (pgetc() == '\n') {
12350                                 nlprompt();
12351                                 continue;
12352                         }
12353                         pungetc();
12354                         goto breakloop;
12355                 case '\n':
12356                         nlnoprompt();
12357                         RETURN(TNL);
12358                 case PEOF:
12359                         RETURN(TEOF);
12360                 case '&':
12361                         if (pgetc() == '&')
12362                                 RETURN(TAND);
12363                         pungetc();
12364                         RETURN(TBACKGND);
12365                 case '|':
12366                         if (pgetc() == '|')
12367                                 RETURN(TOR);
12368                         pungetc();
12369                         RETURN(TPIPE);
12370                 case ';':
12371                         if (pgetc() == ';')
12372                                 RETURN(TENDCASE);
12373                         pungetc();
12374                         RETURN(TSEMI);
12375                 case '(':
12376                         RETURN(TLP);
12377                 case ')':
12378                         RETURN(TRP);
12379                 default:
12380                         goto breakloop;
12381                 }
12382         }
12383  breakloop:
12384         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12385 #undef RETURN
12386 }
12387 #endif /* old xxreadtoken */
12388
12389 static int
12390 readtoken(void)
12391 {
12392         int t;
12393         int kwd = checkkwd;
12394 #if DEBUG
12395         smallint alreadyseen = tokpushback;
12396 #endif
12397
12398 #if ENABLE_ASH_ALIAS
12399  top:
12400 #endif
12401
12402         t = xxreadtoken();
12403
12404         /*
12405          * eat newlines
12406          */
12407         if (kwd & CHKNL) {
12408                 while (t == TNL) {
12409                         parseheredoc();
12410                         t = xxreadtoken();
12411                 }
12412         }
12413
12414         if (t != TWORD || quoteflag) {
12415                 goto out;
12416         }
12417
12418         /*
12419          * check for keywords
12420          */
12421         if (kwd & CHKKWD) {
12422                 const char *const *pp;
12423
12424                 pp = findkwd(wordtext);
12425                 if (pp) {
12426                         lasttoken = t = pp - tokname_array;
12427                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12428                         goto out;
12429                 }
12430         }
12431
12432         if (checkkwd & CHKALIAS) {
12433 #if ENABLE_ASH_ALIAS
12434                 struct alias *ap;
12435                 ap = lookupalias(wordtext, 1);
12436                 if (ap != NULL) {
12437                         if (*ap->val) {
12438                                 pushstring(ap->val, ap);
12439                         }
12440                         goto top;
12441                 }
12442 #endif
12443         }
12444  out:
12445         checkkwd = 0;
12446 #if DEBUG
12447         if (!alreadyseen)
12448                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12449         else
12450                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12451 #endif
12452         return t;
12453 }
12454
12455 static int
12456 peektoken(void)
12457 {
12458         int t;
12459
12460         t = readtoken();
12461         tokpushback = 1;
12462         return t;
12463 }
12464
12465 /*
12466  * Read and parse a command.  Returns NODE_EOF on end of file.
12467  * (NULL is a valid parse tree indicating a blank line.)
12468  */
12469 static union node *
12470 parsecmd(int interact)
12471 {
12472         tokpushback = 0;
12473         checkkwd = 0;
12474         heredoclist = 0;
12475         doprompt = interact;
12476         setprompt_if(doprompt, doprompt);
12477         needprompt = 0;
12478         return list(1);
12479 }
12480
12481 /*
12482  * Input any here documents.
12483  */
12484 static void
12485 parseheredoc(void)
12486 {
12487         struct heredoc *here;
12488         union node *n;
12489
12490         here = heredoclist;
12491         heredoclist = NULL;
12492
12493         while (here) {
12494                 setprompt_if(needprompt, 2);
12495                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12496                                 here->eofmark, here->striptabs);
12497                 n = stzalloc(sizeof(struct narg));
12498                 n->narg.type = NARG;
12499                 /*n->narg.next = NULL; - stzalloc did it */
12500                 n->narg.text = wordtext;
12501                 n->narg.backquote = backquotelist;
12502                 here->here->nhere.doc = n;
12503                 here = here->next;
12504         }
12505 }
12506
12507
12508 /*
12509  * called by editline -- any expansions to the prompt should be added here.
12510  */
12511 static const char *
12512 expandstr(const char *ps)
12513 {
12514         union node n;
12515         int saveprompt;
12516
12517         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12518          * and token processing _can_ alter it (delete NULs etc). */
12519         setinputstring((char *)ps);
12520
12521         saveprompt = doprompt;
12522         doprompt = 0;
12523         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12524         doprompt = saveprompt;
12525
12526         popfile();
12527
12528         n.narg.type = NARG;
12529         n.narg.next = NULL;
12530         n.narg.text = wordtext;
12531         n.narg.backquote = backquotelist;
12532
12533         expandarg(&n, NULL, EXP_QUOTED);
12534         return stackblock();
12535 }
12536
12537 static inline int
12538 parser_eof(void)
12539 {
12540         return tokpushback && lasttoken == TEOF;
12541 }
12542
12543 /*
12544  * Execute a command or commands contained in a string.
12545  */
12546 static int
12547 evalstring(char *s, int flags)
12548 {
12549         struct jmploc *volatile savehandler;
12550         struct jmploc jmploc;
12551         int ex;
12552
12553         union node *n;
12554         struct stackmark smark;
12555         int status;
12556
12557         s = sstrdup(s);
12558         setinputstring(s);
12559         setstackmark(&smark);
12560
12561         status = 0;
12562         /* On exception inside execution loop, we must popfile().
12563          * Try interactively:
12564          *      readonly a=a
12565          *      command eval "a=b"  # throws "is read only" error
12566          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12567          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12568          */
12569         savehandler = exception_handler;
12570         ex = setjmp(jmploc.loc);
12571         if (ex)
12572                 goto out;
12573         exception_handler = &jmploc;
12574
12575         while ((n = parsecmd(0)) != NODE_EOF) {
12576                 int i;
12577
12578                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12579                 if (n)
12580                         status = i;
12581                 popstackmark(&smark);
12582                 if (evalskip)
12583                         break;
12584         }
12585  out:
12586         popstackmark(&smark);
12587         popfile();
12588         stunalloc(s);
12589
12590         exception_handler = savehandler;
12591         if (ex)
12592                 longjmp(exception_handler->loc, ex);
12593
12594         return status;
12595 }
12596
12597 /*
12598  * The eval command.
12599  */
12600 static int FAST_FUNC
12601 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12602 {
12603         char *p;
12604         char *concat;
12605
12606         if (argv[1]) {
12607                 p = argv[1];
12608                 argv += 2;
12609                 if (argv[0]) {
12610                         STARTSTACKSTR(concat);
12611                         for (;;) {
12612                                 concat = stack_putstr(p, concat);
12613                                 p = *argv++;
12614                                 if (p == NULL)
12615                                         break;
12616                                 STPUTC(' ', concat);
12617                         }
12618                         STPUTC('\0', concat);
12619                         p = grabstackstr(concat);
12620                 }
12621                 return evalstring(p, flags & EV_TESTED);
12622         }
12623         return 0;
12624 }
12625
12626 /*
12627  * Read and execute commands.
12628  * "Top" is nonzero for the top level command loop;
12629  * it turns on prompting if the shell is interactive.
12630  */
12631 static int
12632 cmdloop(int top)
12633 {
12634         union node *n;
12635         struct stackmark smark;
12636         int inter;
12637         int status = 0;
12638         int numeof = 0;
12639
12640         TRACE(("cmdloop(%d) called\n", top));
12641         for (;;) {
12642                 int skip;
12643
12644                 setstackmark(&smark);
12645 #if JOBS
12646                 if (doing_jobctl)
12647                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12648 #endif
12649                 inter = 0;
12650                 if (iflag && top) {
12651                         inter++;
12652                         chkmail();
12653                 }
12654                 n = parsecmd(inter);
12655 #if DEBUG
12656                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12657                         showtree(n);
12658 #endif
12659                 if (n == NODE_EOF) {
12660                         if (!top || numeof >= 50)
12661                                 break;
12662                         if (!stoppedjobs()) {
12663                                 if (!Iflag)
12664                                         break;
12665                                 out2str("\nUse \"exit\" to leave shell.\n");
12666                         }
12667                         numeof++;
12668                 } else if (nflag == 0) {
12669                         int i;
12670
12671                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12672                         job_warning >>= 1;
12673                         numeof = 0;
12674                         i = evaltree(n, 0);
12675                         if (n)
12676                                 status = i;
12677                 }
12678                 popstackmark(&smark);
12679                 skip = evalskip;
12680
12681                 if (skip) {
12682                         evalskip &= ~SKIPFUNC;
12683                         break;
12684                 }
12685         }
12686         return status;
12687 }
12688
12689 /*
12690  * Take commands from a file.  To be compatible we should do a path
12691  * search for the file, which is necessary to find sub-commands.
12692  */
12693 static char *
12694 find_dot_file(char *name)
12695 {
12696         char *fullname;
12697         const char *path = pathval();
12698         struct stat statb;
12699
12700         /* don't try this for absolute or relative paths */
12701         if (strchr(name, '/'))
12702                 return name;
12703
12704         while ((fullname = path_advance(&path, name)) != NULL) {
12705                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12706                         /*
12707                          * Don't bother freeing here, since it will
12708                          * be freed by the caller.
12709                          */
12710                         return fullname;
12711                 }
12712                 if (fullname != name)
12713                         stunalloc(fullname);
12714         }
12715
12716         /* not found in the PATH */
12717         ash_msg_and_raise_error("%s: not found", name);
12718         /* NOTREACHED */
12719 }
12720
12721 static int FAST_FUNC
12722 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12723 {
12724         /* "false; . empty_file; echo $?" should print 0, not 1: */
12725         int status = 0;
12726         char *fullname;
12727         char **argv;
12728         char *args_need_save;
12729         volatile struct shparam saveparam;
12730
12731 //???
12732 //      struct strlist *sp;
12733 //      for (sp = cmdenviron; sp; sp = sp->next)
12734 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12735
12736         nextopt(nullstr); /* handle possible "--" */
12737         argv = argptr;
12738
12739         if (!argv[0]) {
12740                 /* bash says: "bash: .: filename argument required" */
12741                 return 2; /* bash compat */
12742         }
12743
12744         /* This aborts if file isn't found, which is POSIXly correct.
12745          * bash returns exitcode 1 instead.
12746          */
12747         fullname = find_dot_file(argv[0]);
12748         argv++;
12749         args_need_save = argv[0];
12750         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12751                 int argc;
12752                 saveparam = shellparam;
12753                 shellparam.malloced = 0;
12754                 argc = 1;
12755                 while (argv[argc])
12756                         argc++;
12757                 shellparam.nparam = argc;
12758                 shellparam.p = argv;
12759         };
12760
12761         /* This aborts if file can't be opened, which is POSIXly correct.
12762          * bash returns exitcode 1 instead.
12763          */
12764         setinputfile(fullname, INPUT_PUSH_FILE);
12765         commandname = fullname;
12766         status = cmdloop(0);
12767         popfile();
12768
12769         if (args_need_save) {
12770                 freeparam(&shellparam);
12771                 shellparam = saveparam;
12772         };
12773
12774         return status;
12775 }
12776
12777 static int FAST_FUNC
12778 exitcmd(int argc UNUSED_PARAM, char **argv)
12779 {
12780         if (stoppedjobs())
12781                 return 0;
12782         if (argv[1])
12783                 exitstatus = number(argv[1]);
12784         raise_exception(EXEXIT);
12785         /* NOTREACHED */
12786 }
12787
12788 /*
12789  * Read a file containing shell functions.
12790  */
12791 static void
12792 readcmdfile(char *name)
12793 {
12794         setinputfile(name, INPUT_PUSH_FILE);
12795         cmdloop(0);
12796         popfile();
12797 }
12798
12799
12800 /* ============ find_command inplementation */
12801
12802 /*
12803  * Resolve a command name.  If you change this routine, you may have to
12804  * change the shellexec routine as well.
12805  */
12806 static void
12807 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12808 {
12809         struct tblentry *cmdp;
12810         int idx;
12811         int prev;
12812         char *fullname;
12813         struct stat statb;
12814         int e;
12815         int updatetbl;
12816         struct builtincmd *bcmd;
12817
12818         /* If name contains a slash, don't use PATH or hash table */
12819         if (strchr(name, '/') != NULL) {
12820                 entry->u.index = -1;
12821                 if (act & DO_ABS) {
12822                         while (stat(name, &statb) < 0) {
12823 #ifdef SYSV
12824                                 if (errno == EINTR)
12825                                         continue;
12826 #endif
12827                                 entry->cmdtype = CMDUNKNOWN;
12828                                 return;
12829                         }
12830                 }
12831                 entry->cmdtype = CMDNORMAL;
12832                 return;
12833         }
12834
12835 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12836
12837         updatetbl = (path == pathval());
12838         if (!updatetbl) {
12839                 act |= DO_ALTPATH;
12840                 if (strstr(path, "%builtin") != NULL)
12841                         act |= DO_ALTBLTIN;
12842         }
12843
12844         /* If name is in the table, check answer will be ok */
12845         cmdp = cmdlookup(name, 0);
12846         if (cmdp != NULL) {
12847                 int bit;
12848
12849                 switch (cmdp->cmdtype) {
12850                 default:
12851 #if DEBUG
12852                         abort();
12853 #endif
12854                 case CMDNORMAL:
12855                         bit = DO_ALTPATH;
12856                         break;
12857                 case CMDFUNCTION:
12858                         bit = DO_NOFUNC;
12859                         break;
12860                 case CMDBUILTIN:
12861                         bit = DO_ALTBLTIN;
12862                         break;
12863                 }
12864                 if (act & bit) {
12865                         updatetbl = 0;
12866                         cmdp = NULL;
12867                 } else if (cmdp->rehash == 0)
12868                         /* if not invalidated by cd, we're done */
12869                         goto success;
12870         }
12871
12872         /* If %builtin not in path, check for builtin next */
12873         bcmd = find_builtin(name);
12874         if (bcmd) {
12875                 if (IS_BUILTIN_REGULAR(bcmd))
12876                         goto builtin_success;
12877                 if (act & DO_ALTPATH) {
12878                         if (!(act & DO_ALTBLTIN))
12879                                 goto builtin_success;
12880                 } else if (builtinloc <= 0) {
12881                         goto builtin_success;
12882                 }
12883         }
12884
12885 #if ENABLE_FEATURE_SH_STANDALONE
12886         {
12887                 int applet_no = find_applet_by_name(name);
12888                 if (applet_no >= 0) {
12889                         entry->cmdtype = CMDNORMAL;
12890                         entry->u.index = -2 - applet_no;
12891                         return;
12892                 }
12893         }
12894 #endif
12895
12896         /* We have to search path. */
12897         prev = -1;              /* where to start */
12898         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12899                 if (cmdp->cmdtype == CMDBUILTIN)
12900                         prev = builtinloc;
12901                 else
12902                         prev = cmdp->param.index;
12903         }
12904
12905         e = ENOENT;
12906         idx = -1;
12907  loop:
12908         while ((fullname = path_advance(&path, name)) != NULL) {
12909                 stunalloc(fullname);
12910                 /* NB: code below will still use fullname
12911                  * despite it being "unallocated" */
12912                 idx++;
12913                 if (pathopt) {
12914                         if (prefix(pathopt, "builtin")) {
12915                                 if (bcmd)
12916                                         goto builtin_success;
12917                                 continue;
12918                         }
12919                         if ((act & DO_NOFUNC)
12920                          || !prefix(pathopt, "func")
12921                         ) {     /* ignore unimplemented options */
12922                                 continue;
12923                         }
12924                 }
12925                 /* if rehash, don't redo absolute path names */
12926                 if (fullname[0] == '/' && idx <= prev) {
12927                         if (idx < prev)
12928                                 continue;
12929                         TRACE(("searchexec \"%s\": no change\n", name));
12930                         goto success;
12931                 }
12932                 while (stat(fullname, &statb) < 0) {
12933 #ifdef SYSV
12934                         if (errno == EINTR)
12935                                 continue;
12936 #endif
12937                         if (errno != ENOENT && errno != ENOTDIR)
12938                                 e = errno;
12939                         goto loop;
12940                 }
12941                 e = EACCES;     /* if we fail, this will be the error */
12942                 if (!S_ISREG(statb.st_mode))
12943                         continue;
12944                 if (pathopt) {          /* this is a %func directory */
12945                         stalloc(strlen(fullname) + 1);
12946                         /* NB: stalloc will return space pointed by fullname
12947                          * (because we don't have any intervening allocations
12948                          * between stunalloc above and this stalloc) */
12949                         readcmdfile(fullname);
12950                         cmdp = cmdlookup(name, 0);
12951                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12952                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12953                         stunalloc(fullname);
12954                         goto success;
12955                 }
12956                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12957                 if (!updatetbl) {
12958                         entry->cmdtype = CMDNORMAL;
12959                         entry->u.index = idx;
12960                         return;
12961                 }
12962                 INT_OFF;
12963                 cmdp = cmdlookup(name, 1);
12964                 cmdp->cmdtype = CMDNORMAL;
12965                 cmdp->param.index = idx;
12966                 INT_ON;
12967                 goto success;
12968         }
12969
12970         /* We failed.  If there was an entry for this command, delete it */
12971         if (cmdp && updatetbl)
12972                 delete_cmd_entry();
12973         if (act & DO_ERR)
12974                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12975         entry->cmdtype = CMDUNKNOWN;
12976         return;
12977
12978  builtin_success:
12979         if (!updatetbl) {
12980                 entry->cmdtype = CMDBUILTIN;
12981                 entry->u.cmd = bcmd;
12982                 return;
12983         }
12984         INT_OFF;
12985         cmdp = cmdlookup(name, 1);
12986         cmdp->cmdtype = CMDBUILTIN;
12987         cmdp->param.cmd = bcmd;
12988         INT_ON;
12989  success:
12990         cmdp->rehash = 0;
12991         entry->cmdtype = cmdp->cmdtype;
12992         entry->u = cmdp->param;
12993 }
12994
12995
12996 /*
12997  * The trap builtin.
12998  */
12999 static int FAST_FUNC
13000 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13001 {
13002         char *action;
13003         char **ap;
13004         int signo, exitcode;
13005
13006         nextopt(nullstr);
13007         ap = argptr;
13008         if (!*ap) {
13009                 for (signo = 0; signo < NSIG; signo++) {
13010                         char *tr = trap_ptr[signo];
13011                         if (tr) {
13012                                 /* note: bash adds "SIG", but only if invoked
13013                                  * as "bash". If called as "sh", or if set -o posix,
13014                                  * then it prints short signal names.
13015                                  * We are printing short names: */
13016                                 out1fmt("trap -- %s %s\n",
13017                                                 single_quote(tr),
13018                                                 get_signame(signo));
13019                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13020                  * In this case, we will exit very soon, no need to free(). */
13021                                 /* if (trap_ptr != trap && tp[0]) */
13022                                 /*      free(tr); */
13023                         }
13024                 }
13025                 /*
13026                 if (trap_ptr != trap) {
13027                         free(trap_ptr);
13028                         trap_ptr = trap;
13029                 }
13030                 */
13031                 return 0;
13032         }
13033
13034         /* Why the second check?
13035          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13036          * In this case, NUM is signal no, not an action.
13037          */
13038         action = NULL;
13039         if (ap[1] && !is_number(ap[0]))
13040                 action = *ap++;
13041
13042         exitcode = 0;
13043         while (*ap) {
13044                 signo = get_signum(*ap);
13045                 if (signo < 0) {
13046                         /* Mimic bash message exactly */
13047                         ash_msg("%s: invalid signal specification", *ap);
13048                         exitcode = 1;
13049                         goto next;
13050                 }
13051                 INT_OFF;
13052                 if (action) {
13053                         if (LONE_DASH(action))
13054                                 action = NULL;
13055                         else {
13056                                 if (action[0]) /* not NULL and not "" and not "-" */
13057                                         may_have_traps = 1;
13058                                 action = ckstrdup(action);
13059                         }
13060                 }
13061                 free(trap[signo]);
13062                 trap[signo] = action;
13063                 if (signo != 0)
13064                         setsignal(signo);
13065                 INT_ON;
13066  next:
13067                 ap++;
13068         }
13069         return exitcode;
13070 }
13071
13072
13073 /* ============ Builtins */
13074
13075 #if ENABLE_ASH_HELP
13076 static int FAST_FUNC
13077 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13078 {
13079         unsigned col;
13080         unsigned i;
13081
13082         out1fmt(
13083                 "Built-in commands:\n"
13084                 "------------------\n");
13085         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13086                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13087                                         builtintab[i].name + 1);
13088                 if (col > 60) {
13089                         out1fmt("\n");
13090                         col = 0;
13091                 }
13092         }
13093 # if ENABLE_FEATURE_SH_STANDALONE
13094         {
13095                 const char *a = applet_names;
13096                 while (*a) {
13097                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13098                         if (col > 60) {
13099                                 out1fmt("\n");
13100                                 col = 0;
13101                         }
13102                         while (*a++ != '\0')
13103                                 continue;
13104                 }
13105         }
13106 # endif
13107         newline_and_flush(stdout);
13108         return EXIT_SUCCESS;
13109 }
13110 #endif
13111
13112 #if MAX_HISTORY
13113 static int FAST_FUNC
13114 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13115 {
13116         show_history(line_input_state);
13117         return EXIT_SUCCESS;
13118 }
13119 #endif
13120
13121 /*
13122  * The export and readonly commands.
13123  */
13124 static int FAST_FUNC
13125 exportcmd(int argc UNUSED_PARAM, char **argv)
13126 {
13127         struct var *vp;
13128         char *name;
13129         const char *p;
13130         char **aptr;
13131         char opt;
13132         int flag;
13133         int flag_off;
13134
13135         /* "readonly" in bash accepts, but ignores -n.
13136          * We do the same: it saves a conditional in nextopt's param.
13137          */
13138         flag_off = 0;
13139         while ((opt = nextopt("np")) != '\0') {
13140                 if (opt == 'n')
13141                         flag_off = VEXPORT;
13142         }
13143         flag = VEXPORT;
13144         if (argv[0][0] == 'r') {
13145                 flag = VREADONLY;
13146                 flag_off = 0; /* readonly ignores -n */
13147         }
13148         flag_off = ~flag_off;
13149
13150         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13151         {
13152                 aptr = argptr;
13153                 name = *aptr;
13154                 if (name) {
13155                         do {
13156                                 p = strchr(name, '=');
13157                                 if (p != NULL) {
13158                                         p++;
13159                                 } else {
13160                                         vp = *findvar(hashvar(name), name);
13161                                         if (vp) {
13162                                                 vp->flags = ((vp->flags | flag) & flag_off);
13163                                                 continue;
13164                                         }
13165                                 }
13166                                 setvar(name, p, (flag & flag_off));
13167                         } while ((name = *++aptr) != NULL);
13168                         return 0;
13169                 }
13170         }
13171
13172         /* No arguments. Show the list of exported or readonly vars.
13173          * -n is ignored.
13174          */
13175         showvars(argv[0], flag, 0);
13176         return 0;
13177 }
13178
13179 /*
13180  * Delete a function if it exists.
13181  */
13182 static void
13183 unsetfunc(const char *name)
13184 {
13185         struct tblentry *cmdp;
13186
13187         cmdp = cmdlookup(name, 0);
13188         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13189                 delete_cmd_entry();
13190 }
13191
13192 /*
13193  * The unset builtin command.  We unset the function before we unset the
13194  * variable to allow a function to be unset when there is a readonly variable
13195  * with the same name.
13196  */
13197 static int FAST_FUNC
13198 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13199 {
13200         char **ap;
13201         int i;
13202         int flag = 0;
13203
13204         while ((i = nextopt("vf")) != 0) {
13205                 flag = i;
13206         }
13207
13208         for (ap = argptr; *ap; ap++) {
13209                 if (flag != 'f') {
13210                         unsetvar(*ap);
13211                         continue;
13212                 }
13213                 if (flag != 'v')
13214                         unsetfunc(*ap);
13215         }
13216         return 0;
13217 }
13218
13219 static const unsigned char timescmd_str[] ALIGN1 = {
13220         ' ',  offsetof(struct tms, tms_utime),
13221         '\n', offsetof(struct tms, tms_stime),
13222         ' ',  offsetof(struct tms, tms_cutime),
13223         '\n', offsetof(struct tms, tms_cstime),
13224         0
13225 };
13226 static int FAST_FUNC
13227 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13228 {
13229         unsigned long clk_tck, s, t;
13230         const unsigned char *p;
13231         struct tms buf;
13232
13233         clk_tck = bb_clk_tck();
13234         times(&buf);
13235
13236         p = timescmd_str;
13237         do {
13238                 t = *(clock_t *)(((char *) &buf) + p[1]);
13239                 s = t / clk_tck;
13240                 t = t % clk_tck;
13241                 out1fmt("%lum%lu.%03lus%c",
13242                         s / 60, s % 60,
13243                         (t * 1000) / clk_tck,
13244                         p[0]);
13245                 p += 2;
13246         } while (*p);
13247
13248         return 0;
13249 }
13250
13251 #if ENABLE_FEATURE_SH_MATH
13252 /*
13253  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13254  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13255  *
13256  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13257  */
13258 static int FAST_FUNC
13259 letcmd(int argc UNUSED_PARAM, char **argv)
13260 {
13261         arith_t i;
13262
13263         argv++;
13264         if (!*argv)
13265                 ash_msg_and_raise_error("expression expected");
13266         do {
13267                 i = ash_arith(*argv);
13268         } while (*++argv);
13269
13270         return !i;
13271 }
13272 #endif
13273
13274 /*
13275  * The read builtin. Options:
13276  *      -r              Do not interpret '\' specially
13277  *      -s              Turn off echo (tty only)
13278  *      -n NCHARS       Read NCHARS max
13279  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13280  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13281  *      -u FD           Read from given FD instead of fd 0
13282  * This uses unbuffered input, which may be avoidable in some cases.
13283  * TODO: bash also has:
13284  *      -a ARRAY        Read into array[0],[1],etc
13285  *      -d DELIM        End on DELIM char, not newline
13286  *      -e              Use line editing (tty only)
13287  */
13288 static int FAST_FUNC
13289 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13290 {
13291         char *opt_n = NULL;
13292         char *opt_p = NULL;
13293         char *opt_t = NULL;
13294         char *opt_u = NULL;
13295         int read_flags = 0;
13296         const char *r;
13297         int i;
13298
13299         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13300                 switch (i) {
13301                 case 'p':
13302                         opt_p = optionarg;
13303                         break;
13304                 case 'n':
13305                         opt_n = optionarg;
13306                         break;
13307                 case 's':
13308                         read_flags |= BUILTIN_READ_SILENT;
13309                         break;
13310                 case 't':
13311                         opt_t = optionarg;
13312                         break;
13313                 case 'r':
13314                         read_flags |= BUILTIN_READ_RAW;
13315                         break;
13316                 case 'u':
13317                         opt_u = optionarg;
13318                         break;
13319                 default:
13320                         break;
13321                 }
13322         }
13323
13324         /* "read -s" needs to save/restore termios, can't allow ^C
13325          * to jump out of it.
13326          */
13327  again:
13328         INT_OFF;
13329         r = shell_builtin_read(setvar0,
13330                 argptr,
13331                 bltinlookup("IFS"), /* can be NULL */
13332                 read_flags,
13333                 opt_n,
13334                 opt_p,
13335                 opt_t,
13336                 opt_u
13337         );
13338         INT_ON;
13339
13340         if ((uintptr_t)r == 1 && errno == EINTR) {
13341                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13342                 if (pending_sig == 0)
13343                         goto again;
13344         }
13345
13346         if ((uintptr_t)r > 1)
13347                 ash_msg_and_raise_error(r);
13348
13349         return (uintptr_t)r;
13350 }
13351
13352 static int FAST_FUNC
13353 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13354 {
13355         static const char permuser[3] ALIGN1 = "ogu";
13356
13357         mode_t mask;
13358         int symbolic_mode = 0;
13359
13360         while (nextopt("S") != '\0') {
13361                 symbolic_mode = 1;
13362         }
13363
13364         INT_OFF;
13365         mask = umask(0);
13366         umask(mask);
13367         INT_ON;
13368
13369         if (*argptr == NULL) {
13370                 if (symbolic_mode) {
13371                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13372                         char *p = buf;
13373                         int i;
13374
13375                         i = 2;
13376                         for (;;) {
13377                                 *p++ = ',';
13378                                 *p++ = permuser[i];
13379                                 *p++ = '=';
13380                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13381                                 if (!(mask & 0400)) *p++ = 'r';
13382                                 if (!(mask & 0200)) *p++ = 'w';
13383                                 if (!(mask & 0100)) *p++ = 'x';
13384                                 mask <<= 3;
13385                                 if (--i < 0)
13386                                         break;
13387                         }
13388                         *p = '\0';
13389                         puts(buf + 1);
13390                 } else {
13391                         out1fmt("%04o\n", mask);
13392                 }
13393         } else {
13394                 char *modestr = *argptr;
13395                 /* numeric umasks are taken as-is */
13396                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13397                 if (!isdigit(modestr[0]))
13398                         mask ^= 0777;
13399                 mask = bb_parse_mode(modestr, mask);
13400                 if ((unsigned)mask > 0777) {
13401                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13402                 }
13403                 if (!isdigit(modestr[0]))
13404                         mask ^= 0777;
13405                 umask(mask);
13406         }
13407         return 0;
13408 }
13409
13410 static int FAST_FUNC
13411 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13412 {
13413         return shell_builtin_ulimit(argv);
13414 }
13415
13416 /* ============ main() and helpers */
13417
13418 /*
13419  * Called to exit the shell.
13420  */
13421 static void
13422 exitshell(void)
13423 {
13424         struct jmploc loc;
13425         char *p;
13426         int status;
13427
13428 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13429         save_history(line_input_state);
13430 #endif
13431         status = exitstatus;
13432         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13433         if (setjmp(loc.loc)) {
13434                 if (exception_type == EXEXIT)
13435                         status = exitstatus;
13436                 goto out;
13437         }
13438         exception_handler = &loc;
13439         p = trap[0];
13440         if (p) {
13441                 trap[0] = NULL;
13442                 evalskip = 0;
13443                 evalstring(p, 0);
13444                 /*free(p); - we'll exit soon */
13445         }
13446  out:
13447         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13448          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13449          */
13450         setjobctl(0);
13451         flush_stdout_stderr();
13452         _exit(status);
13453         /* NOTREACHED */
13454 }
13455
13456 static void
13457 init(void)
13458 {
13459         /* we will never free this */
13460         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13461
13462         sigmode[SIGCHLD - 1] = S_DFL;
13463         setsignal(SIGCHLD);
13464
13465         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13466          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13467          */
13468         signal(SIGHUP, SIG_DFL);
13469
13470         {
13471                 char **envp;
13472                 const char *p;
13473                 struct stat st1, st2;
13474
13475                 initvar();
13476                 for (envp = environ; envp && *envp; envp++) {
13477                         p = endofname(*envp);
13478                         if (p != *envp && *p == '=') {
13479                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13480                         }
13481                 }
13482
13483                 setvareq((char*)defoptindvar, VTEXTFIXED);
13484
13485                 setvar0("PPID", utoa(getppid()));
13486 #if BASH_SHLVL_VAR
13487                 p = lookupvar("SHLVL");
13488                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13489 #endif
13490 #if BASH_HOSTNAME_VAR
13491                 if (!lookupvar("HOSTNAME")) {
13492                         struct utsname uts;
13493                         uname(&uts);
13494                         setvar0("HOSTNAME", uts.nodename);
13495                 }
13496 #endif
13497                 p = lookupvar("PWD");
13498                 if (p) {
13499                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13500                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13501                         ) {
13502                                 p = NULL;
13503                         }
13504                 }
13505                 setpwd(p, 0);
13506         }
13507 }
13508
13509
13510 //usage:#define ash_trivial_usage
13511 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13512 //usage:#define ash_full_usage "\n\n"
13513 //usage:        "Unix shell interpreter"
13514
13515 /*
13516  * Process the shell command line arguments.
13517  */
13518 static void
13519 procargs(char **argv)
13520 {
13521         int i;
13522         const char *xminusc;
13523         char **xargv;
13524
13525         xargv = argv;
13526         arg0 = xargv[0];
13527         /* if (xargv[0]) - mmm, this is always true! */
13528                 xargv++;
13529         for (i = 0; i < NOPTS; i++)
13530                 optlist[i] = 2;
13531         argptr = xargv;
13532         if (options(/*cmdline:*/ 1)) {
13533                 /* it already printed err message */
13534                 raise_exception(EXERROR);
13535         }
13536         xargv = argptr;
13537         xminusc = minusc;
13538         if (*xargv == NULL) {
13539                 if (xminusc)
13540                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13541                 sflag = 1;
13542         }
13543         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13544                 iflag = 1;
13545         if (mflag == 2)
13546                 mflag = iflag;
13547         for (i = 0; i < NOPTS; i++)
13548                 if (optlist[i] == 2)
13549                         optlist[i] = 0;
13550 #if DEBUG == 2
13551         debug = 1;
13552 #endif
13553         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13554         if (xminusc) {
13555                 minusc = *xargv++;
13556                 if (*xargv)
13557                         goto setarg0;
13558         } else if (!sflag) {
13559                 setinputfile(*xargv, 0);
13560  setarg0:
13561                 arg0 = *xargv++;
13562                 commandname = arg0;
13563         }
13564
13565         shellparam.p = xargv;
13566 #if ENABLE_ASH_GETOPTS
13567         shellparam.optind = 1;
13568         shellparam.optoff = -1;
13569 #endif
13570         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13571         while (*xargv) {
13572                 shellparam.nparam++;
13573                 xargv++;
13574         }
13575         optschanged();
13576 }
13577
13578 /*
13579  * Read /etc/profile, ~/.profile, $ENV.
13580  */
13581 static void
13582 read_profile(const char *name)
13583 {
13584         name = expandstr(name);
13585         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13586                 return;
13587         cmdloop(0);
13588         popfile();
13589 }
13590
13591 /*
13592  * This routine is called when an error or an interrupt occurs in an
13593  * interactive shell and control is returned to the main command loop.
13594  * (In dash, this function is auto-generated by build machinery).
13595  */
13596 static void
13597 reset(void)
13598 {
13599         /* from eval.c: */
13600         evalskip = 0;
13601         loopnest = 0;
13602
13603         /* from expand.c: */
13604         ifsfree();
13605
13606         /* from input.c: */
13607         g_parsefile->left_in_buffer = 0;
13608         g_parsefile->left_in_line = 0;      /* clear input buffer */
13609         popallfiles();
13610
13611         /* from redir.c: */
13612         while (redirlist)
13613                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13614
13615         /* from var.c: */
13616         unwindlocalvars(NULL);
13617 }
13618
13619 #if PROFILE
13620 static short profile_buf[16384];
13621 extern int etext();
13622 #endif
13623
13624 /*
13625  * Main routine.  We initialize things, parse the arguments, execute
13626  * profiles if we're a login shell, and then call cmdloop to execute
13627  * commands.  The setjmp call sets up the location to jump to when an
13628  * exception occurs.  When an exception occurs the variable "state"
13629  * is used to figure out how far we had gotten.
13630  */
13631 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13632 int ash_main(int argc UNUSED_PARAM, char **argv)
13633 {
13634         volatile smallint state;
13635         struct jmploc jmploc;
13636         struct stackmark smark;
13637
13638         /* Initialize global data */
13639         INIT_G_misc();
13640         INIT_G_memstack();
13641         INIT_G_var();
13642 #if ENABLE_ASH_ALIAS
13643         INIT_G_alias();
13644 #endif
13645         INIT_G_cmdtable();
13646
13647 #if PROFILE
13648         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13649 #endif
13650
13651 #if ENABLE_FEATURE_EDITING
13652         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13653 #endif
13654         state = 0;
13655         if (setjmp(jmploc.loc)) {
13656                 smallint e;
13657                 smallint s;
13658
13659                 reset();
13660
13661                 e = exception_type;
13662                 s = state;
13663                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13664                         exitshell();
13665                 }
13666                 if (e == EXINT) {
13667                         newline_and_flush(stderr);
13668                 }
13669
13670                 popstackmark(&smark);
13671                 FORCE_INT_ON; /* enable interrupts */
13672                 if (s == 1)
13673                         goto state1;
13674                 if (s == 2)
13675                         goto state2;
13676                 if (s == 3)
13677                         goto state3;
13678                 goto state4;
13679         }
13680         exception_handler = &jmploc;
13681         rootpid = getpid();
13682
13683         init();
13684         setstackmark(&smark);
13685         procargs(argv);
13686 #if DEBUG
13687         TRACE(("Shell args: "));
13688         trace_puts_args(argv);
13689 #endif
13690
13691         if (argv[0] && argv[0][0] == '-')
13692                 isloginsh = 1;
13693         if (isloginsh) {
13694                 const char *hp;
13695
13696                 state = 1;
13697                 read_profile("/etc/profile");
13698  state1:
13699                 state = 2;
13700                 hp = lookupvar("HOME");
13701                 if (hp)
13702                         read_profile("$HOME/.profile");
13703         }
13704  state2:
13705         state = 3;
13706         if (
13707 #ifndef linux
13708          getuid() == geteuid() && getgid() == getegid() &&
13709 #endif
13710          iflag
13711         ) {
13712                 const char *shinit = lookupvar("ENV");
13713                 if (shinit != NULL && *shinit != '\0')
13714                         read_profile(shinit);
13715         }
13716         popstackmark(&smark);
13717  state3:
13718         state = 4;
13719         if (minusc) {
13720                 /* evalstring pushes parsefile stack.
13721                  * Ensure we don't falsely claim that 0 (stdin)
13722                  * is one of stacked source fds.
13723                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13724                 // if (!sflag) g_parsefile->pf_fd = -1;
13725                 // ^^ not necessary since now we special-case fd 0
13726                 // in is_hidden_fd() to not be considered "hidden fd"
13727                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13728         }
13729
13730         if (sflag || minusc == NULL) {
13731 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13732                 if (iflag) {
13733                         const char *hp = lookupvar("HISTFILE");
13734                         if (!hp) {
13735                                 hp = lookupvar("HOME");
13736                                 if (hp) {
13737                                         INT_OFF;
13738                                         hp = concat_path_file(hp, ".ash_history");
13739                                         setvar0("HISTFILE", hp);
13740                                         free((char*)hp);
13741                                         INT_ON;
13742                                         hp = lookupvar("HISTFILE");
13743                                 }
13744                         }
13745                         if (hp)
13746                                 line_input_state->hist_file = hp;
13747 # if ENABLE_FEATURE_SH_HISTFILESIZE
13748                         hp = lookupvar("HISTFILESIZE");
13749                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13750 # endif
13751                 }
13752 #endif
13753  state4: /* XXX ??? - why isn't this before the "if" statement */
13754                 cmdloop(1);
13755         }
13756 #if PROFILE
13757         monitor(0);
13758 #endif
13759 #ifdef GPROF
13760         {
13761                 extern void _mcleanup(void);
13762                 _mcleanup();
13763         }
13764 #endif
13765         TRACE(("End of main reached\n"));
13766         exitshell();
13767         /* NOTREACHED */
13768 }
13769
13770
13771 /*-
13772  * Copyright (c) 1989, 1991, 1993, 1994
13773  *      The Regents of the University of California.  All rights reserved.
13774  *
13775  * This code is derived from software contributed to Berkeley by
13776  * Kenneth Almquist.
13777  *
13778  * Redistribution and use in source and binary forms, with or without
13779  * modification, are permitted provided that the following conditions
13780  * are met:
13781  * 1. Redistributions of source code must retain the above copyright
13782  *    notice, this list of conditions and the following disclaimer.
13783  * 2. Redistributions in binary form must reproduce the above copyright
13784  *    notice, this list of conditions and the following disclaimer in the
13785  *    documentation and/or other materials provided with the distribution.
13786  * 3. Neither the name of the University nor the names of its contributors
13787  *    may be used to endorse or promote products derived from this software
13788  *    without specific prior written permission.
13789  *
13790  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13791  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13792  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13793  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13794  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13795  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13796  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13797  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13798  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13799  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13800  * SUCH DAMAGE.
13801  */