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