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