ash: [VAR] Move unsetvar functionality into setvareq
[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  * Open a file in noclobber mode.
5179  * The code was copied from bash.
5180  */
5181 static int
5182 noclobberopen(const char *fname)
5183 {
5184         int r, fd;
5185         struct stat finfo, finfo2;
5186
5187         /*
5188          * If the file exists and is a regular file, return an error
5189          * immediately.
5190          */
5191         r = stat(fname, &finfo);
5192         if (r == 0 && S_ISREG(finfo.st_mode)) {
5193                 errno = EEXIST;
5194                 return -1;
5195         }
5196
5197         /*
5198          * If the file was not present (r != 0), make sure we open it
5199          * exclusively so that if it is created before we open it, our open
5200          * will fail.  Make sure that we do not truncate an existing file.
5201          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5202          * file was not a regular file, we leave O_EXCL off.
5203          */
5204         if (r != 0)
5205                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5206         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5207
5208         /* If the open failed, return the file descriptor right away. */
5209         if (fd < 0)
5210                 return fd;
5211
5212         /*
5213          * OK, the open succeeded, but the file may have been changed from a
5214          * non-regular file to a regular file between the stat and the open.
5215          * We are assuming that the O_EXCL open handles the case where FILENAME
5216          * did not exist and is symlinked to an existing file between the stat
5217          * and open.
5218          */
5219
5220         /*
5221          * If we can open it and fstat the file descriptor, and neither check
5222          * revealed that it was a regular file, and the file has not been
5223          * replaced, return the file descriptor.
5224          */
5225         if (fstat(fd, &finfo2) == 0
5226          && !S_ISREG(finfo2.st_mode)
5227          && finfo.st_dev == finfo2.st_dev
5228          && finfo.st_ino == finfo2.st_ino
5229         ) {
5230                 return fd;
5231         }
5232
5233         /* The file has been replaced.  badness. */
5234         close(fd);
5235         errno = EEXIST;
5236         return -1;
5237 }
5238
5239 /*
5240  * Handle here documents.  Normally we fork off a process to write the
5241  * data to a pipe.  If the document is short, we can stuff the data in
5242  * the pipe without forking.
5243  */
5244 /* openhere needs this forward reference */
5245 static void expandhere(union node *arg, int fd);
5246 static int
5247 openhere(union node *redir)
5248 {
5249         int pip[2];
5250         size_t len = 0;
5251
5252         if (pipe(pip) < 0)
5253                 ash_msg_and_raise_error("pipe call failed");
5254         if (redir->type == NHERE) {
5255                 len = strlen(redir->nhere.doc->narg.text);
5256                 if (len <= PIPE_BUF) {
5257                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5258                         goto out;
5259                 }
5260         }
5261         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5262                 /* child */
5263                 close(pip[0]);
5264                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5265                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5266                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5267                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5268                 signal(SIGPIPE, SIG_DFL);
5269                 if (redir->type == NHERE)
5270                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5271                 else /* NXHERE */
5272                         expandhere(redir->nhere.doc, pip[1]);
5273                 _exit(EXIT_SUCCESS);
5274         }
5275  out:
5276         close(pip[1]);
5277         return pip[0];
5278 }
5279
5280 static int
5281 openredirect(union node *redir)
5282 {
5283         char *fname;
5284         int f;
5285
5286         switch (redir->nfile.type) {
5287 /* Can't happen, our single caller does this itself */
5288 //      case NTOFD:
5289 //      case NFROMFD:
5290 //              return -1;
5291         case NHERE:
5292         case NXHERE:
5293                 return openhere(redir);
5294         }
5295
5296         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5297          * allocated space. Do it only when we know it is safe.
5298          */
5299         fname = redir->nfile.expfname;
5300
5301         switch (redir->nfile.type) {
5302         default:
5303 #if DEBUG
5304                 abort();
5305 #endif
5306         case NFROM:
5307                 f = open(fname, O_RDONLY);
5308                 if (f < 0)
5309                         goto eopen;
5310                 break;
5311         case NFROMTO:
5312                 f = open(fname, O_RDWR|O_CREAT, 0666);
5313                 if (f < 0)
5314                         goto ecreate;
5315                 break;
5316         case NTO:
5317 #if BASH_REDIR_OUTPUT
5318         case NTO2:
5319 #endif
5320                 /* Take care of noclobber mode. */
5321                 if (Cflag) {
5322                         f = noclobberopen(fname);
5323                         if (f < 0)
5324                                 goto ecreate;
5325                         break;
5326                 }
5327                 /* FALLTHROUGH */
5328         case NCLOBBER:
5329                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5330                 if (f < 0)
5331                         goto ecreate;
5332                 break;
5333         case NAPPEND:
5334                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5335                 if (f < 0)
5336                         goto ecreate;
5337                 break;
5338         }
5339
5340         return f;
5341  ecreate:
5342         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5343  eopen:
5344         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5345 }
5346
5347 /*
5348  * Copy a file descriptor to be >= 10. Throws exception on error.
5349  */
5350 static int
5351 savefd(int from)
5352 {
5353         int newfd;
5354         int err;
5355
5356         newfd = fcntl(from, F_DUPFD, 10);
5357         err = newfd < 0 ? errno : 0;
5358         if (err != EBADF) {
5359                 if (err)
5360                         ash_msg_and_raise_error("%d: %m", from);
5361                 close(from);
5362                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5363         }
5364
5365         return newfd;
5366 }
5367 static int
5368 dup2_or_raise(int from, int to)
5369 {
5370         int newfd;
5371
5372         newfd = (from != to) ? dup2(from, to) : to;
5373         if (newfd < 0) {
5374                 /* Happens when source fd is not open: try "echo >&99" */
5375                 ash_msg_and_raise_error("%d: %m", from);
5376         }
5377         return newfd;
5378 }
5379
5380 /* Struct def and variable are moved down to the first usage site */
5381 struct two_fd_t {
5382         int orig, copy;
5383 };
5384 struct redirtab {
5385         struct redirtab *next;
5386         int pair_count;
5387         struct two_fd_t two_fd[];
5388 };
5389 #define redirlist (G_var.redirlist)
5390 enum {
5391         COPYFD_RESTORE = (int)~(INT_MAX),
5392 };
5393
5394 static int
5395 need_to_remember(struct redirtab *rp, int fd)
5396 {
5397         int i;
5398
5399         if (!rp) /* remembering was not requested */
5400                 return 0;
5401
5402         for (i = 0; i < rp->pair_count; i++) {
5403                 if (rp->two_fd[i].orig == fd) {
5404                         /* already remembered */
5405                         return 0;
5406                 }
5407         }
5408         return 1;
5409 }
5410
5411 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5412 static int
5413 is_hidden_fd(struct redirtab *rp, int fd)
5414 {
5415         int i;
5416         struct parsefile *pf;
5417
5418         if (fd == -1)
5419                 return 0;
5420         /* Check open scripts' fds */
5421         pf = g_parsefile;
5422         while (pf) {
5423                 /* We skip pf_fd == 0 case because of the following case:
5424                  * $ ash  # running ash interactively
5425                  * $ . ./script.sh
5426                  * and in script.sh: "exec 9>&0".
5427                  * Even though top-level pf_fd _is_ 0,
5428                  * it's still ok to use it: "read" builtin uses it,
5429                  * why should we cripple "exec" builtin?
5430                  */
5431                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5432                         return 1;
5433                 }
5434                 pf = pf->prev;
5435         }
5436
5437         if (!rp)
5438                 return 0;
5439         /* Check saved fds of redirects */
5440         fd |= COPYFD_RESTORE;
5441         for (i = 0; i < rp->pair_count; i++) {
5442                 if (rp->two_fd[i].copy == fd) {
5443                         return 1;
5444                 }
5445         }
5446         return 0;
5447 }
5448
5449 /*
5450  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5451  * old file descriptors are stashed away so that the redirection can be
5452  * undone by calling popredir.
5453  */
5454 /* flags passed to redirect */
5455 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5456 #define REDIR_SAVEFD2 03        /* set preverrout */
5457 static void
5458 redirect(union node *redir, int flags)
5459 {
5460         struct redirtab *sv;
5461         int sv_pos;
5462         int i;
5463         int fd;
5464         int newfd;
5465         int copied_fd2 = -1;
5466
5467         if (!redir) {
5468                 return;
5469         }
5470
5471         sv = NULL;
5472         sv_pos = 0;
5473         INT_OFF;
5474         if (flags & REDIR_PUSH) {
5475                 union node *tmp = redir;
5476                 do {
5477                         sv_pos++;
5478 #if BASH_REDIR_OUTPUT
5479                         if (tmp->nfile.type == NTO2)
5480                                 sv_pos++;
5481 #endif
5482                         tmp = tmp->nfile.next;
5483                 } while (tmp);
5484                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5485                 sv->next = redirlist;
5486                 sv->pair_count = sv_pos;
5487                 redirlist = sv;
5488                 while (sv_pos > 0) {
5489                         sv_pos--;
5490                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5491                 }
5492         }
5493
5494         do {
5495                 int right_fd = -1;
5496                 fd = redir->nfile.fd;
5497                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5498                         right_fd = redir->ndup.dupfd;
5499                         //bb_error_msg("doing %d > %d", fd, right_fd);
5500                         /* redirect from/to same file descriptor? */
5501                         if (right_fd == fd)
5502                                 continue;
5503                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5504                         if (is_hidden_fd(sv, right_fd)) {
5505                                 errno = EBADF; /* as if it is closed */
5506                                 ash_msg_and_raise_error("%d: %m", right_fd);
5507                         }
5508                         newfd = -1;
5509                 } else {
5510                         newfd = openredirect(redir); /* always >= 0 */
5511                         if (fd == newfd) {
5512                                 /* Descriptor wasn't open before redirect.
5513                                  * Mark it for close in the future */
5514                                 if (need_to_remember(sv, fd)) {
5515                                         goto remember_to_close;
5516                                 }
5517                                 continue;
5518                         }
5519                 }
5520 #if BASH_REDIR_OUTPUT
5521  redirect_more:
5522 #endif
5523                 if (need_to_remember(sv, fd)) {
5524                         /* Copy old descriptor */
5525                         /* Careful to not accidentally "save"
5526                          * to the same fd as right side fd in N>&M */
5527                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5528 #if defined(F_DUPFD_CLOEXEC)
5529                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5530 #else
5531                         i = fcntl(fd, F_DUPFD, minfd);
5532 #endif
5533                         if (i == -1) {
5534                                 i = errno;
5535                                 if (i != EBADF) {
5536                                         /* Strange error (e.g. "too many files" EMFILE?) */
5537                                         if (newfd >= 0)
5538                                                 close(newfd);
5539                                         errno = i;
5540                                         ash_msg_and_raise_error("%d: %m", fd);
5541                                         /* NOTREACHED */
5542                                 }
5543                                 /* EBADF: it is not open - good, remember to close it */
5544  remember_to_close:
5545                                 i = CLOSED;
5546                         } else { /* fd is open, save its copy */
5547 #if !defined(F_DUPFD_CLOEXEC)
5548                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5549 #endif
5550                                 /* "exec fd>&-" should not close fds
5551                                  * which point to script file(s).
5552                                  * Force them to be restored afterwards */
5553                                 if (is_hidden_fd(sv, fd))
5554                                         i |= COPYFD_RESTORE;
5555                         }
5556                         if (fd == 2)
5557                                 copied_fd2 = i;
5558                         sv->two_fd[sv_pos].orig = fd;
5559                         sv->two_fd[sv_pos].copy = i;
5560                         sv_pos++;
5561                 }
5562                 if (newfd < 0) {
5563                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5564                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5565                                 /* Don't want to trigger debugging */
5566                                 if (fd != -1)
5567                                         close(fd);
5568                         } else {
5569                                 dup2_or_raise(redir->ndup.dupfd, fd);
5570                         }
5571                 } else if (fd != newfd) { /* move newfd to fd */
5572                         dup2_or_raise(newfd, fd);
5573 #if BASH_REDIR_OUTPUT
5574                         if (!(redir->nfile.type == NTO2 && fd == 2))
5575 #endif
5576                                 close(newfd);
5577                 }
5578 #if BASH_REDIR_OUTPUT
5579                 if (redir->nfile.type == NTO2 && fd == 1) {
5580                         /* We already redirected it to fd 1, now copy it to 2 */
5581                         newfd = 1;
5582                         fd = 2;
5583                         goto redirect_more;
5584                 }
5585 #endif
5586         } while ((redir = redir->nfile.next) != NULL);
5587
5588         INT_ON;
5589         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5590                 preverrout_fd = copied_fd2;
5591 }
5592
5593 /*
5594  * Undo the effects of the last redirection.
5595  */
5596 static void
5597 popredir(int drop, int restore)
5598 {
5599         struct redirtab *rp;
5600         int i;
5601
5602         if (redirlist == NULL)
5603                 return;
5604         INT_OFF;
5605         rp = redirlist;
5606         for (i = 0; i < rp->pair_count; i++) {
5607                 int fd = rp->two_fd[i].orig;
5608                 int copy = rp->two_fd[i].copy;
5609                 if (copy == CLOSED) {
5610                         if (!drop)
5611                                 close(fd);
5612                         continue;
5613                 }
5614                 if (copy != EMPTY) {
5615                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5616                                 copy &= ~COPYFD_RESTORE;
5617                                 /*close(fd);*/
5618                                 dup2_or_raise(copy, fd);
5619                         }
5620                         close(copy & ~COPYFD_RESTORE);
5621                 }
5622         }
5623         redirlist = rp->next;
5624         free(rp);
5625         INT_ON;
5626 }
5627
5628 /*
5629  * Undo all redirections.  Called on error or interrupt.
5630  */
5631
5632 static int
5633 redirectsafe(union node *redir, int flags)
5634 {
5635         int err;
5636         volatile int saveint;
5637         struct jmploc *volatile savehandler = exception_handler;
5638         struct jmploc jmploc;
5639
5640         SAVE_INT(saveint);
5641         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5642         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5643         if (!err) {
5644                 exception_handler = &jmploc;
5645                 redirect(redir, flags);
5646         }
5647         exception_handler = savehandler;
5648         if (err && exception_type != EXERROR)
5649                 longjmp(exception_handler->loc, 1);
5650         RESTORE_INT(saveint);
5651         return err;
5652 }
5653
5654
5655 /* ============ Routines to expand arguments to commands
5656  *
5657  * We have to deal with backquotes, shell variables, and file metacharacters.
5658  */
5659
5660 #if ENABLE_FEATURE_SH_MATH
5661 static arith_t
5662 ash_arith(const char *s)
5663 {
5664         arith_state_t math_state;
5665         arith_t result;
5666
5667         math_state.lookupvar = lookupvar;
5668         math_state.setvar    = setvar0;
5669         //math_state.endofname = endofname;
5670
5671         INT_OFF;
5672         result = arith(&math_state, s);
5673         if (math_state.errmsg)
5674                 ash_msg_and_raise_error(math_state.errmsg);
5675         INT_ON;
5676
5677         return result;
5678 }
5679 #endif
5680
5681 /*
5682  * expandarg flags
5683  */
5684 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5685 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5686 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5687 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5688 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5689  * POSIX says for this case:
5690  *  Pathname expansion shall not be performed on the word by a
5691  *  non-interactive shell; an interactive shell may perform it, but shall
5692  *  do so only when the expansion would result in one word.
5693  * Currently, our code complies to the above rule by never globbing
5694  * redirection filenames.
5695  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5696  * (this means that on a typical Linux distro, bash almost always
5697  * performs globbing, and thus diverges from what we do).
5698  */
5699 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5700 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5701 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5702 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5703 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5704 /*
5705  * rmescape() flags
5706  */
5707 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5708 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5709 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5710 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5711 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5712
5713 /* Add CTLESC when necessary. */
5714 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5715 /* Do not skip NUL characters. */
5716 #define QUOTES_KEEPNUL EXP_TILDE
5717
5718 /*
5719  * Structure specifying which parts of the string should be searched
5720  * for IFS characters.
5721  */
5722 struct ifsregion {
5723         struct ifsregion *next; /* next region in list */
5724         int begoff;             /* offset of start of region */
5725         int endoff;             /* offset of end of region */
5726         int nulonly;            /* search for nul bytes only */
5727 };
5728
5729 struct arglist {
5730         struct strlist *list;
5731         struct strlist **lastp;
5732 };
5733
5734 /* output of current string */
5735 static char *expdest;
5736 /* list of back quote expressions */
5737 static struct nodelist *argbackq;
5738 /* first struct in list of ifs regions */
5739 static struct ifsregion ifsfirst;
5740 /* last struct in list */
5741 static struct ifsregion *ifslastp;
5742 /* holds expanded arg list */
5743 static struct arglist exparg;
5744
5745 /*
5746  * Our own itoa().
5747  */
5748 #if !ENABLE_FEATURE_SH_MATH
5749 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5750 typedef long arith_t;
5751 # define ARITH_FMT "%ld"
5752 #endif
5753 static int
5754 cvtnum(arith_t num)
5755 {
5756         int len;
5757
5758         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5759         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5760         STADJUST(len, expdest);
5761         return len;
5762 }
5763
5764 /*
5765  * Break the argument string into pieces based upon IFS and add the
5766  * strings to the argument list.  The regions of the string to be
5767  * searched for IFS characters have been stored by recordregion.
5768  */
5769 static void
5770 ifsbreakup(char *string, struct arglist *arglist)
5771 {
5772         struct ifsregion *ifsp;
5773         struct strlist *sp;
5774         char *start;
5775         char *p;
5776         char *q;
5777         const char *ifs, *realifs;
5778         int ifsspc;
5779         int nulonly;
5780
5781         start = string;
5782         if (ifslastp != NULL) {
5783                 ifsspc = 0;
5784                 nulonly = 0;
5785                 realifs = ifsset() ? ifsval() : defifs;
5786                 ifsp = &ifsfirst;
5787                 do {
5788                         p = string + ifsp->begoff;
5789                         nulonly = ifsp->nulonly;
5790                         ifs = nulonly ? nullstr : realifs;
5791                         ifsspc = 0;
5792                         while (p < string + ifsp->endoff) {
5793                                 q = p;
5794                                 if ((unsigned char)*p == CTLESC)
5795                                         p++;
5796                                 if (!strchr(ifs, *p)) {
5797                                         p++;
5798                                         continue;
5799                                 }
5800                                 if (!nulonly)
5801                                         ifsspc = (strchr(defifs, *p) != NULL);
5802                                 /* Ignore IFS whitespace at start */
5803                                 if (q == start && ifsspc) {
5804                                         p++;
5805                                         start = p;
5806                                         continue;
5807                                 }
5808                                 *q = '\0';
5809                                 sp = stzalloc(sizeof(*sp));
5810                                 sp->text = start;
5811                                 *arglist->lastp = sp;
5812                                 arglist->lastp = &sp->next;
5813                                 p++;
5814                                 if (!nulonly) {
5815                                         for (;;) {
5816                                                 if (p >= string + ifsp->endoff) {
5817                                                         break;
5818                                                 }
5819                                                 q = p;
5820                                                 if ((unsigned char)*p == CTLESC)
5821                                                         p++;
5822                                                 if (strchr(ifs, *p) == NULL) {
5823                                                         p = q;
5824                                                         break;
5825                                                 }
5826                                                 if (strchr(defifs, *p) == NULL) {
5827                                                         if (ifsspc) {
5828                                                                 p++;
5829                                                                 ifsspc = 0;
5830                                                         } else {
5831                                                                 p = q;
5832                                                                 break;
5833                                                         }
5834                                                 } else
5835                                                         p++;
5836                                         }
5837                                 }
5838                                 start = p;
5839                         } /* while */
5840                         ifsp = ifsp->next;
5841                 } while (ifsp != NULL);
5842                 if (nulonly)
5843                         goto add;
5844         }
5845
5846         if (!*start)
5847                 return;
5848
5849  add:
5850         sp = stzalloc(sizeof(*sp));
5851         sp->text = start;
5852         *arglist->lastp = sp;
5853         arglist->lastp = &sp->next;
5854 }
5855
5856 static void
5857 ifsfree(void)
5858 {
5859         struct ifsregion *p = ifsfirst.next;
5860
5861         if (!p)
5862                 goto out;
5863
5864         INT_OFF;
5865         do {
5866                 struct ifsregion *ifsp;
5867                 ifsp = p->next;
5868                 free(p);
5869                 p = ifsp;
5870         } while (p);
5871         ifsfirst.next = NULL;
5872         INT_ON;
5873  out:
5874         ifslastp = NULL;
5875 }
5876
5877 static size_t
5878 esclen(const char *start, const char *p)
5879 {
5880         size_t esc = 0;
5881
5882         while (p > start && (unsigned char)*--p == CTLESC) {
5883                 esc++;
5884         }
5885         return esc;
5886 }
5887
5888 /*
5889  * Remove any CTLESC characters from a string.
5890  */
5891 static char *
5892 rmescapes(char *str, int flag)
5893 {
5894         static const char qchars[] ALIGN1 = {
5895                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5896
5897         char *p, *q, *r;
5898         unsigned inquotes;
5899         unsigned protect_against_glob;
5900         unsigned globbing;
5901         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5902
5903         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5904         if (!p)
5905                 return str;
5906
5907         q = p;
5908         r = str;
5909         if (flag & RMESCAPE_ALLOC) {
5910                 size_t len = p - str;
5911                 size_t fulllen = len + strlen(p) + 1;
5912
5913                 if (flag & RMESCAPE_GROW) {
5914                         int strloc = str - (char *)stackblock();
5915                         r = makestrspace(fulllen, expdest);
5916                         /* p and str may be invalidated by makestrspace */
5917                         str = (char *)stackblock() + strloc;
5918                         p = str + len;
5919                 } else if (flag & RMESCAPE_HEAP) {
5920                         r = ckmalloc(fulllen);
5921                 } else {
5922                         r = stalloc(fulllen);
5923                 }
5924                 q = r;
5925                 if (len > 0) {
5926                         q = (char *)mempcpy(q, str, len);
5927                 }
5928         }
5929
5930         inquotes = 0;
5931         globbing = flag & RMESCAPE_GLOB;
5932         protect_against_glob = globbing;
5933         while (*p) {
5934                 if ((unsigned char)*p == CTLQUOTEMARK) {
5935 // Note: both inquotes and protect_against_glob only affect whether
5936 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5937                         inquotes = ~inquotes;
5938                         p++;
5939                         protect_against_glob = globbing;
5940                         continue;
5941                 }
5942                 if ((unsigned char)*p == CTLESC) {
5943                         p++;
5944 #if DEBUG
5945                         if (*p == '\0')
5946                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5947 #endif
5948                         if (protect_against_glob) {
5949                                 /*
5950                                  * We used to trust glob() and fnmatch() to eat
5951                                  * superfluous escapes (\z where z has no
5952                                  * special meaning anyway). But this causes
5953                                  * bugs such as string of one greek letter rho
5954                                  * (unicode-encoded as two bytes "cf,81")
5955                                  * getting encoded as "cf,CTLESC,81"
5956                                  * and here, converted to "cf,\,81" -
5957                                  * which does not go well with some flavors
5958                                  * of fnmatch() in unicode locales
5959                                  * (for example, glibc <= 2.22).
5960                                  *
5961                                  * Lets add "\" only on the chars which need it.
5962                                  * Testcases for less obvious chars are shown.
5963                                  */
5964                                 if (*p == '*'
5965                                  || *p == '?'
5966                                  || *p == '['
5967                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5968                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5969                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5970                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5971                                 /* Some libc support [^negate], that's why "^" also needs love */
5972                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5973                                 ) {
5974                                         *q++ = '\\';
5975                                 }
5976                         }
5977                 } else if (*p == '\\' && !inquotes) {
5978                         /* naked back slash */
5979                         protect_against_glob = 0;
5980                         goto copy;
5981                 }
5982 #if BASH_PATTERN_SUBST
5983                 else if (*p == '/' && slash) {
5984                         /* stop handling globbing and mark location of slash */
5985                         globbing = slash = 0;
5986                         *p = CTLESC;
5987                 }
5988 #endif
5989                 protect_against_glob = globbing;
5990  copy:
5991                 *q++ = *p++;
5992         }
5993         *q = '\0';
5994         if (flag & RMESCAPE_GROW) {
5995                 expdest = r;
5996                 STADJUST(q - r + 1, expdest);
5997         }
5998         return r;
5999 }
6000 #define pmatch(a, b) !fnmatch((a), (b), 0)
6001
6002 /*
6003  * Prepare a pattern for a expmeta (internal glob(3)) call.
6004  *
6005  * Returns an stalloced string.
6006  */
6007 static char *
6008 preglob(const char *pattern, int flag)
6009 {
6010         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
6011 }
6012
6013 /*
6014  * Put a string on the stack.
6015  */
6016 static void
6017 memtodest(const char *p, size_t len, int syntax, int quotes)
6018 {
6019         char *q;
6020
6021         if (!len)
6022                 return;
6023
6024         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6025
6026         do {
6027                 unsigned char c = *p++;
6028                 if (c) {
6029                         if (quotes & QUOTES_ESC) {
6030                                 int n = SIT(c, syntax);
6031                                 if (n == CCTL
6032                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6033                                      && n == CBACK
6034                                     )
6035                                 ) {
6036                                         USTPUTC(CTLESC, q);
6037                                 }
6038                         }
6039                 } else if (!(quotes & QUOTES_KEEPNUL))
6040                         continue;
6041                 USTPUTC(c, q);
6042         } while (--len);
6043
6044         expdest = q;
6045 }
6046
6047 static size_t
6048 strtodest(const char *p, int syntax, int quotes)
6049 {
6050         size_t len = strlen(p);
6051         memtodest(p, len, syntax, quotes);
6052         return len;
6053 }
6054
6055 /*
6056  * Record the fact that we have to scan this region of the
6057  * string for IFS characters.
6058  */
6059 static void
6060 recordregion(int start, int end, int nulonly)
6061 {
6062         struct ifsregion *ifsp;
6063
6064         if (ifslastp == NULL) {
6065                 ifsp = &ifsfirst;
6066         } else {
6067                 INT_OFF;
6068                 ifsp = ckzalloc(sizeof(*ifsp));
6069                 /*ifsp->next = NULL; - ckzalloc did it */
6070                 ifslastp->next = ifsp;
6071                 INT_ON;
6072         }
6073         ifslastp = ifsp;
6074         ifslastp->begoff = start;
6075         ifslastp->endoff = end;
6076         ifslastp->nulonly = nulonly;
6077 }
6078
6079 static void
6080 removerecordregions(int endoff)
6081 {
6082         if (ifslastp == NULL)
6083                 return;
6084
6085         if (ifsfirst.endoff > endoff) {
6086                 while (ifsfirst.next) {
6087                         struct ifsregion *ifsp;
6088                         INT_OFF;
6089                         ifsp = ifsfirst.next->next;
6090                         free(ifsfirst.next);
6091                         ifsfirst.next = ifsp;
6092                         INT_ON;
6093                 }
6094                 if (ifsfirst.begoff > endoff) {
6095                         ifslastp = NULL;
6096                 } else {
6097                         ifslastp = &ifsfirst;
6098                         ifsfirst.endoff = endoff;
6099                 }
6100                 return;
6101         }
6102
6103         ifslastp = &ifsfirst;
6104         while (ifslastp->next && ifslastp->next->begoff < endoff)
6105                 ifslastp = ifslastp->next;
6106         while (ifslastp->next) {
6107                 struct ifsregion *ifsp;
6108                 INT_OFF;
6109                 ifsp = ifslastp->next->next;
6110                 free(ifslastp->next);
6111                 ifslastp->next = ifsp;
6112                 INT_ON;
6113         }
6114         if (ifslastp->endoff > endoff)
6115                 ifslastp->endoff = endoff;
6116 }
6117
6118 static char *
6119 exptilde(char *startp, char *p, int flags)
6120 {
6121         unsigned char c;
6122         char *name;
6123         struct passwd *pw;
6124         const char *home;
6125         int quotes = flags & QUOTES_ESC;
6126
6127         name = p + 1;
6128
6129         while ((c = *++p) != '\0') {
6130                 switch (c) {
6131                 case CTLESC:
6132                         return startp;
6133                 case CTLQUOTEMARK:
6134                         return startp;
6135                 case ':':
6136                         if (flags & EXP_VARTILDE)
6137                                 goto done;
6138                         break;
6139                 case '/':
6140                 case CTLENDVAR:
6141                         goto done;
6142                 }
6143         }
6144  done:
6145         *p = '\0';
6146         if (*name == '\0') {
6147                 home = lookupvar("HOME");
6148         } else {
6149                 pw = getpwnam(name);
6150                 if (pw == NULL)
6151                         goto lose;
6152                 home = pw->pw_dir;
6153         }
6154         if (!home || !*home)
6155                 goto lose;
6156         *p = c;
6157         strtodest(home, SQSYNTAX, quotes);
6158         return p;
6159  lose:
6160         *p = c;
6161         return startp;
6162 }
6163
6164 /*
6165  * Execute a command inside back quotes.  If it's a builtin command, we
6166  * want to save its output in a block obtained from malloc.  Otherwise
6167  * we fork off a subprocess and get the output of the command via a pipe.
6168  * Should be called with interrupts off.
6169  */
6170 struct backcmd {                /* result of evalbackcmd */
6171         int fd;                 /* file descriptor to read from */
6172         int nleft;              /* number of chars in buffer */
6173         char *buf;              /* buffer */
6174         struct job *jp;         /* job structure for command */
6175 };
6176
6177 /* These forward decls are needed to use "eval" code for backticks handling: */
6178 #define EV_EXIT 01              /* exit after evaluating tree */
6179 static int evaltree(union node *, int);
6180
6181 static void FAST_FUNC
6182 evalbackcmd(union node *n, struct backcmd *result)
6183 {
6184         int pip[2];
6185         struct job *jp;
6186
6187         result->fd = -1;
6188         result->buf = NULL;
6189         result->nleft = 0;
6190         result->jp = NULL;
6191         if (n == NULL) {
6192                 goto out;
6193         }
6194
6195         if (pipe(pip) < 0)
6196                 ash_msg_and_raise_error("pipe call failed");
6197         jp = makejob(/*n,*/ 1);
6198         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6199                 /* child */
6200                 FORCE_INT_ON;
6201                 close(pip[0]);
6202                 if (pip[1] != 1) {
6203                         /*close(1);*/
6204                         dup2_or_raise(pip[1], 1);
6205                         close(pip[1]);
6206                 }
6207 /* TODO: eflag clearing makes the following not abort:
6208  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6209  * which is what bash does (unless it is in POSIX mode).
6210  * dash deleted "eflag = 0" line in the commit
6211  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6212  *  [EVAL] Don't clear eflag in evalbackcmd
6213  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6214  */
6215                 eflag = 0;
6216                 ifsfree();
6217                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6218                 /* NOTREACHED */
6219         }
6220         /* parent */
6221         close(pip[1]);
6222         result->fd = pip[0];
6223         result->jp = jp;
6224
6225  out:
6226         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6227                 result->fd, result->buf, result->nleft, result->jp));
6228 }
6229
6230 /*
6231  * Expand stuff in backwards quotes.
6232  */
6233 static void
6234 expbackq(union node *cmd, int flag)
6235 {
6236         struct backcmd in;
6237         int i;
6238         char buf[128];
6239         char *p;
6240         char *dest;
6241         int startloc;
6242         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6243         struct stackmark smark;
6244
6245         INT_OFF;
6246         startloc = expdest - (char *)stackblock();
6247         pushstackmark(&smark, startloc);
6248         evalbackcmd(cmd, &in);
6249         popstackmark(&smark);
6250
6251         p = in.buf;
6252         i = in.nleft;
6253         if (i == 0)
6254                 goto read;
6255         for (;;) {
6256                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6257  read:
6258                 if (in.fd < 0)
6259                         break;
6260                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6261                 TRACE(("expbackq: read returns %d\n", i));
6262                 if (i <= 0)
6263                         break;
6264                 p = buf;
6265         }
6266
6267         free(in.buf);
6268         if (in.fd >= 0) {
6269                 close(in.fd);
6270                 back_exitstatus = waitforjob(in.jp);
6271         }
6272         INT_ON;
6273
6274         /* Eat all trailing newlines */
6275         dest = expdest;
6276         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6277                 STUNPUTC(dest);
6278         expdest = dest;
6279
6280         if (!(flag & EXP_QUOTED))
6281                 recordregion(startloc, dest - (char *)stackblock(), 0);
6282         TRACE(("evalbackq: size:%d:'%.*s'\n",
6283                 (int)((dest - (char *)stackblock()) - startloc),
6284                 (int)((dest - (char *)stackblock()) - startloc),
6285                 stackblock() + startloc));
6286 }
6287
6288 #if ENABLE_FEATURE_SH_MATH
6289 /*
6290  * Expand arithmetic expression.  Backup to start of expression,
6291  * evaluate, place result in (backed up) result, adjust string position.
6292  */
6293 static void
6294 expari(int flag)
6295 {
6296         char *p, *start;
6297         int begoff;
6298         int len;
6299
6300         /* ifsfree(); */
6301
6302         /*
6303          * This routine is slightly over-complicated for
6304          * efficiency.  Next we scan backwards looking for the
6305          * start of arithmetic.
6306          */
6307         start = stackblock();
6308         p = expdest - 1;
6309         *p = '\0';
6310         p--;
6311         while (1) {
6312                 int esc;
6313
6314                 while ((unsigned char)*p != CTLARI) {
6315                         p--;
6316 #if DEBUG
6317                         if (p < start) {
6318                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6319                         }
6320 #endif
6321                 }
6322
6323                 esc = esclen(start, p);
6324                 if (!(esc % 2)) {
6325                         break;
6326                 }
6327
6328                 p -= esc + 1;
6329         }
6330
6331         begoff = p - start;
6332
6333         removerecordregions(begoff);
6334
6335         expdest = p;
6336
6337         if (flag & QUOTES_ESC)
6338                 rmescapes(p + 1, 0);
6339
6340         len = cvtnum(ash_arith(p + 1));
6341
6342         if (!(flag & EXP_QUOTED))
6343                 recordregion(begoff, begoff + len, 0);
6344 }
6345 #endif
6346
6347 /* argstr needs it */
6348 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6349
6350 /*
6351  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6352  * characters to allow for further processing.  Otherwise treat
6353  * $@ like $* since no splitting will be performed.
6354  *
6355  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6356  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6357  * for correct expansion of "B=$A" word.
6358  */
6359 static void
6360 argstr(char *p, int flags, struct strlist *var_str_list)
6361 {
6362         static const char spclchars[] ALIGN1 = {
6363                 '=',
6364                 ':',
6365                 CTLQUOTEMARK,
6366                 CTLENDVAR,
6367                 CTLESC,
6368                 CTLVAR,
6369                 CTLBACKQ,
6370 #if ENABLE_FEATURE_SH_MATH
6371                 CTLENDARI,
6372 #endif
6373                 '\0'
6374         };
6375         const char *reject = spclchars;
6376         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6377         int inquotes;
6378         size_t length;
6379         int startloc;
6380
6381         if (!(flags & EXP_VARTILDE)) {
6382                 reject += 2;
6383         } else if (flags & EXP_VARTILDE2) {
6384                 reject++;
6385         }
6386         inquotes = 0;
6387         length = 0;
6388         if (flags & EXP_TILDE) {
6389                 char *q;
6390
6391                 flags &= ~EXP_TILDE;
6392  tilde:
6393                 q = p;
6394                 if (*q == '~')
6395                         p = exptilde(p, q, flags);
6396         }
6397  start:
6398         startloc = expdest - (char *)stackblock();
6399         for (;;) {
6400                 unsigned char c;
6401
6402                 length += strcspn(p + length, reject);
6403                 c = p[length];
6404                 if (c) {
6405                         if (!(c & 0x80)
6406                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6407                         ) {
6408                                 /* c == '=' || c == ':' || c == CTLENDARI */
6409                                 length++;
6410                         }
6411                 }
6412                 if (length > 0) {
6413                         int newloc;
6414                         expdest = stack_nputstr(p, length, expdest);
6415                         newloc = expdest - (char *)stackblock();
6416                         if (breakall && !inquotes && newloc > startloc) {
6417                                 recordregion(startloc, newloc, 0);
6418                         }
6419                         startloc = newloc;
6420                 }
6421                 p += length + 1;
6422                 length = 0;
6423
6424                 switch (c) {
6425                 case '\0':
6426                         goto breakloop;
6427                 case '=':
6428                         if (flags & EXP_VARTILDE2) {
6429                                 p--;
6430                                 continue;
6431                         }
6432                         flags |= EXP_VARTILDE2;
6433                         reject++;
6434                         /* fall through */
6435                 case ':':
6436                         /*
6437                          * sort of a hack - expand tildes in variable
6438                          * assignments (after the first '=' and after ':'s).
6439                          */
6440                         if (*--p == '~') {
6441                                 goto tilde;
6442                         }
6443                         continue;
6444                 }
6445
6446                 switch (c) {
6447                 case CTLENDVAR: /* ??? */
6448                         goto breakloop;
6449                 case CTLQUOTEMARK:
6450                         inquotes ^= EXP_QUOTED;
6451                         /* "$@" syntax adherence hack */
6452                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6453                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6454                                 goto start;
6455                         }
6456  addquote:
6457                         if (flags & QUOTES_ESC) {
6458                                 p--;
6459                                 length++;
6460                                 startloc++;
6461                         }
6462                         break;
6463                 case CTLESC:
6464                         startloc++;
6465                         length++;
6466
6467                         /*
6468                          * Quoted parameter expansion pattern: remove quote
6469                          * unless inside inner quotes or we have a literal
6470                          * backslash.
6471                          */
6472                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6473                             EXP_QPAT && *p != '\\')
6474                                 break;
6475
6476                         goto addquote;
6477                 case CTLVAR:
6478                         TRACE(("argstr: evalvar('%s')\n", p));
6479                         p = evalvar(p, flags | inquotes, var_str_list);
6480                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6481                         goto start;
6482                 case CTLBACKQ:
6483                         expbackq(argbackq->n, flags | inquotes);
6484                         argbackq = argbackq->next;
6485                         goto start;
6486 #if ENABLE_FEATURE_SH_MATH
6487                 case CTLENDARI:
6488                         p--;
6489                         expari(flags | inquotes);
6490                         goto start;
6491 #endif
6492                 }
6493         }
6494  breakloop: ;
6495 }
6496
6497 static char *
6498 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6499                 char *pattern, int quotes, int zero)
6500 {
6501         char *loc, *loc2;
6502         char c;
6503
6504         loc = startp;
6505         loc2 = rmesc;
6506         do {
6507                 int match;
6508                 const char *s = loc2;
6509
6510                 c = *loc2;
6511                 if (zero) {
6512                         *loc2 = '\0';
6513                         s = rmesc;
6514                 }
6515                 match = pmatch(pattern, s);
6516
6517                 *loc2 = c;
6518                 if (match)
6519                         return loc;
6520                 if (quotes && (unsigned char)*loc == CTLESC)
6521                         loc++;
6522                 loc++;
6523                 loc2++;
6524         } while (c);
6525         return NULL;
6526 }
6527
6528 static char *
6529 scanright(char *startp, char *rmesc, char *rmescend,
6530                 char *pattern, int quotes, int match_at_start)
6531 {
6532 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6533         int try2optimize = match_at_start;
6534 #endif
6535         int esc = 0;
6536         char *loc;
6537         char *loc2;
6538
6539         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6540          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6541          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6542          * Logic:
6543          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6544          * and on each iteration they go back two/one char until they reach the beginning.
6545          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6546          */
6547         /* TODO: document in what other circumstances we are called. */
6548
6549         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6550                 int match;
6551                 char c = *loc2;
6552                 const char *s = loc2;
6553                 if (match_at_start) {
6554                         *loc2 = '\0';
6555                         s = rmesc;
6556                 }
6557                 match = pmatch(pattern, s);
6558                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6559                 *loc2 = c;
6560                 if (match)
6561                         return loc;
6562 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6563                 if (try2optimize) {
6564                         /* Maybe we can optimize this:
6565                          * if pattern ends with unescaped *, we can avoid checking
6566                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6567                          * it won't match truncated "raw_value_of_" strings too.
6568                          */
6569                         unsigned plen = strlen(pattern);
6570                         /* Does it end with "*"? */
6571                         if (plen != 0 && pattern[--plen] == '*') {
6572                                 /* "xxxx*" is not escaped */
6573                                 /* "xxx\*" is escaped */
6574                                 /* "xx\\*" is not escaped */
6575                                 /* "x\\\*" is escaped */
6576                                 int slashes = 0;
6577                                 while (plen != 0 && pattern[--plen] == '\\')
6578                                         slashes++;
6579                                 if (!(slashes & 1))
6580                                         break; /* ends with unescaped "*" */
6581                         }
6582                         try2optimize = 0;
6583                 }
6584 #endif
6585                 loc--;
6586                 if (quotes) {
6587                         if (--esc < 0) {
6588                                 esc = esclen(startp, loc);
6589                         }
6590                         if (esc % 2) {
6591                                 esc--;
6592                                 loc--;
6593                         }
6594                 }
6595         }
6596         return NULL;
6597 }
6598
6599 static void varunset(const char *, const char *, const char *, int) NORETURN;
6600 static void
6601 varunset(const char *end, const char *var, const char *umsg, int varflags)
6602 {
6603         const char *msg;
6604         const char *tail;
6605
6606         tail = nullstr;
6607         msg = "parameter not set";
6608         if (umsg) {
6609                 if ((unsigned char)*end == CTLENDVAR) {
6610                         if (varflags & VSNUL)
6611                                 tail = " or null";
6612                 } else {
6613                         msg = umsg;
6614                 }
6615         }
6616         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6617 }
6618
6619 static const char *
6620 subevalvar(char *p, char *varname, int strloc, int subtype,
6621                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6622 {
6623         struct nodelist *saveargbackq = argbackq;
6624         int quotes = flag & QUOTES_ESC;
6625         char *startp;
6626         char *loc;
6627         char *rmesc, *rmescend;
6628         char *str;
6629         int amount, resetloc;
6630         IF_BASH_PATTERN_SUBST(int workloc;)
6631         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6632         int zero;
6633         char *(*scan)(char*, char*, char*, char*, int, int);
6634
6635         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6636         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6637
6638         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6639                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6640                         var_str_list);
6641         STPUTC('\0', expdest);
6642         argbackq = saveargbackq;
6643         startp = (char *)stackblock() + startloc;
6644
6645         switch (subtype) {
6646         case VSASSIGN:
6647                 setvar0(varname, startp);
6648                 amount = startp - expdest;
6649                 STADJUST(amount, expdest);
6650                 return startp;
6651
6652         case VSQUESTION:
6653                 varunset(p, varname, startp, varflags);
6654                 /* NOTREACHED */
6655
6656 #if BASH_SUBSTR
6657         case VSSUBSTR: {
6658                 int pos, len, orig_len;
6659                 char *colon;
6660
6661                 loc = str = stackblock() + strloc;
6662
6663 # if !ENABLE_FEATURE_SH_MATH
6664 #  define ash_arith number
6665 # endif
6666                 /* Read POS in ${var:POS:LEN} */
6667                 colon = strchr(loc, ':');
6668                 if (colon) *colon = '\0';
6669                 pos = ash_arith(loc);
6670                 if (colon) *colon = ':';
6671
6672                 /* Read LEN in ${var:POS:LEN} */
6673                 len = str - startp - 1;
6674                 /* *loc != '\0', guaranteed by parser */
6675                 if (quotes) {
6676                         char *ptr;
6677
6678                         /* Adjust the length by the number of escapes */
6679                         for (ptr = startp; ptr < (str - 1); ptr++) {
6680                                 if ((unsigned char)*ptr == CTLESC) {
6681                                         len--;
6682                                         ptr++;
6683                                 }
6684                         }
6685                 }
6686                 orig_len = len;
6687                 if (*loc++ == ':') {
6688                         /* ${var::LEN} */
6689                         len = ash_arith(loc);
6690                 } else {
6691                         /* Skip POS in ${var:POS:LEN} */
6692                         len = orig_len;
6693                         while (*loc && *loc != ':') {
6694                                 loc++;
6695                         }
6696                         if (*loc++ == ':') {
6697                                 len = ash_arith(loc);
6698                         }
6699                 }
6700 #  undef ash_arith
6701
6702                 if (pos < 0) {
6703                         /* ${VAR:$((-n)):l} starts n chars from the end */
6704                         pos = orig_len + pos;
6705                 }
6706                 if ((unsigned)pos >= orig_len) {
6707                         /* apart from obvious ${VAR:999999:l},
6708                          * covers ${VAR:$((-9999999)):l} - result is ""
6709                          * (bash compat)
6710                          */
6711                         pos = 0;
6712                         len = 0;
6713                 }
6714                 if (len < 0) {
6715                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6716                         len = (orig_len - pos) + len;
6717                 }
6718                 if ((unsigned)len > (orig_len - pos))
6719                         len = orig_len - pos;
6720
6721                 for (str = startp; pos; str++, pos--) {
6722                         if (quotes && (unsigned char)*str == CTLESC)
6723                                 str++;
6724                 }
6725                 for (loc = startp; len; len--) {
6726                         if (quotes && (unsigned char)*str == CTLESC)
6727                                 *loc++ = *str++;
6728                         *loc++ = *str++;
6729                 }
6730                 *loc = '\0';
6731                 amount = loc - expdest;
6732                 STADJUST(amount, expdest);
6733                 return loc;
6734         }
6735 #endif /* BASH_SUBSTR */
6736         }
6737
6738         resetloc = expdest - (char *)stackblock();
6739
6740 #if BASH_PATTERN_SUBST
6741         /* We'll comeback here if we grow the stack while handling
6742          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6743          * stack will need rebasing, and we'll need to remove our work
6744          * areas each time
6745          */
6746  restart:
6747 #endif
6748
6749         amount = expdest - ((char *)stackblock() + resetloc);
6750         STADJUST(-amount, expdest);
6751         startp = (char *)stackblock() + startloc;
6752
6753         rmesc = startp;
6754         rmescend = (char *)stackblock() + strloc;
6755         if (quotes) {
6756                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6757                 if (rmesc != startp) {
6758                         rmescend = expdest;
6759                         startp = (char *)stackblock() + startloc;
6760                 }
6761         }
6762         rmescend--;
6763         str = (char *)stackblock() + strloc;
6764         /*
6765          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6766          * The result is a_\_z_c (not a\_\_z_c)!
6767          *
6768          * The search pattern and replace string treat backslashes differently!
6769          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6770          * and string.  It's only used on the first call.
6771          */
6772         preglob(str, IF_BASH_PATTERN_SUBST(
6773                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6774                         RMESCAPE_SLASH : ) 0);
6775
6776 #if BASH_PATTERN_SUBST
6777         workloc = expdest - (char *)stackblock();
6778         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6779                 int len;
6780                 char *idx, *end;
6781
6782                 if (!repl) {
6783                         repl = strchr(str, CTLESC);
6784                         if (repl)
6785                                 *repl++ = '\0';
6786                         else
6787                                 repl = nullstr;
6788                 }
6789                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6790
6791                 /* If there's no pattern to match, return the expansion unmolested */
6792                 if (str[0] == '\0')
6793                         return NULL;
6794
6795                 len = 0;
6796                 idx = startp;
6797                 end = str - 1;
6798                 while (idx < end) {
6799  try_to_match:
6800                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6801                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6802                         if (!loc) {
6803                                 /* No match, advance */
6804                                 char *restart_detect = stackblock();
6805  skip_matching:
6806                                 STPUTC(*idx, expdest);
6807                                 if (quotes && (unsigned char)*idx == CTLESC) {
6808                                         idx++;
6809                                         len++;
6810                                         STPUTC(*idx, expdest);
6811                                 }
6812                                 if (stackblock() != restart_detect)
6813                                         goto restart;
6814                                 idx++;
6815                                 len++;
6816                                 rmesc++;
6817                                 /* continue; - prone to quadratic behavior, smarter code: */
6818                                 if (idx >= end)
6819                                         break;
6820                                 if (str[0] == '*') {
6821                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6822                                          * it would never match "ong_string" etc, no point in trying.
6823                                          */
6824                                         goto skip_matching;
6825                                 }
6826                                 goto try_to_match;
6827                         }
6828
6829                         if (subtype == VSREPLACEALL) {
6830                                 while (idx < loc) {
6831                                         if (quotes && (unsigned char)*idx == CTLESC)
6832                                                 idx++;
6833                                         idx++;
6834                                         rmesc++;
6835                                 }
6836                         } else {
6837                                 idx = loc;
6838                         }
6839
6840                         //bb_error_msg("repl:'%s'", repl);
6841                         for (loc = (char*)repl; *loc; loc++) {
6842                                 char *restart_detect = stackblock();
6843                                 if (quotes && *loc == '\\') {
6844                                         STPUTC(CTLESC, expdest);
6845                                         len++;
6846                                 }
6847                                 STPUTC(*loc, expdest);
6848                                 if (stackblock() != restart_detect)
6849                                         goto restart;
6850                                 len++;
6851                         }
6852
6853                         if (subtype == VSREPLACE) {
6854                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6855                                 while (*idx) {
6856                                         char *restart_detect = stackblock();
6857                                         STPUTC(*idx, expdest);
6858                                         if (stackblock() != restart_detect)
6859                                                 goto restart;
6860                                         len++;
6861                                         idx++;
6862                                 }
6863                                 break;
6864                         }
6865                 }
6866
6867                 /* We've put the replaced text into a buffer at workloc, now
6868                  * move it to the right place and adjust the stack.
6869                  */
6870                 STPUTC('\0', expdest);
6871                 startp = (char *)stackblock() + startloc;
6872                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6873                 //bb_error_msg("startp:'%s'", startp);
6874                 amount = expdest - (startp + len);
6875                 STADJUST(-amount, expdest);
6876                 return startp;
6877         }
6878 #endif /* BASH_PATTERN_SUBST */
6879
6880         subtype -= VSTRIMRIGHT;
6881 #if DEBUG
6882         if (subtype < 0 || subtype > 7)
6883                 abort();
6884 #endif
6885         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6886         zero = subtype >> 1;
6887         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6888         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6889
6890         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6891         if (loc) {
6892                 if (zero) {
6893                         memmove(startp, loc, str - loc);
6894                         loc = startp + (str - loc) - 1;
6895                 }
6896                 *loc = '\0';
6897                 amount = loc - expdest;
6898                 STADJUST(amount, expdest);
6899         }
6900         return loc;
6901 }
6902
6903 /*
6904  * Add the value of a specialized variable to the stack string.
6905  * name parameter (examples):
6906  * ash -c 'echo $1'      name:'1='
6907  * ash -c 'echo $qwe'    name:'qwe='
6908  * ash -c 'echo $$'      name:'$='
6909  * ash -c 'echo ${$}'    name:'$='
6910  * ash -c 'echo ${$##q}' name:'$=q'
6911  * ash -c 'echo ${#$}'   name:'$='
6912  * note: examples with bad shell syntax:
6913  * ash -c 'echo ${#$1}'  name:'$=1'
6914  * ash -c 'echo ${#1#}'  name:'1=#'
6915  */
6916 static NOINLINE ssize_t
6917 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6918 {
6919         const char *p;
6920         int num;
6921         int i;
6922         ssize_t len = 0;
6923         int sep;
6924         int quoted = *quotedp;
6925         int subtype = varflags & VSTYPE;
6926         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6927         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6928         int syntax;
6929
6930         sep = (flags & EXP_FULL) << CHAR_BIT;
6931         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6932
6933         switch (*name) {
6934         case '$':
6935                 num = rootpid;
6936                 goto numvar;
6937         case '?':
6938                 num = exitstatus;
6939                 goto numvar;
6940         case '#':
6941                 num = shellparam.nparam;
6942                 goto numvar;
6943         case '!':
6944                 num = backgndpid;
6945                 if (num == 0)
6946                         return -1;
6947  numvar:
6948                 len = cvtnum(num);
6949                 goto check_1char_name;
6950         case '-':
6951                 expdest = makestrspace(NOPTS, expdest);
6952                 for (i = NOPTS - 1; i >= 0; i--) {
6953                         if (optlist[i]) {
6954                                 USTPUTC(optletters(i), expdest);
6955                                 len++;
6956                         }
6957                 }
6958  check_1char_name:
6959 #if 0
6960                 /* handles cases similar to ${#$1} */
6961                 if (name[2] != '\0')
6962                         raise_error_syntax("bad substitution");
6963 #endif
6964                 break;
6965         case '@':
6966                 if (quoted && sep)
6967                         goto param;
6968                 /* fall through */
6969         case '*': {
6970                 char **ap;
6971                 char sepc;
6972
6973                 if (quoted)
6974                         sep = 0;
6975                 sep |= ifsset() ? ifsval()[0] : ' ';
6976  param:
6977                 sepc = sep;
6978                 *quotedp = !sepc;
6979                 ap = shellparam.p;
6980                 if (!ap)
6981                         return -1;
6982                 while ((p = *ap++) != NULL) {
6983                         len += strtodest(p, syntax, quotes);
6984
6985                         if (*ap && sep) {
6986                                 len++;
6987                                 memtodest(&sepc, 1, syntax, quotes);
6988                         }
6989                 }
6990                 break;
6991         } /* case '*' */
6992         case '0':
6993         case '1':
6994         case '2':
6995         case '3':
6996         case '4':
6997         case '5':
6998         case '6':
6999         case '7':
7000         case '8':
7001         case '9':
7002                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7003                 if (num < 0 || num > shellparam.nparam)
7004                         return -1;
7005                 p = num ? shellparam.p[num - 1] : arg0;
7006                 goto value;
7007         default:
7008                 /* NB: name has form "VAR=..." */
7009
7010                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
7011                  * which should be considered before we check variables. */
7012                 if (var_str_list) {
7013                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
7014                         p = NULL;
7015                         do {
7016                                 char *str, *eq;
7017                                 str = var_str_list->text;
7018                                 eq = strchr(str, '=');
7019                                 if (!eq) /* stop at first non-assignment */
7020                                         break;
7021                                 eq++;
7022                                 if (name_len == (unsigned)(eq - str)
7023                                  && strncmp(str, name, name_len) == 0
7024                                 ) {
7025                                         p = eq;
7026                                         /* goto value; - WRONG! */
7027                                         /* think "A=1 A=2 B=$A" */
7028                                 }
7029                                 var_str_list = var_str_list->next;
7030                         } while (var_str_list);
7031                         if (p)
7032                                 goto value;
7033                 }
7034                 p = lookupvar(name);
7035  value:
7036                 if (!p)
7037                         return -1;
7038
7039                 len = strtodest(p, syntax, quotes);
7040 #if ENABLE_UNICODE_SUPPORT
7041                 if (subtype == VSLENGTH && len > 0) {
7042                         reinit_unicode_for_ash();
7043                         if (unicode_status == UNICODE_ON) {
7044                                 STADJUST(-len, expdest);
7045                                 discard = 0;
7046                                 len = unicode_strlen(p);
7047                         }
7048                 }
7049 #endif
7050                 break;
7051         }
7052
7053         if (discard)
7054                 STADJUST(-len, expdest);
7055         return len;
7056 }
7057
7058 /*
7059  * Expand a variable, and return a pointer to the next character in the
7060  * input string.
7061  */
7062 static char *
7063 evalvar(char *p, int flag, struct strlist *var_str_list)
7064 {
7065         char varflags;
7066         char subtype;
7067         int quoted;
7068         char easy;
7069         char *var;
7070         int patloc;
7071         int startloc;
7072         ssize_t varlen;
7073
7074         varflags = (unsigned char) *p++;
7075         subtype = varflags & VSTYPE;
7076
7077         if (!subtype)
7078                 raise_error_syntax("bad substitution");
7079
7080         quoted = flag & EXP_QUOTED;
7081         var = p;
7082         easy = (!quoted || (*var == '@' && shellparam.nparam));
7083         startloc = expdest - (char *)stackblock();
7084         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7085
7086  again:
7087         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7088         if (varflags & VSNUL)
7089                 varlen--;
7090
7091         if (subtype == VSPLUS) {
7092                 varlen = -1 - varlen;
7093                 goto vsplus;
7094         }
7095
7096         if (subtype == VSMINUS) {
7097  vsplus:
7098                 if (varlen < 0) {
7099                         argstr(
7100                                 p,
7101                                 flag | EXP_TILDE | EXP_WORD,
7102                                 var_str_list
7103                         );
7104                         goto end;
7105                 }
7106                 goto record;
7107         }
7108
7109         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7110                 if (varlen >= 0)
7111                         goto record;
7112
7113                 subevalvar(p, var, 0, subtype, startloc, varflags,
7114                            flag & ~QUOTES_ESC, var_str_list);
7115                 varflags &= ~VSNUL;
7116                 /*
7117                  * Remove any recorded regions beyond
7118                  * start of variable
7119                  */
7120                 removerecordregions(startloc);
7121                 goto again;
7122         }
7123
7124         if (varlen < 0 && uflag)
7125                 varunset(p, var, 0, 0);
7126
7127         if (subtype == VSLENGTH) {
7128                 cvtnum(varlen > 0 ? varlen : 0);
7129                 goto record;
7130         }
7131
7132         if (subtype == VSNORMAL) {
7133  record:
7134                 if (!easy)
7135                         goto end;
7136                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7137                 goto end;
7138         }
7139
7140 #if DEBUG
7141         switch (subtype) {
7142         case VSTRIMLEFT:
7143         case VSTRIMLEFTMAX:
7144         case VSTRIMRIGHT:
7145         case VSTRIMRIGHTMAX:
7146 #if BASH_SUBSTR
7147         case VSSUBSTR:
7148 #endif
7149 #if BASH_PATTERN_SUBST
7150         case VSREPLACE:
7151         case VSREPLACEALL:
7152 #endif
7153                 break;
7154         default:
7155                 abort();
7156         }
7157 #endif
7158
7159         if (varlen >= 0) {
7160                 /*
7161                  * Terminate the string and start recording the pattern
7162                  * right after it
7163                  */
7164                 STPUTC('\0', expdest);
7165                 patloc = expdest - (char *)stackblock();
7166                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7167                                 startloc, varflags, flag, var_str_list)) {
7168                         int amount = expdest - (
7169                                 (char *)stackblock() + patloc - 1
7170                         );
7171                         STADJUST(-amount, expdest);
7172                 }
7173                 /* Remove any recorded regions beyond start of variable */
7174                 removerecordregions(startloc);
7175                 goto record;
7176         }
7177
7178  end:
7179         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7180                 int nesting = 1;
7181                 for (;;) {
7182                         unsigned char c = *p++;
7183                         if (c == CTLESC)
7184                                 p++;
7185                         else if (c == CTLBACKQ) {
7186                                 if (varlen >= 0)
7187                                         argbackq = argbackq->next;
7188                         } else if (c == CTLVAR) {
7189                                 if ((*p++ & VSTYPE) != VSNORMAL)
7190                                         nesting++;
7191                         } else if (c == CTLENDVAR) {
7192                                 if (--nesting == 0)
7193                                         break;
7194                         }
7195                 }
7196         }
7197         return p;
7198 }
7199
7200 /*
7201  * Add a file name to the list.
7202  */
7203 static void
7204 addfname(const char *name)
7205 {
7206         struct strlist *sp;
7207
7208         sp = stzalloc(sizeof(*sp));
7209         sp->text = sstrdup(name);
7210         *exparg.lastp = sp;
7211         exparg.lastp = &sp->next;
7212 }
7213
7214 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7215 static int
7216 hasmeta(const char *p)
7217 {
7218         static const char chars[] ALIGN1 = {
7219                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7220         };
7221
7222         for (;;) {
7223                 p = strpbrk(p, chars);
7224                 if (!p)
7225                         break;
7226                 switch ((unsigned char) *p) {
7227                 case CTLQUOTEMARK:
7228                         for (;;) {
7229                                 p++;
7230                                 if (*p == CTLQUOTEMARK)
7231                                         break;
7232                                 if (*p == CTLESC)
7233                                         p++;
7234                                 if (*p == '\0') /* huh? */
7235                                         return 0;
7236                         }
7237                         break;
7238                 case '\\':
7239                 case CTLESC:
7240                         p++;
7241                         if (*p == '\0')
7242                                 return 0;
7243                         break;
7244                 case '[':
7245                         if (!strchr(p + 1, ']')) {
7246                                 /* It's not a properly closed [] pattern,
7247                                  * but other metas may follow. Continue checking.
7248                                  * my[file* _is_ globbed by bash
7249                                  * and matches filenames like "my[file1".
7250                                  */
7251                                 break;
7252                         }
7253                         /* fallthrough */
7254                 default:
7255                 /* case '*': */
7256                 /* case '?': */
7257                         return 1;
7258                 }
7259                 p++;
7260         }
7261
7262         return 0;
7263 }
7264
7265 /* If we want to use glob() from libc... */
7266 #if !ENABLE_ASH_INTERNAL_GLOB
7267
7268 /* Add the result of glob() to the list */
7269 static void
7270 addglob(const glob_t *pglob)
7271 {
7272         char **p = pglob->gl_pathv;
7273
7274         do {
7275                 addfname(*p);
7276         } while (*++p);
7277 }
7278 static void
7279 expandmeta(struct strlist *str /*, int flag*/)
7280 {
7281         /* TODO - EXP_REDIR */
7282
7283         while (str) {
7284                 char *p;
7285                 glob_t pglob;
7286                 int i;
7287
7288                 if (fflag)
7289                         goto nometa;
7290
7291                 if (!hasmeta(str->text))
7292                         goto nometa;
7293
7294                 INT_OFF;
7295                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7296 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7297 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7298 //
7299 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7300 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7301 // Which means you need to unescape the string, right? Not so fast:
7302 // if there _is_ a file named "file\?" (with backslash), it is returned
7303 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7304 // You DON'T KNOW by looking at the result whether you need to unescape it.
7305 //
7306 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7307 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7308 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7309 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7310 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7311 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7312                 i = glob(p, 0, NULL, &pglob);
7313                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7314                 if (p != str->text)
7315                         free(p);
7316                 switch (i) {
7317                 case 0:
7318 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7319                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7320                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7321                                 goto nometa2;
7322 #endif
7323                         addglob(&pglob);
7324                         globfree(&pglob);
7325                         INT_ON;
7326                         break;
7327                 case GLOB_NOMATCH:
7328  //nometa2:
7329                         globfree(&pglob);
7330                         INT_ON;
7331  nometa:
7332                         *exparg.lastp = str;
7333                         rmescapes(str->text, 0);
7334                         exparg.lastp = &str->next;
7335                         break;
7336                 default:        /* GLOB_NOSPACE */
7337                         globfree(&pglob);
7338                         INT_ON;
7339                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7340                 }
7341                 str = str->next;
7342         }
7343 }
7344
7345 #else
7346 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7347
7348 /*
7349  * Do metacharacter (i.e. *, ?, [...]) expansion.
7350  */
7351 static void
7352 expmeta(char *expdir, char *enddir, char *name)
7353 {
7354         char *p;
7355         const char *cp;
7356         char *start;
7357         char *endname;
7358         int metaflag;
7359         struct stat statb;
7360         DIR *dirp;
7361         struct dirent *dp;
7362         int atend;
7363         int matchdot;
7364         int esc;
7365
7366         metaflag = 0;
7367         start = name;
7368         for (p = name; esc = 0, *p; p += esc + 1) {
7369                 if (*p == '*' || *p == '?')
7370                         metaflag = 1;
7371                 else if (*p == '[') {
7372                         char *q = p + 1;
7373                         if (*q == '!')
7374                                 q++;
7375                         for (;;) {
7376                                 if (*q == '\\')
7377                                         q++;
7378                                 if (*q == '/' || *q == '\0')
7379                                         break;
7380                                 if (*++q == ']') {
7381                                         metaflag = 1;
7382                                         break;
7383                                 }
7384                         }
7385                 } else {
7386                         if (*p == '\\')
7387                                 esc++;
7388                         if (p[esc] == '/') {
7389                                 if (metaflag)
7390                                         break;
7391                                 start = p + esc + 1;
7392                         }
7393                 }
7394         }
7395         if (metaflag == 0) {    /* we've reached the end of the file name */
7396                 if (enddir != expdir)
7397                         metaflag++;
7398                 p = name;
7399                 do {
7400                         if (*p == '\\')
7401                                 p++;
7402                         *enddir++ = *p;
7403                 } while (*p++);
7404                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7405                         addfname(expdir);
7406                 return;
7407         }
7408         endname = p;
7409         if (name < start) {
7410                 p = name;
7411                 do {
7412                         if (*p == '\\')
7413                                 p++;
7414                         *enddir++ = *p++;
7415                 } while (p < start);
7416         }
7417         if (enddir == expdir) {
7418                 cp = ".";
7419         } else if (enddir == expdir + 1 && *expdir == '/') {
7420                 cp = "/";
7421         } else {
7422                 cp = expdir;
7423                 enddir[-1] = '\0';
7424         }
7425         dirp = opendir(cp);
7426         if (dirp == NULL)
7427                 return;
7428         if (enddir != expdir)
7429                 enddir[-1] = '/';
7430         if (*endname == 0) {
7431                 atend = 1;
7432         } else {
7433                 atend = 0;
7434                 *endname = '\0';
7435                 endname += esc + 1;
7436         }
7437         matchdot = 0;
7438         p = start;
7439         if (*p == '\\')
7440                 p++;
7441         if (*p == '.')
7442                 matchdot++;
7443         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7444                 if (dp->d_name[0] == '.' && !matchdot)
7445                         continue;
7446                 if (pmatch(start, dp->d_name)) {
7447                         if (atend) {
7448                                 strcpy(enddir, dp->d_name);
7449                                 addfname(expdir);
7450                         } else {
7451                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7452                                         continue;
7453                                 p[-1] = '/';
7454                                 expmeta(expdir, p, endname);
7455                         }
7456                 }
7457         }
7458         closedir(dirp);
7459         if (!atend)
7460                 endname[-esc - 1] = esc ? '\\' : '/';
7461 }
7462
7463 static struct strlist *
7464 msort(struct strlist *list, int len)
7465 {
7466         struct strlist *p, *q = NULL;
7467         struct strlist **lpp;
7468         int half;
7469         int n;
7470
7471         if (len <= 1)
7472                 return list;
7473         half = len >> 1;
7474         p = list;
7475         for (n = half; --n >= 0;) {
7476                 q = p;
7477                 p = p->next;
7478         }
7479         q->next = NULL;                 /* terminate first half of list */
7480         q = msort(list, half);          /* sort first half of list */
7481         p = msort(p, len - half);               /* sort second half */
7482         lpp = &list;
7483         for (;;) {
7484 #if ENABLE_LOCALE_SUPPORT
7485                 if (strcoll(p->text, q->text) < 0)
7486 #else
7487                 if (strcmp(p->text, q->text) < 0)
7488 #endif
7489                                                 {
7490                         *lpp = p;
7491                         lpp = &p->next;
7492                         p = *lpp;
7493                         if (p == NULL) {
7494                                 *lpp = q;
7495                                 break;
7496                         }
7497                 } else {
7498                         *lpp = q;
7499                         lpp = &q->next;
7500                         q = *lpp;
7501                         if (q == NULL) {
7502                                 *lpp = p;
7503                                 break;
7504                         }
7505                 }
7506         }
7507         return list;
7508 }
7509
7510 /*
7511  * Sort the results of file name expansion.  It calculates the number of
7512  * strings to sort and then calls msort (short for merge sort) to do the
7513  * work.
7514  */
7515 static struct strlist *
7516 expsort(struct strlist *str)
7517 {
7518         int len;
7519         struct strlist *sp;
7520
7521         len = 0;
7522         for (sp = str; sp; sp = sp->next)
7523                 len++;
7524         return msort(str, len);
7525 }
7526
7527 static void
7528 expandmeta(struct strlist *str /*, int flag*/)
7529 {
7530         /* TODO - EXP_REDIR */
7531
7532         while (str) {
7533                 char *expdir;
7534                 struct strlist **savelastp;
7535                 struct strlist *sp;
7536                 char *p;
7537
7538                 if (fflag)
7539                         goto nometa;
7540                 if (!hasmeta(str->text))
7541                         goto nometa;
7542                 savelastp = exparg.lastp;
7543
7544                 INT_OFF;
7545                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7546                 {
7547                         int i = strlen(str->text);
7548 //BUGGY estimation of how long expanded name can be
7549                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7550                 }
7551                 expmeta(expdir, expdir, p);
7552                 free(expdir);
7553                 if (p != str->text)
7554                         free(p);
7555                 INT_ON;
7556                 if (exparg.lastp == savelastp) {
7557                         /*
7558                          * no matches
7559                          */
7560  nometa:
7561                         *exparg.lastp = str;
7562                         rmescapes(str->text, 0);
7563                         exparg.lastp = &str->next;
7564                 } else {
7565                         *exparg.lastp = NULL;
7566                         *savelastp = sp = expsort(*savelastp);
7567                         while (sp->next != NULL)
7568                                 sp = sp->next;
7569                         exparg.lastp = &sp->next;
7570                 }
7571                 str = str->next;
7572         }
7573 }
7574 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7575
7576 /*
7577  * Perform variable substitution and command substitution on an argument,
7578  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7579  * perform splitting and file name expansion.  When arglist is NULL, perform
7580  * here document expansion.
7581  */
7582 static void
7583 expandarg(union node *arg, struct arglist *arglist, int flag)
7584 {
7585         struct strlist *sp;
7586         char *p;
7587
7588         argbackq = arg->narg.backquote;
7589         STARTSTACKSTR(expdest);
7590         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7591         argstr(arg->narg.text, flag,
7592                         /* var_str_list: */ arglist ? arglist->list : NULL);
7593         p = _STPUTC('\0', expdest);
7594         expdest = p - 1;
7595         if (arglist == NULL) {
7596                 /* here document expanded */
7597                 goto out;
7598         }
7599         p = grabstackstr(p);
7600         TRACE(("expandarg: p:'%s'\n", p));
7601         exparg.lastp = &exparg.list;
7602         /*
7603          * TODO - EXP_REDIR
7604          */
7605         if (flag & EXP_FULL) {
7606                 ifsbreakup(p, &exparg);
7607                 *exparg.lastp = NULL;
7608                 exparg.lastp = &exparg.list;
7609                 expandmeta(exparg.list /*, flag*/);
7610         } else {
7611                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7612                         rmescapes(p, 0);
7613                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7614                 }
7615                 sp = stzalloc(sizeof(*sp));
7616                 sp->text = p;
7617                 *exparg.lastp = sp;
7618                 exparg.lastp = &sp->next;
7619         }
7620         *exparg.lastp = NULL;
7621         if (exparg.list) {
7622                 *arglist->lastp = exparg.list;
7623                 arglist->lastp = exparg.lastp;
7624         }
7625
7626  out:
7627         ifsfree();
7628 }
7629
7630 /*
7631  * Expand shell variables and backquotes inside a here document.
7632  */
7633 static void
7634 expandhere(union node *arg, int fd)
7635 {
7636         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7637         full_write(fd, stackblock(), expdest - (char *)stackblock());
7638 }
7639
7640 /*
7641  * Returns true if the pattern matches the string.
7642  */
7643 static int
7644 patmatch(char *pattern, const char *string)
7645 {
7646         char *p = preglob(pattern, 0);
7647         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7648         return pmatch(p, string);
7649 }
7650
7651 /*
7652  * See if a pattern matches in a case statement.
7653  */
7654 static int
7655 casematch(union node *pattern, char *val)
7656 {
7657         struct stackmark smark;
7658         int result;
7659
7660         setstackmark(&smark);
7661         argbackq = pattern->narg.backquote;
7662         STARTSTACKSTR(expdest);
7663         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7664                         /* var_str_list: */ NULL);
7665         STACKSTRNUL(expdest);
7666         ifsfree();
7667         result = patmatch(stackblock(), val);
7668         popstackmark(&smark);
7669         return result;
7670 }
7671
7672
7673 /* ============ find_command */
7674
7675 struct builtincmd {
7676         const char *name;
7677         int (*builtin)(int, char **) FAST_FUNC;
7678         /* unsigned flags; */
7679 };
7680 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7681 /* "regular" builtins always take precedence over commands,
7682  * regardless of PATH=....%builtin... position */
7683 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7684 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7685
7686 struct cmdentry {
7687         smallint cmdtype;       /* CMDxxx */
7688         union param {
7689                 int index;
7690                 /* index >= 0 for commands without path (slashes) */
7691                 /* (TODO: what exactly does the value mean? PATH position?) */
7692                 /* index == -1 for commands with slashes */
7693                 /* index == (-2 - applet_no) for NOFORK applets */
7694                 const struct builtincmd *cmd;
7695                 struct funcnode *func;
7696         } u;
7697 };
7698 /* values of cmdtype */
7699 #define CMDUNKNOWN      -1      /* no entry in table for command */
7700 #define CMDNORMAL       0       /* command is an executable program */
7701 #define CMDFUNCTION     1       /* command is a shell function */
7702 #define CMDBUILTIN      2       /* command is a shell builtin */
7703
7704 /* action to find_command() */
7705 #define DO_ERR          0x01    /* prints errors */
7706 #define DO_ABS          0x02    /* checks absolute paths */
7707 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7708 #define DO_ALTPATH      0x08    /* using alternate path */
7709 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7710
7711 static void find_command(char *, struct cmdentry *, int, const char *);
7712
7713
7714 /* ============ Hashing commands */
7715
7716 /*
7717  * When commands are first encountered, they are entered in a hash table.
7718  * This ensures that a full path search will not have to be done for them
7719  * on each invocation.
7720  *
7721  * We should investigate converting to a linear search, even though that
7722  * would make the command name "hash" a misnomer.
7723  */
7724
7725 struct tblentry {
7726         struct tblentry *next;  /* next entry in hash chain */
7727         union param param;      /* definition of builtin function */
7728         smallint cmdtype;       /* CMDxxx */
7729         char rehash;            /* if set, cd done since entry created */
7730         char cmdname[1];        /* name of command */
7731 };
7732
7733 static struct tblentry **cmdtable;
7734 #define INIT_G_cmdtable() do { \
7735         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7736 } while (0)
7737
7738 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7739
7740
7741 static void
7742 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7743 {
7744 #if ENABLE_FEATURE_SH_STANDALONE
7745         if (applet_no >= 0) {
7746                 if (APPLET_IS_NOEXEC(applet_no)) {
7747                         clearenv();
7748                         while (*envp)
7749                                 putenv(*envp++);
7750                         run_applet_no_and_exit(applet_no, cmd, argv);
7751                 }
7752                 /* re-exec ourselves with the new arguments */
7753                 execve(bb_busybox_exec_path, argv, envp);
7754                 /* If they called chroot or otherwise made the binary no longer
7755                  * executable, fall through */
7756         }
7757 #endif
7758
7759  repeat:
7760 #ifdef SYSV
7761         do {
7762                 execve(cmd, argv, envp);
7763         } while (errno == EINTR);
7764 #else
7765         execve(cmd, argv, envp);
7766 #endif
7767         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7768                 /* Run "cmd" as a shell script:
7769                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7770                  * "If the execve() function fails with ENOEXEC, the shell
7771                  * shall execute a command equivalent to having a shell invoked
7772                  * with the command name as its first operand,
7773                  * with any remaining arguments passed to the new shell"
7774                  *
7775                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7776                  * just call ourselves.
7777                  *
7778                  * Note that bash reads ~80 chars of the file, and if it sees
7779                  * a zero byte before it sees newline, it doesn't try to
7780                  * interpret it, but fails with "cannot execute binary file"
7781                  * message and exit code 126. For one, this prevents attempts
7782                  * to interpret foreign ELF binaries as shell scripts.
7783                  */
7784                 argv[0] = cmd;
7785                 cmd = (char*) bb_busybox_exec_path;
7786                 /* NB: this is only possible because all callers of shellexec()
7787                  * ensure that the argv[-1] slot exists!
7788                  */
7789                 argv--;
7790                 argv[0] = (char*) "ash";
7791                 goto repeat;
7792         }
7793 }
7794
7795 /*
7796  * Exec a program.  Never returns.  If you change this routine, you may
7797  * have to change the find_command routine as well.
7798  * argv[-1] must exist and be writable! See tryexec() for why.
7799  */
7800 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7801 static void shellexec(char *prog, char **argv, const char *path, int idx)
7802 {
7803         char *cmdname;
7804         int e;
7805         char **envp;
7806         int exerrno;
7807         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7808
7809         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7810         if (strchr(prog, '/') != NULL
7811 #if ENABLE_FEATURE_SH_STANDALONE
7812          || (applet_no = find_applet_by_name(prog)) >= 0
7813 #endif
7814         ) {
7815                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7816                 if (applet_no >= 0) {
7817                         /* We tried execing ourself, but it didn't work.
7818                          * Maybe /proc/self/exe doesn't exist?
7819                          * Try $PATH search.
7820                          */
7821                         goto try_PATH;
7822                 }
7823                 e = errno;
7824         } else {
7825  try_PATH:
7826                 e = ENOENT;
7827                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7828                         if (--idx < 0 && pathopt == NULL) {
7829                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7830                                 if (errno != ENOENT && errno != ENOTDIR)
7831                                         e = errno;
7832                         }
7833                         stunalloc(cmdname);
7834                 }
7835         }
7836
7837         /* Map to POSIX errors */
7838         switch (e) {
7839         case EACCES:
7840                 exerrno = 126;
7841                 break;
7842         case ENOENT:
7843                 exerrno = 127;
7844                 break;
7845         default:
7846                 exerrno = 2;
7847                 break;
7848         }
7849         exitstatus = exerrno;
7850         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7851                 prog, e, suppress_int));
7852         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7853         /* NOTREACHED */
7854 }
7855
7856 static void
7857 printentry(struct tblentry *cmdp)
7858 {
7859         int idx;
7860         const char *path;
7861         char *name;
7862
7863         idx = cmdp->param.index;
7864         path = pathval();
7865         do {
7866                 name = path_advance(&path, cmdp->cmdname);
7867                 stunalloc(name);
7868         } while (--idx >= 0);
7869         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7870 }
7871
7872 /*
7873  * Clear out command entries.  The argument specifies the first entry in
7874  * PATH which has changed.
7875  */
7876 static void
7877 clearcmdentry(int firstchange)
7878 {
7879         struct tblentry **tblp;
7880         struct tblentry **pp;
7881         struct tblentry *cmdp;
7882
7883         INT_OFF;
7884         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7885                 pp = tblp;
7886                 while ((cmdp = *pp) != NULL) {
7887                         if ((cmdp->cmdtype == CMDNORMAL &&
7888                              cmdp->param.index >= firstchange)
7889                          || (cmdp->cmdtype == CMDBUILTIN &&
7890                              builtinloc >= firstchange)
7891                         ) {
7892                                 *pp = cmdp->next;
7893                                 free(cmdp);
7894                         } else {
7895                                 pp = &cmdp->next;
7896                         }
7897                 }
7898         }
7899         INT_ON;
7900 }
7901
7902 /*
7903  * Locate a command in the command hash table.  If "add" is nonzero,
7904  * add the command to the table if it is not already present.  The
7905  * variable "lastcmdentry" is set to point to the address of the link
7906  * pointing to the entry, so that delete_cmd_entry can delete the
7907  * entry.
7908  *
7909  * Interrupts must be off if called with add != 0.
7910  */
7911 static struct tblentry **lastcmdentry;
7912
7913 static struct tblentry *
7914 cmdlookup(const char *name, int add)
7915 {
7916         unsigned int hashval;
7917         const char *p;
7918         struct tblentry *cmdp;
7919         struct tblentry **pp;
7920
7921         p = name;
7922         hashval = (unsigned char)*p << 4;
7923         while (*p)
7924                 hashval += (unsigned char)*p++;
7925         hashval &= 0x7FFF;
7926         pp = &cmdtable[hashval % CMDTABLESIZE];
7927         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7928                 if (strcmp(cmdp->cmdname, name) == 0)
7929                         break;
7930                 pp = &cmdp->next;
7931         }
7932         if (add && cmdp == NULL) {
7933                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7934                                 + strlen(name)
7935                                 /* + 1 - already done because
7936                                  * tblentry::cmdname is char[1] */);
7937                 /*cmdp->next = NULL; - ckzalloc did it */
7938                 cmdp->cmdtype = CMDUNKNOWN;
7939                 strcpy(cmdp->cmdname, name);
7940         }
7941         lastcmdentry = pp;
7942         return cmdp;
7943 }
7944
7945 /*
7946  * Delete the command entry returned on the last lookup.
7947  */
7948 static void
7949 delete_cmd_entry(void)
7950 {
7951         struct tblentry *cmdp;
7952
7953         INT_OFF;
7954         cmdp = *lastcmdentry;
7955         *lastcmdentry = cmdp->next;
7956         if (cmdp->cmdtype == CMDFUNCTION)
7957                 freefunc(cmdp->param.func);
7958         free(cmdp);
7959         INT_ON;
7960 }
7961
7962 /*
7963  * Add a new command entry, replacing any existing command entry for
7964  * the same name - except special builtins.
7965  */
7966 static void
7967 addcmdentry(char *name, struct cmdentry *entry)
7968 {
7969         struct tblentry *cmdp;
7970
7971         cmdp = cmdlookup(name, 1);
7972         if (cmdp->cmdtype == CMDFUNCTION) {
7973                 freefunc(cmdp->param.func);
7974         }
7975         cmdp->cmdtype = entry->cmdtype;
7976         cmdp->param = entry->u;
7977         cmdp->rehash = 0;
7978 }
7979
7980 static int FAST_FUNC
7981 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7982 {
7983         struct tblentry **pp;
7984         struct tblentry *cmdp;
7985         int c;
7986         struct cmdentry entry;
7987         char *name;
7988
7989         if (nextopt("r") != '\0') {
7990                 clearcmdentry(0);
7991                 return 0;
7992         }
7993
7994         if (*argptr == NULL) {
7995                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7996                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7997                                 if (cmdp->cmdtype == CMDNORMAL)
7998                                         printentry(cmdp);
7999                         }
8000                 }
8001                 return 0;
8002         }
8003
8004         c = 0;
8005         while ((name = *argptr) != NULL) {
8006                 cmdp = cmdlookup(name, 0);
8007                 if (cmdp != NULL
8008                  && (cmdp->cmdtype == CMDNORMAL
8009                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8010                 ) {
8011                         delete_cmd_entry();
8012                 }
8013                 find_command(name, &entry, DO_ERR, pathval());
8014                 if (entry.cmdtype == CMDUNKNOWN)
8015                         c = 1;
8016                 argptr++;
8017         }
8018         return c;
8019 }
8020
8021 /*
8022  * Called when a cd is done.  Marks all commands so the next time they
8023  * are executed they will be rehashed.
8024  */
8025 static void
8026 hashcd(void)
8027 {
8028         struct tblentry **pp;
8029         struct tblentry *cmdp;
8030
8031         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8032                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8033                         if (cmdp->cmdtype == CMDNORMAL
8034                          || (cmdp->cmdtype == CMDBUILTIN
8035                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8036                              && builtinloc > 0)
8037                         ) {
8038                                 cmdp->rehash = 1;
8039                         }
8040                 }
8041         }
8042 }
8043
8044 /*
8045  * Fix command hash table when PATH changed.
8046  * Called before PATH is changed.  The argument is the new value of PATH;
8047  * pathval() still returns the old value at this point.
8048  * Called with interrupts off.
8049  */
8050 static void FAST_FUNC
8051 changepath(const char *new)
8052 {
8053         const char *old;
8054         int firstchange;
8055         int idx;
8056         int idx_bltin;
8057
8058         old = pathval();
8059         firstchange = 9999;     /* assume no change */
8060         idx = 0;
8061         idx_bltin = -1;
8062         for (;;) {
8063                 if (*old != *new) {
8064                         firstchange = idx;
8065                         if ((*old == '\0' && *new == ':')
8066                          || (*old == ':' && *new == '\0')
8067                         ) {
8068                                 firstchange++;
8069                         }
8070                         old = new;      /* ignore subsequent differences */
8071                 }
8072                 if (*new == '\0')
8073                         break;
8074                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8075                         idx_bltin = idx;
8076                 if (*new == ':')
8077                         idx++;
8078                 new++;
8079                 old++;
8080         }
8081         if (builtinloc < 0 && idx_bltin >= 0)
8082                 builtinloc = idx_bltin;             /* zap builtins */
8083         if (builtinloc >= 0 && idx_bltin < 0)
8084                 firstchange = 0;
8085         clearcmdentry(firstchange);
8086         builtinloc = idx_bltin;
8087 }
8088 enum {
8089         TEOF,
8090         TNL,
8091         TREDIR,
8092         TWORD,
8093         TSEMI,
8094         TBACKGND,
8095         TAND,
8096         TOR,
8097         TPIPE,
8098         TLP,
8099         TRP,
8100         TENDCASE,
8101         TENDBQUOTE,
8102         TNOT,
8103         TCASE,
8104         TDO,
8105         TDONE,
8106         TELIF,
8107         TELSE,
8108         TESAC,
8109         TFI,
8110         TFOR,
8111 #if BASH_FUNCTION
8112         TFUNCTION,
8113 #endif
8114         TIF,
8115         TIN,
8116         TTHEN,
8117         TUNTIL,
8118         TWHILE,
8119         TBEGIN,
8120         TEND
8121 };
8122 typedef smallint token_id_t;
8123
8124 /* Nth bit indicates if token marks the end of a list */
8125 enum {
8126         tokendlist = 0
8127         /*  0 */ | (1u << TEOF)
8128         /*  1 */ | (0u << TNL)
8129         /*  2 */ | (0u << TREDIR)
8130         /*  3 */ | (0u << TWORD)
8131         /*  4 */ | (0u << TSEMI)
8132         /*  5 */ | (0u << TBACKGND)
8133         /*  6 */ | (0u << TAND)
8134         /*  7 */ | (0u << TOR)
8135         /*  8 */ | (0u << TPIPE)
8136         /*  9 */ | (0u << TLP)
8137         /* 10 */ | (1u << TRP)
8138         /* 11 */ | (1u << TENDCASE)
8139         /* 12 */ | (1u << TENDBQUOTE)
8140         /* 13 */ | (0u << TNOT)
8141         /* 14 */ | (0u << TCASE)
8142         /* 15 */ | (1u << TDO)
8143         /* 16 */ | (1u << TDONE)
8144         /* 17 */ | (1u << TELIF)
8145         /* 18 */ | (1u << TELSE)
8146         /* 19 */ | (1u << TESAC)
8147         /* 20 */ | (1u << TFI)
8148         /* 21 */ | (0u << TFOR)
8149 #if BASH_FUNCTION
8150         /* 22 */ | (0u << TFUNCTION)
8151 #endif
8152         /* 23 */ | (0u << TIF)
8153         /* 24 */ | (0u << TIN)
8154         /* 25 */ | (1u << TTHEN)
8155         /* 26 */ | (0u << TUNTIL)
8156         /* 27 */ | (0u << TWHILE)
8157         /* 28 */ | (0u << TBEGIN)
8158         /* 29 */ | (1u << TEND)
8159         , /* thus far 29 bits used */
8160 };
8161
8162 static const char *const tokname_array[] = {
8163         "end of file",
8164         "newline",
8165         "redirection",
8166         "word",
8167         ";",
8168         "&",
8169         "&&",
8170         "||",
8171         "|",
8172         "(",
8173         ")",
8174         ";;",
8175         "`",
8176 #define KWDOFFSET 13
8177         /* the following are keywords */
8178         "!",
8179         "case",
8180         "do",
8181         "done",
8182         "elif",
8183         "else",
8184         "esac",
8185         "fi",
8186         "for",
8187 #if BASH_FUNCTION
8188         "function",
8189 #endif
8190         "if",
8191         "in",
8192         "then",
8193         "until",
8194         "while",
8195         "{",
8196         "}",
8197 };
8198
8199 /* Wrapper around strcmp for qsort/bsearch/... */
8200 static int
8201 pstrcmp(const void *a, const void *b)
8202 {
8203         return strcmp((char*)a, *(char**)b);
8204 }
8205
8206 static const char *const *
8207 findkwd(const char *s)
8208 {
8209         return bsearch(s, tokname_array + KWDOFFSET,
8210                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8211                         sizeof(tokname_array[0]), pstrcmp);
8212 }
8213
8214 /*
8215  * Locate and print what a word is...
8216  */
8217 static int
8218 describe_command(char *command, const char *path, int describe_command_verbose)
8219 {
8220         struct cmdentry entry;
8221 #if ENABLE_ASH_ALIAS
8222         const struct alias *ap;
8223 #endif
8224
8225         path = path ? path : pathval();
8226
8227         if (describe_command_verbose) {
8228                 out1str(command);
8229         }
8230
8231         /* First look at the keywords */
8232         if (findkwd(command)) {
8233                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8234                 goto out;
8235         }
8236
8237 #if ENABLE_ASH_ALIAS
8238         /* Then look at the aliases */
8239         ap = lookupalias(command, 0);
8240         if (ap != NULL) {
8241                 if (!describe_command_verbose) {
8242                         out1str("alias ");
8243                         printalias(ap);
8244                         return 0;
8245                 }
8246                 out1fmt(" is an alias for %s", ap->val);
8247                 goto out;
8248         }
8249 #endif
8250         /* Brute force */
8251         find_command(command, &entry, DO_ABS, path);
8252
8253         switch (entry.cmdtype) {
8254         case CMDNORMAL: {
8255                 int j = entry.u.index;
8256                 char *p;
8257                 if (j < 0) {
8258                         p = command;
8259                 } else {
8260                         do {
8261                                 p = path_advance(&path, command);
8262                                 stunalloc(p);
8263                         } while (--j >= 0);
8264                 }
8265                 if (describe_command_verbose) {
8266                         out1fmt(" is %s", p);
8267                 } else {
8268                         out1str(p);
8269                 }
8270                 break;
8271         }
8272
8273         case CMDFUNCTION:
8274                 if (describe_command_verbose) {
8275                         out1str(" is a shell function");
8276                 } else {
8277                         out1str(command);
8278                 }
8279                 break;
8280
8281         case CMDBUILTIN:
8282                 if (describe_command_verbose) {
8283                         out1fmt(" is a %sshell builtin",
8284                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8285                                         "special " : nullstr
8286                         );
8287                 } else {
8288                         out1str(command);
8289                 }
8290                 break;
8291
8292         default:
8293                 if (describe_command_verbose) {
8294                         out1str(": not found\n");
8295                 }
8296                 return 127;
8297         }
8298  out:
8299         out1str("\n");
8300         return 0;
8301 }
8302
8303 static int FAST_FUNC
8304 typecmd(int argc UNUSED_PARAM, char **argv)
8305 {
8306         int i = 1;
8307         int err = 0;
8308         int verbose = 1;
8309
8310         /* type -p ... ? (we don't bother checking for 'p') */
8311         if (argv[1] && argv[1][0] == '-') {
8312                 i++;
8313                 verbose = 0;
8314         }
8315         while (argv[i]) {
8316                 err |= describe_command(argv[i++], NULL, verbose);
8317         }
8318         return err;
8319 }
8320
8321 #if ENABLE_ASH_CMDCMD
8322 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8323 static char **
8324 parse_command_args(char **argv, const char **path)
8325 {
8326         char *cp, c;
8327
8328         for (;;) {
8329                 cp = *++argv;
8330                 if (!cp)
8331                         return NULL;
8332                 if (*cp++ != '-')
8333                         break;
8334                 c = *cp++;
8335                 if (!c)
8336                         break;
8337                 if (c == '-' && !*cp) {
8338                         if (!*++argv)
8339                                 return NULL;
8340                         break;
8341                 }
8342                 do {
8343                         switch (c) {
8344                         case 'p':
8345                                 *path = bb_default_path;
8346                                 break;
8347                         default:
8348                                 /* run 'typecmd' for other options */
8349                                 return NULL;
8350                         }
8351                         c = *cp++;
8352                 } while (c);
8353         }
8354         return argv;
8355 }
8356
8357 static int FAST_FUNC
8358 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8359 {
8360         char *cmd;
8361         int c;
8362         enum {
8363                 VERIFY_BRIEF = 1,
8364                 VERIFY_VERBOSE = 2,
8365         } verify = 0;
8366         const char *path = NULL;
8367
8368         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8369          * never reaches this function.
8370          */
8371
8372         while ((c = nextopt("pvV")) != '\0')
8373                 if (c == 'V')
8374                         verify |= VERIFY_VERBOSE;
8375                 else if (c == 'v')
8376                         /*verify |= VERIFY_BRIEF*/;
8377 #if DEBUG
8378                 else if (c != 'p')
8379                         abort();
8380 #endif
8381                 else
8382                         path = bb_default_path;
8383
8384         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8385         cmd = *argptr;
8386         if (/*verify && */ cmd)
8387                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8388
8389         return 0;
8390 }
8391 #endif
8392
8393
8394 /*static int funcblocksize;     // size of structures in function */
8395 /*static int funcstringsize;    // size of strings in node */
8396 static void *funcblock;         /* block to allocate function from */
8397 static char *funcstring_end;    /* end of block to allocate strings from */
8398
8399 /* flags in argument to evaltree */
8400 #define EV_EXIT    01           /* exit after evaluating tree */
8401 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8402
8403 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8404         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8405         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8406         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8407         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8408         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8409         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8410         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8411         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8412         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8413         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8414         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8415         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8416         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8417         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8418         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8419         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8420         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8421 #if BASH_REDIR_OUTPUT
8422         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8423 #endif
8424         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8425         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8426         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8427         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8428         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8429         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8430         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8431         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8432         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8433 };
8434
8435 static int calcsize(int funcblocksize, union node *n);
8436
8437 static int
8438 sizenodelist(int funcblocksize, struct nodelist *lp)
8439 {
8440         while (lp) {
8441                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8442                 funcblocksize = calcsize(funcblocksize, lp->n);
8443                 lp = lp->next;
8444         }
8445         return funcblocksize;
8446 }
8447
8448 static int
8449 calcsize(int funcblocksize, union node *n)
8450 {
8451         if (n == NULL)
8452                 return funcblocksize;
8453         funcblocksize += nodesize[n->type];
8454         switch (n->type) {
8455         case NCMD:
8456                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8457                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8458                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8459                 break;
8460         case NPIPE:
8461                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8462                 break;
8463         case NREDIR:
8464         case NBACKGND:
8465         case NSUBSHELL:
8466                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8467                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8468                 break;
8469         case NAND:
8470         case NOR:
8471         case NSEMI:
8472         case NWHILE:
8473         case NUNTIL:
8474                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8475                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8476                 break;
8477         case NIF:
8478                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8479                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8480                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8481                 break;
8482         case NFOR:
8483                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8484                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8485                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8486                 break;
8487         case NCASE:
8488                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8489                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8490                 break;
8491         case NCLIST:
8492                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8493                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8494                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8495                 break;
8496         case NDEFUN:
8497         case NARG:
8498                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8499                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8500                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8501                 break;
8502         case NTO:
8503 #if BASH_REDIR_OUTPUT
8504         case NTO2:
8505 #endif
8506         case NCLOBBER:
8507         case NFROM:
8508         case NFROMTO:
8509         case NAPPEND:
8510                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8511                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8512                 break;
8513         case NTOFD:
8514         case NFROMFD:
8515                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8516                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8517         break;
8518         case NHERE:
8519         case NXHERE:
8520                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8521                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8522                 break;
8523         case NNOT:
8524                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8525                 break;
8526         };
8527         return funcblocksize;
8528 }
8529
8530 static char *
8531 nodeckstrdup(char *s)
8532 {
8533         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8534         return strcpy(funcstring_end, s);
8535 }
8536
8537 static union node *copynode(union node *);
8538
8539 static struct nodelist *
8540 copynodelist(struct nodelist *lp)
8541 {
8542         struct nodelist *start;
8543         struct nodelist **lpp;
8544
8545         lpp = &start;
8546         while (lp) {
8547                 *lpp = funcblock;
8548                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8549                 (*lpp)->n = copynode(lp->n);
8550                 lp = lp->next;
8551                 lpp = &(*lpp)->next;
8552         }
8553         *lpp = NULL;
8554         return start;
8555 }
8556
8557 static union node *
8558 copynode(union node *n)
8559 {
8560         union node *new;
8561
8562         if (n == NULL)
8563                 return NULL;
8564         new = funcblock;
8565         funcblock = (char *) funcblock + nodesize[n->type];
8566
8567         switch (n->type) {
8568         case NCMD:
8569                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8570                 new->ncmd.args = copynode(n->ncmd.args);
8571                 new->ncmd.assign = copynode(n->ncmd.assign);
8572                 break;
8573         case NPIPE:
8574                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8575                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8576                 break;
8577         case NREDIR:
8578         case NBACKGND:
8579         case NSUBSHELL:
8580                 new->nredir.redirect = copynode(n->nredir.redirect);
8581                 new->nredir.n = copynode(n->nredir.n);
8582                 break;
8583         case NAND:
8584         case NOR:
8585         case NSEMI:
8586         case NWHILE:
8587         case NUNTIL:
8588                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8589                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8590                 break;
8591         case NIF:
8592                 new->nif.elsepart = copynode(n->nif.elsepart);
8593                 new->nif.ifpart = copynode(n->nif.ifpart);
8594                 new->nif.test = copynode(n->nif.test);
8595                 break;
8596         case NFOR:
8597                 new->nfor.var = nodeckstrdup(n->nfor.var);
8598                 new->nfor.body = copynode(n->nfor.body);
8599                 new->nfor.args = copynode(n->nfor.args);
8600                 break;
8601         case NCASE:
8602                 new->ncase.cases = copynode(n->ncase.cases);
8603                 new->ncase.expr = copynode(n->ncase.expr);
8604                 break;
8605         case NCLIST:
8606                 new->nclist.body = copynode(n->nclist.body);
8607                 new->nclist.pattern = copynode(n->nclist.pattern);
8608                 new->nclist.next = copynode(n->nclist.next);
8609                 break;
8610         case NDEFUN:
8611         case NARG:
8612                 new->narg.backquote = copynodelist(n->narg.backquote);
8613                 new->narg.text = nodeckstrdup(n->narg.text);
8614                 new->narg.next = copynode(n->narg.next);
8615                 break;
8616         case NTO:
8617 #if BASH_REDIR_OUTPUT
8618         case NTO2:
8619 #endif
8620         case NCLOBBER:
8621         case NFROM:
8622         case NFROMTO:
8623         case NAPPEND:
8624                 new->nfile.fname = copynode(n->nfile.fname);
8625                 new->nfile.fd = n->nfile.fd;
8626                 new->nfile.next = copynode(n->nfile.next);
8627                 break;
8628         case NTOFD:
8629         case NFROMFD:
8630                 new->ndup.vname = copynode(n->ndup.vname);
8631                 new->ndup.dupfd = n->ndup.dupfd;
8632                 new->ndup.fd = n->ndup.fd;
8633                 new->ndup.next = copynode(n->ndup.next);
8634                 break;
8635         case NHERE:
8636         case NXHERE:
8637                 new->nhere.doc = copynode(n->nhere.doc);
8638                 new->nhere.fd = n->nhere.fd;
8639                 new->nhere.next = copynode(n->nhere.next);
8640                 break;
8641         case NNOT:
8642                 new->nnot.com = copynode(n->nnot.com);
8643                 break;
8644         };
8645         new->type = n->type;
8646         return new;
8647 }
8648
8649 /*
8650  * Make a copy of a parse tree.
8651  */
8652 static struct funcnode *
8653 copyfunc(union node *n)
8654 {
8655         struct funcnode *f;
8656         size_t blocksize;
8657
8658         /*funcstringsize = 0;*/
8659         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8660         f = ckzalloc(blocksize /* + funcstringsize */);
8661         funcblock = (char *) f + offsetof(struct funcnode, n);
8662         funcstring_end = (char *) f + blocksize;
8663         copynode(n);
8664         /* f->count = 0; - ckzalloc did it */
8665         return f;
8666 }
8667
8668 /*
8669  * Define a shell function.
8670  */
8671 static void
8672 defun(union node *func)
8673 {
8674         struct cmdentry entry;
8675
8676         INT_OFF;
8677         entry.cmdtype = CMDFUNCTION;
8678         entry.u.func = copyfunc(func);
8679         addcmdentry(func->narg.text, &entry);
8680         INT_ON;
8681 }
8682
8683 /* Reasons for skipping commands (see comment on breakcmd routine) */
8684 #define SKIPBREAK      (1 << 0)
8685 #define SKIPCONT       (1 << 1)
8686 #define SKIPFUNC       (1 << 2)
8687 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8688 static int skipcount;           /* number of levels to skip */
8689 static int funcnest;            /* depth of function calls */
8690 static int loopnest;            /* current loop nesting level */
8691
8692 /* Forward decl way out to parsing code - dotrap needs it */
8693 static int evalstring(char *s, int flags);
8694
8695 /* Called to execute a trap.
8696  * Single callsite - at the end of evaltree().
8697  * If we return non-zero, evaltree raises EXEXIT exception.
8698  *
8699  * Perhaps we should avoid entering new trap handlers
8700  * while we are executing a trap handler. [is it a TODO?]
8701  */
8702 static void
8703 dotrap(void)
8704 {
8705         uint8_t *g;
8706         int sig;
8707         uint8_t last_status;
8708
8709         if (!pending_sig)
8710                 return;
8711
8712         last_status = exitstatus;
8713         pending_sig = 0;
8714         barrier();
8715
8716         TRACE(("dotrap entered\n"));
8717         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8718                 char *p;
8719
8720                 if (!*g)
8721                         continue;
8722
8723                 if (evalskip) {
8724                         pending_sig = sig;
8725                         break;
8726                 }
8727
8728                 p = trap[sig];
8729                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8730                  * don't upset it by resetting gotsig[SIGINT-1] */
8731                 if (sig == SIGINT && !p)
8732                         continue;
8733
8734                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8735                 *g = 0;
8736                 if (!p)
8737                         continue;
8738                 evalstring(p, 0);
8739         }
8740         exitstatus = last_status;
8741         TRACE(("dotrap returns\n"));
8742 }
8743
8744 /* forward declarations - evaluation is fairly recursive business... */
8745 static int evalloop(union node *, int);
8746 static int evalfor(union node *, int);
8747 static int evalcase(union node *, int);
8748 static int evalsubshell(union node *, int);
8749 static void expredir(union node *);
8750 static int evalpipe(union node *, int);
8751 static int evalcommand(union node *, int);
8752 static int evalbltin(const struct builtincmd *, int, char **, int);
8753 static void prehash(union node *);
8754
8755 /*
8756  * Evaluate a parse tree.  The value is left in the global variable
8757  * exitstatus.
8758  */
8759 static int
8760 evaltree(union node *n, int flags)
8761 {
8762         int checkexit = 0;
8763         int (*evalfn)(union node *, int);
8764         int status = 0;
8765
8766         if (n == NULL) {
8767                 TRACE(("evaltree(NULL) called\n"));
8768                 goto out;
8769         }
8770         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8771
8772         dotrap();
8773
8774         switch (n->type) {
8775         default:
8776 #if DEBUG
8777                 out1fmt("Node type = %d\n", n->type);
8778                 fflush_all();
8779                 break;
8780 #endif
8781         case NNOT:
8782                 status = !evaltree(n->nnot.com, EV_TESTED);
8783                 goto setstatus;
8784         case NREDIR:
8785                 expredir(n->nredir.redirect);
8786                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8787                 if (!status) {
8788                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8789                 }
8790                 if (n->nredir.redirect)
8791                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8792                 goto setstatus;
8793         case NCMD:
8794                 evalfn = evalcommand;
8795  checkexit:
8796                 if (eflag && !(flags & EV_TESTED))
8797                         checkexit = ~0;
8798                 goto calleval;
8799         case NFOR:
8800                 evalfn = evalfor;
8801                 goto calleval;
8802         case NWHILE:
8803         case NUNTIL:
8804                 evalfn = evalloop;
8805                 goto calleval;
8806         case NSUBSHELL:
8807         case NBACKGND:
8808                 evalfn = evalsubshell;
8809                 goto checkexit;
8810         case NPIPE:
8811                 evalfn = evalpipe;
8812                 goto checkexit;
8813         case NCASE:
8814                 evalfn = evalcase;
8815                 goto calleval;
8816         case NAND:
8817         case NOR:
8818         case NSEMI: {
8819
8820 #if NAND + 1 != NOR
8821 #error NAND + 1 != NOR
8822 #endif
8823 #if NOR + 1 != NSEMI
8824 #error NOR + 1 != NSEMI
8825 #endif
8826                 unsigned is_or = n->type - NAND;
8827                 status = evaltree(
8828                         n->nbinary.ch1,
8829                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8830                 );
8831                 if ((!status) == is_or || evalskip)
8832                         break;
8833                 n = n->nbinary.ch2;
8834  evaln:
8835                 evalfn = evaltree;
8836  calleval:
8837                 status = evalfn(n, flags);
8838                 goto setstatus;
8839         }
8840         case NIF:
8841                 status = evaltree(n->nif.test, EV_TESTED);
8842                 if (evalskip)
8843                         break;
8844                 if (!status) {
8845                         n = n->nif.ifpart;
8846                         goto evaln;
8847                 }
8848                 if (n->nif.elsepart) {
8849                         n = n->nif.elsepart;
8850                         goto evaln;
8851                 }
8852                 status = 0;
8853                 goto setstatus;
8854         case NDEFUN:
8855                 defun(n);
8856                 /* Not necessary. To test it:
8857                  * "false; f() { qwerty; }; echo $?" should print 0.
8858                  */
8859                 /* status = 0; */
8860  setstatus:
8861                 exitstatus = status;
8862                 break;
8863         }
8864  out:
8865         /* Order of checks below is important:
8866          * signal handlers trigger before exit caused by "set -e".
8867          */
8868         dotrap();
8869
8870         if (checkexit & status)
8871                 raise_exception(EXEXIT);
8872         if (flags & EV_EXIT)
8873                 raise_exception(EXEXIT);
8874
8875         TRACE(("leaving evaltree (no interrupts)\n"));
8876         return exitstatus;
8877 }
8878
8879 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8880 static
8881 #endif
8882 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8883
8884 static int
8885 skiploop(void)
8886 {
8887         int skip = evalskip;
8888
8889         switch (skip) {
8890         case 0:
8891                 break;
8892         case SKIPBREAK:
8893         case SKIPCONT:
8894                 if (--skipcount <= 0) {
8895                         evalskip = 0;
8896                         break;
8897                 }
8898                 skip = SKIPBREAK;
8899                 break;
8900         }
8901         return skip;
8902 }
8903
8904 static int
8905 evalloop(union node *n, int flags)
8906 {
8907         int skip;
8908         int status;
8909
8910         loopnest++;
8911         status = 0;
8912         flags &= EV_TESTED;
8913         do {
8914                 int i;
8915
8916                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8917                 skip = skiploop();
8918                 if (skip == SKIPFUNC)
8919                         status = i;
8920                 if (skip)
8921                         continue;
8922                 if (n->type != NWHILE)
8923                         i = !i;
8924                 if (i != 0)
8925                         break;
8926                 status = evaltree(n->nbinary.ch2, flags);
8927                 skip = skiploop();
8928         } while (!(skip & ~SKIPCONT));
8929         loopnest--;
8930
8931         return status;
8932 }
8933
8934 static int
8935 evalfor(union node *n, int flags)
8936 {
8937         struct arglist arglist;
8938         union node *argp;
8939         struct strlist *sp;
8940         struct stackmark smark;
8941         int status = 0;
8942
8943         setstackmark(&smark);
8944         arglist.list = NULL;
8945         arglist.lastp = &arglist.list;
8946         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8947                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8948         }
8949         *arglist.lastp = NULL;
8950
8951         loopnest++;
8952         flags &= EV_TESTED;
8953         for (sp = arglist.list; sp; sp = sp->next) {
8954                 setvar0(n->nfor.var, sp->text);
8955                 status = evaltree(n->nfor.body, flags);
8956                 if (skiploop() & ~SKIPCONT)
8957                         break;
8958         }
8959         loopnest--;
8960         popstackmark(&smark);
8961
8962         return status;
8963 }
8964
8965 static int
8966 evalcase(union node *n, int flags)
8967 {
8968         union node *cp;
8969         union node *patp;
8970         struct arglist arglist;
8971         struct stackmark smark;
8972         int status = 0;
8973
8974         setstackmark(&smark);
8975         arglist.list = NULL;
8976         arglist.lastp = &arglist.list;
8977         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8978         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8979                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8980                         if (casematch(patp, arglist.list->text)) {
8981                                 /* Ensure body is non-empty as otherwise
8982                                  * EV_EXIT may prevent us from setting the
8983                                  * exit status.
8984                                  */
8985                                 if (evalskip == 0 && cp->nclist.body) {
8986                                         status = evaltree(cp->nclist.body, flags);
8987                                 }
8988                                 goto out;
8989                         }
8990                 }
8991         }
8992  out:
8993         popstackmark(&smark);
8994
8995         return status;
8996 }
8997
8998 /*
8999  * Kick off a subshell to evaluate a tree.
9000  */
9001 static int
9002 evalsubshell(union node *n, int flags)
9003 {
9004         struct job *jp;
9005         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9006         int status;
9007
9008         expredir(n->nredir.redirect);
9009         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9010                 goto nofork;
9011         INT_OFF;
9012         if (backgnd == FORK_FG)
9013                 get_tty_state();
9014         jp = makejob(/*n,*/ 1);
9015         if (forkshell(jp, n, backgnd) == 0) {
9016                 /* child */
9017                 INT_ON;
9018                 flags |= EV_EXIT;
9019                 if (backgnd)
9020                         flags &= ~EV_TESTED;
9021  nofork:
9022                 redirect(n->nredir.redirect, 0);
9023                 evaltreenr(n->nredir.n, flags);
9024                 /* never returns */
9025         }
9026         /* parent */
9027         status = 0;
9028         if (backgnd == FORK_FG)
9029                 status = waitforjob(jp);
9030         INT_ON;
9031         return status;
9032 }
9033
9034 /*
9035  * Compute the names of the files in a redirection list.
9036  */
9037 static void fixredir(union node *, const char *, int);
9038 static void
9039 expredir(union node *n)
9040 {
9041         union node *redir;
9042
9043         for (redir = n; redir; redir = redir->nfile.next) {
9044                 struct arglist fn;
9045
9046                 fn.list = NULL;
9047                 fn.lastp = &fn.list;
9048                 switch (redir->type) {
9049                 case NFROMTO:
9050                 case NFROM:
9051                 case NTO:
9052 #if BASH_REDIR_OUTPUT
9053                 case NTO2:
9054 #endif
9055                 case NCLOBBER:
9056                 case NAPPEND:
9057                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9058                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9059 #if BASH_REDIR_OUTPUT
9060  store_expfname:
9061 #endif
9062 #if 0
9063 // By the design of stack allocator, the loop of this kind:
9064 //      while true; do while true; do break; done </dev/null; done
9065 // will look like a memory leak: ash plans to free expfname's
9066 // of "/dev/null" as soon as it finishes running the loop
9067 // (in this case, never).
9068 // This "fix" is wrong:
9069                         if (redir->nfile.expfname)
9070                                 stunalloc(redir->nfile.expfname);
9071 // It results in corrupted state of stacked allocations.
9072 #endif
9073                         redir->nfile.expfname = fn.list->text;
9074                         break;
9075                 case NFROMFD:
9076                 case NTOFD: /* >& */
9077                         if (redir->ndup.vname) {
9078                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9079                                 if (fn.list == NULL)
9080                                         ash_msg_and_raise_error("redir error");
9081 #if BASH_REDIR_OUTPUT
9082 //FIXME: we used expandarg with different args!
9083                                 if (!isdigit_str9(fn.list->text)) {
9084                                         /* >&file, not >&fd */
9085                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9086                                                 ash_msg_and_raise_error("redir error");
9087                                         redir->type = NTO2;
9088                                         goto store_expfname;
9089                                 }
9090 #endif
9091                                 fixredir(redir, fn.list->text, 1);
9092                         }
9093                         break;
9094                 }
9095         }
9096 }
9097
9098 /*
9099  * Evaluate a pipeline.  All the processes in the pipeline are children
9100  * of the process creating the pipeline.  (This differs from some versions
9101  * of the shell, which make the last process in a pipeline the parent
9102  * of all the rest.)
9103  */
9104 static int
9105 evalpipe(union node *n, int flags)
9106 {
9107         struct job *jp;
9108         struct nodelist *lp;
9109         int pipelen;
9110         int prevfd;
9111         int pip[2];
9112         int status = 0;
9113
9114         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9115         pipelen = 0;
9116         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9117                 pipelen++;
9118         flags |= EV_EXIT;
9119         INT_OFF;
9120         if (n->npipe.pipe_backgnd == 0)
9121                 get_tty_state();
9122         jp = makejob(/*n,*/ pipelen);
9123         prevfd = -1;
9124         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9125                 prehash(lp->n);
9126                 pip[1] = -1;
9127                 if (lp->next) {
9128                         if (pipe(pip) < 0) {
9129                                 close(prevfd);
9130                                 ash_msg_and_raise_error("pipe call failed");
9131                         }
9132                 }
9133                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9134                         /* child */
9135                         INT_ON;
9136                         if (pip[1] >= 0) {
9137                                 close(pip[0]);
9138                         }
9139                         if (prevfd > 0) {
9140                                 dup2(prevfd, 0);
9141                                 close(prevfd);
9142                         }
9143                         if (pip[1] > 1) {
9144                                 dup2(pip[1], 1);
9145                                 close(pip[1]);
9146                         }
9147                         evaltreenr(lp->n, flags);
9148                         /* never returns */
9149                 }
9150                 /* parent */
9151                 if (prevfd >= 0)
9152                         close(prevfd);
9153                 prevfd = pip[0];
9154                 /* Don't want to trigger debugging */
9155                 if (pip[1] != -1)
9156                         close(pip[1]);
9157         }
9158         if (n->npipe.pipe_backgnd == 0) {
9159                 status = waitforjob(jp);
9160                 TRACE(("evalpipe:  job done exit status %d\n", status));
9161         }
9162         INT_ON;
9163
9164         return status;
9165 }
9166
9167 /*
9168  * Controls whether the shell is interactive or not.
9169  */
9170 static void
9171 setinteractive(int on)
9172 {
9173         static smallint is_interactive;
9174
9175         if (++on == is_interactive)
9176                 return;
9177         is_interactive = on;
9178         setsignal(SIGINT);
9179         setsignal(SIGQUIT);
9180         setsignal(SIGTERM);
9181 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9182         if (is_interactive > 1) {
9183                 /* Looks like they want an interactive shell */
9184                 static smallint did_banner;
9185
9186                 if (!did_banner) {
9187                         /* note: ash and hush share this string */
9188                         out1fmt("\n\n%s %s\n"
9189                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9190                                 "\n",
9191                                 bb_banner,
9192                                 "built-in shell (ash)"
9193                         );
9194                         did_banner = 1;
9195                 }
9196         }
9197 #endif
9198 }
9199
9200 static void
9201 optschanged(void)
9202 {
9203 #if DEBUG
9204         opentrace();
9205 #endif
9206         setinteractive(iflag);
9207         setjobctl(mflag);
9208 #if ENABLE_FEATURE_EDITING_VI
9209         if (viflag)
9210                 line_input_state->flags |= VI_MODE;
9211         else
9212                 line_input_state->flags &= ~VI_MODE;
9213 #else
9214         viflag = 0; /* forcibly keep the option off */
9215 #endif
9216 }
9217
9218 static struct localvar *localvars;
9219
9220 /*
9221  * Called after a function returns.
9222  * Interrupts must be off.
9223  */
9224 static void
9225 poplocalvars(void)
9226 {
9227         struct localvar *lvp;
9228         struct var *vp;
9229
9230         while ((lvp = localvars) != NULL) {
9231                 localvars = lvp->next;
9232                 vp = lvp->vp;
9233                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9234                 if (vp == NULL) {       /* $- saved */
9235                         memcpy(optlist, lvp->text, sizeof(optlist));
9236                         free((char*)lvp->text);
9237                         optschanged();
9238                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9239                         unsetvar(vp->var_text);
9240                 } else {
9241                         if (vp->var_func)
9242                                 vp->var_func(var_end(lvp->text));
9243                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9244                                 free((char*)vp->var_text);
9245                         vp->flags = lvp->flags;
9246                         vp->var_text = lvp->text;
9247                 }
9248                 free(lvp);
9249         }
9250 }
9251
9252 static int
9253 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9254 {
9255         volatile struct shparam saveparam;
9256         struct localvar *volatile savelocalvars;
9257         struct jmploc *volatile savehandler;
9258         struct jmploc jmploc;
9259         int e;
9260
9261         saveparam = shellparam;
9262         savelocalvars = localvars;
9263         savehandler = exception_handler;
9264         e = setjmp(jmploc.loc);
9265         if (e) {
9266                 goto funcdone;
9267         }
9268         INT_OFF;
9269         exception_handler = &jmploc;
9270         localvars = NULL;
9271         shellparam.malloced = 0;
9272         func->count++;
9273         funcnest++;
9274         INT_ON;
9275         shellparam.nparam = argc - 1;
9276         shellparam.p = argv + 1;
9277 #if ENABLE_ASH_GETOPTS
9278         shellparam.optind = 1;
9279         shellparam.optoff = -1;
9280 #endif
9281         evaltree(func->n.narg.next, flags & EV_TESTED);
9282  funcdone:
9283         INT_OFF;
9284         funcnest--;
9285         freefunc(func);
9286         poplocalvars();
9287         localvars = savelocalvars;
9288         freeparam(&shellparam);
9289         shellparam = saveparam;
9290         exception_handler = savehandler;
9291         INT_ON;
9292         evalskip &= ~SKIPFUNC;
9293         return e;
9294 }
9295
9296 /*
9297  * Make a variable a local variable.  When a variable is made local, it's
9298  * value and flags are saved in a localvar structure.  The saved values
9299  * will be restored when the shell function returns.  We handle the name
9300  * "-" as a special case: it makes changes to "set +-options" local
9301  * (options will be restored on return from the function).
9302  */
9303 static void
9304 mklocal(char *name)
9305 {
9306         struct localvar *lvp;
9307         struct var **vpp;
9308         struct var *vp;
9309         char *eq = strchr(name, '=');
9310
9311         INT_OFF;
9312         /* Cater for duplicate "local". Examples:
9313          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9314          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9315          */
9316         lvp = localvars;
9317         while (lvp) {
9318                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9319                         if (eq)
9320                                 setvareq(name, 0);
9321                         /* else:
9322                          * it's a duplicate "local VAR" declaration, do nothing
9323                          */
9324                         goto ret;
9325                 }
9326                 lvp = lvp->next;
9327         }
9328
9329         lvp = ckzalloc(sizeof(*lvp));
9330         if (LONE_DASH(name)) {
9331                 char *p;
9332                 p = ckmalloc(sizeof(optlist));
9333                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9334                 vp = NULL;
9335         } else {
9336                 vpp = hashvar(name);
9337                 vp = *findvar(vpp, name);
9338                 if (vp == NULL) {
9339                         /* variable did not exist yet */
9340                         if (eq)
9341                                 setvareq(name, VSTRFIXED);
9342                         else
9343                                 setvar(name, NULL, VSTRFIXED);
9344                         vp = *vpp;      /* the new variable */
9345                         lvp->flags = VUNSET;
9346                 } else {
9347                         lvp->text = vp->var_text;
9348                         lvp->flags = vp->flags;
9349                         /* make sure neither "struct var" nor string gets freed
9350                          * during (un)setting:
9351                          */
9352                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9353                         if (eq)
9354                                 setvareq(name, 0);
9355                         else
9356                                 /* "local VAR" unsets VAR: */
9357                                 setvar0(name, NULL);
9358                 }
9359         }
9360         lvp->vp = vp;
9361         lvp->next = localvars;
9362         localvars = lvp;
9363  ret:
9364         INT_ON;
9365 }
9366
9367 /*
9368  * The "local" command.
9369  */
9370 static int FAST_FUNC
9371 localcmd(int argc UNUSED_PARAM, char **argv)
9372 {
9373         char *name;
9374
9375         if (!funcnest)
9376                 ash_msg_and_raise_error("not in a function");
9377
9378         argv = argptr;
9379         while ((name = *argv++) != NULL) {
9380                 mklocal(name);
9381         }
9382         return 0;
9383 }
9384
9385 static int FAST_FUNC
9386 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9387 {
9388         return 1;
9389 }
9390
9391 static int FAST_FUNC
9392 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9393 {
9394         return 0;
9395 }
9396
9397 static int FAST_FUNC
9398 execcmd(int argc UNUSED_PARAM, char **argv)
9399 {
9400         optionarg = NULL;
9401         while (nextopt("a:") != '\0')
9402                 /* nextopt() sets optionarg to "-a ARGV0" */;
9403
9404         argv = argptr;
9405         if (argv[0]) {
9406                 char *prog;
9407
9408                 iflag = 0;              /* exit on error */
9409                 mflag = 0;
9410                 optschanged();
9411                 /* We should set up signals for "exec CMD"
9412                  * the same way as for "CMD" without "exec".
9413                  * But optschanged->setinteractive->setsignal
9414                  * still thought we are a root shell. Therefore, for example,
9415                  * SIGQUIT is still set to IGN. Fix it:
9416                  */
9417                 shlvl++;
9418                 setsignal(SIGQUIT);
9419                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9420                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9421                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9422
9423                 prog = argv[0];
9424                 if (optionarg)
9425                         argv[0] = optionarg;
9426                 shellexec(prog, argv, pathval(), 0);
9427                 /* NOTREACHED */
9428         }
9429         return 0;
9430 }
9431
9432 /*
9433  * The return command.
9434  */
9435 static int FAST_FUNC
9436 returncmd(int argc UNUSED_PARAM, char **argv)
9437 {
9438         /*
9439          * If called outside a function, do what ksh does;
9440          * skip the rest of the file.
9441          */
9442         evalskip = SKIPFUNC;
9443         return argv[1] ? number(argv[1]) : exitstatus;
9444 }
9445
9446 /* Forward declarations for builtintab[] */
9447 static int breakcmd(int, char **) FAST_FUNC;
9448 static int dotcmd(int, char **) FAST_FUNC;
9449 static int evalcmd(int, char **, int) FAST_FUNC;
9450 static int exitcmd(int, char **) FAST_FUNC;
9451 static int exportcmd(int, char **) FAST_FUNC;
9452 #if ENABLE_ASH_GETOPTS
9453 static int getoptscmd(int, char **) FAST_FUNC;
9454 #endif
9455 #if ENABLE_ASH_HELP
9456 static int helpcmd(int, char **) FAST_FUNC;
9457 #endif
9458 #if MAX_HISTORY
9459 static int historycmd(int, char **) FAST_FUNC;
9460 #endif
9461 #if ENABLE_FEATURE_SH_MATH
9462 static int letcmd(int, char **) FAST_FUNC;
9463 #endif
9464 static int readcmd(int, char **) FAST_FUNC;
9465 static int setcmd(int, char **) FAST_FUNC;
9466 static int shiftcmd(int, char **) FAST_FUNC;
9467 static int timescmd(int, char **) FAST_FUNC;
9468 static int trapcmd(int, char **) FAST_FUNC;
9469 static int umaskcmd(int, char **) FAST_FUNC;
9470 static int unsetcmd(int, char **) FAST_FUNC;
9471 static int ulimitcmd(int, char **) FAST_FUNC;
9472
9473 #define BUILTIN_NOSPEC          "0"
9474 #define BUILTIN_SPECIAL         "1"
9475 #define BUILTIN_REGULAR         "2"
9476 #define BUILTIN_SPEC_REG        "3"
9477 #define BUILTIN_ASSIGN          "4"
9478 #define BUILTIN_SPEC_ASSG       "5"
9479 #define BUILTIN_REG_ASSG        "6"
9480 #define BUILTIN_SPEC_REG_ASSG   "7"
9481
9482 /* Stubs for calling non-FAST_FUNC's */
9483 #if ENABLE_ASH_ECHO
9484 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9485 #endif
9486 #if ENABLE_ASH_PRINTF
9487 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9488 #endif
9489 #if ENABLE_ASH_TEST || BASH_TEST2
9490 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9491 #endif
9492
9493 /* Keep these in proper order since it is searched via bsearch() */
9494 static const struct builtincmd builtintab[] = {
9495         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9496         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9497 #if ENABLE_ASH_TEST
9498         { BUILTIN_REGULAR       "["       , testcmd    },
9499 #endif
9500 #if BASH_TEST2
9501         { BUILTIN_REGULAR       "[["      , testcmd    },
9502 #endif
9503 #if ENABLE_ASH_ALIAS
9504         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9505 #endif
9506 #if JOBS
9507         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9508 #endif
9509         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9510         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9511         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9512 #if ENABLE_ASH_CMDCMD
9513         { BUILTIN_REGULAR       "command" , commandcmd },
9514 #endif
9515         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9516 #if ENABLE_ASH_ECHO
9517         { BUILTIN_REGULAR       "echo"    , echocmd    },
9518 #endif
9519         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9520         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9521         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9522         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9523         { BUILTIN_REGULAR       "false"   , falsecmd   },
9524 #if JOBS
9525         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9526 #endif
9527 #if ENABLE_ASH_GETOPTS
9528         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9529 #endif
9530         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9531 #if ENABLE_ASH_HELP
9532         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9533 #endif
9534 #if MAX_HISTORY
9535         { BUILTIN_NOSPEC        "history" , historycmd },
9536 #endif
9537 #if JOBS
9538         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9539         { BUILTIN_REGULAR       "kill"    , killcmd    },
9540 #endif
9541 #if ENABLE_FEATURE_SH_MATH
9542         { BUILTIN_NOSPEC        "let"     , letcmd     },
9543 #endif
9544         { BUILTIN_ASSIGN        "local"   , localcmd   },
9545 #if ENABLE_ASH_PRINTF
9546         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9547 #endif
9548         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9549         { BUILTIN_REGULAR       "read"    , readcmd    },
9550         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9551         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9552         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9553         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9554 #if BASH_SOURCE
9555         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9556 #endif
9557 #if ENABLE_ASH_TEST
9558         { BUILTIN_REGULAR       "test"    , testcmd    },
9559 #endif
9560         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9561         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9562         { BUILTIN_REGULAR       "true"    , truecmd    },
9563         { BUILTIN_NOSPEC        "type"    , typecmd    },
9564         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9565         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9566 #if ENABLE_ASH_ALIAS
9567         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9568 #endif
9569         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9570         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9571 };
9572
9573 /* Should match the above table! */
9574 #define COMMANDCMD (builtintab + \
9575         /* . : */       2 + \
9576         /* [ */         1 * ENABLE_ASH_TEST + \
9577         /* [[ */        1 * BASH_TEST2 + \
9578         /* alias */     1 * ENABLE_ASH_ALIAS + \
9579         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9580         /* break cd cddir  */   3)
9581 #define EVALCMD (COMMANDCMD + \
9582         /* command */   1 * ENABLE_ASH_CMDCMD + \
9583         /* continue */  1 + \
9584         /* echo */      1 * ENABLE_ASH_ECHO + \
9585         0)
9586 #define EXECCMD (EVALCMD + \
9587         /* eval */      1)
9588
9589 /*
9590  * Search the table of builtin commands.
9591  */
9592 static int
9593 pstrcmp1(const void *a, const void *b)
9594 {
9595         return strcmp((char*)a, *(char**)b + 1);
9596 }
9597 static struct builtincmd *
9598 find_builtin(const char *name)
9599 {
9600         struct builtincmd *bp;
9601
9602         bp = bsearch(
9603                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9604                 pstrcmp1
9605         );
9606         return bp;
9607 }
9608
9609 /*
9610  * Execute a simple command.
9611  */
9612 static int
9613 isassignment(const char *p)
9614 {
9615         const char *q = endofname(p);
9616         if (p == q)
9617                 return 0;
9618         return *q == '=';
9619 }
9620 static int FAST_FUNC
9621 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9622 {
9623         /* Preserve exitstatus of a previous possible redirection
9624          * as POSIX mandates */
9625         return back_exitstatus;
9626 }
9627 static int
9628 evalcommand(union node *cmd, int flags)
9629 {
9630         static const struct builtincmd null_bltin = {
9631                 "\0\0", bltincmd /* why three NULs? */
9632         };
9633         struct stackmark smark;
9634         union node *argp;
9635         struct arglist arglist;
9636         struct arglist varlist;
9637         char **argv;
9638         int argc;
9639         const struct strlist *sp;
9640         struct cmdentry cmdentry;
9641         struct job *jp;
9642         char *lastarg;
9643         const char *path;
9644         int spclbltin;
9645         int status;
9646         char **nargv;
9647         struct builtincmd *bcmd;
9648         smallint cmd_is_exec;
9649         smallint pseudovarflag = 0;
9650
9651         /* First expand the arguments. */
9652         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9653         setstackmark(&smark);
9654         back_exitstatus = 0;
9655
9656         cmdentry.cmdtype = CMDBUILTIN;
9657         cmdentry.u.cmd = &null_bltin;
9658         varlist.lastp = &varlist.list;
9659         *varlist.lastp = NULL;
9660         arglist.lastp = &arglist.list;
9661         *arglist.lastp = NULL;
9662
9663         argc = 0;
9664         if (cmd->ncmd.args) {
9665                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9666                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9667         }
9668
9669         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9670                 struct strlist **spp;
9671
9672                 spp = arglist.lastp;
9673                 if (pseudovarflag && isassignment(argp->narg.text))
9674                         expandarg(argp, &arglist, EXP_VARTILDE);
9675                 else
9676                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9677
9678                 for (sp = *spp; sp; sp = sp->next)
9679                         argc++;
9680         }
9681
9682         /* Reserve one extra spot at the front for shellexec. */
9683         nargv = stalloc(sizeof(char *) * (argc + 2));
9684         argv = ++nargv;
9685         for (sp = arglist.list; sp; sp = sp->next) {
9686                 TRACE(("evalcommand arg: %s\n", sp->text));
9687                 *nargv++ = sp->text;
9688         }
9689         *nargv = NULL;
9690
9691         lastarg = NULL;
9692         if (iflag && funcnest == 0 && argc > 0)
9693                 lastarg = nargv[-1];
9694
9695         preverrout_fd = 2;
9696         expredir(cmd->ncmd.redirect);
9697         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9698
9699         path = vpath.var_text;
9700         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9701                 struct strlist **spp;
9702                 char *p;
9703
9704                 spp = varlist.lastp;
9705                 expandarg(argp, &varlist, EXP_VARTILDE);
9706
9707                 /*
9708                  * Modify the command lookup path, if a PATH= assignment
9709                  * is present
9710                  */
9711                 p = (*spp)->text;
9712                 if (varcmp(p, path) == 0)
9713                         path = p;
9714         }
9715
9716         /* Print the command if xflag is set. */
9717         if (xflag) {
9718                 const char *pfx = "";
9719
9720                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9721
9722                 sp = varlist.list;
9723                 while (sp) {
9724                         char *varval = sp->text;
9725                         char *eq = strchrnul(varval, '=');
9726                         if (*eq)
9727                                 eq++;
9728                         fdprintf(preverrout_fd, "%s%.*s%s",
9729                                 pfx,
9730                                 (int)(eq - varval), varval,
9731                                 maybe_single_quote(eq)
9732                         );
9733                         sp = sp->next;
9734                         pfx = " ";
9735                 }
9736
9737                 sp = arglist.list;
9738                 while (sp) {
9739                         fdprintf(preverrout_fd, "%s%s",
9740                                 pfx,
9741                                 /* always quote if matches reserved word: */
9742                                 findkwd(sp->text)
9743                                 ? single_quote(sp->text)
9744                                 : maybe_single_quote(sp->text)
9745                         );
9746                         sp = sp->next;
9747                         pfx = " ";
9748                 }
9749                 safe_write(preverrout_fd, "\n", 1);
9750         }
9751
9752         cmd_is_exec = 0;
9753         spclbltin = -1;
9754
9755         /* Now locate the command. */
9756         if (argc) {
9757                 int cmd_flag = DO_ERR;
9758 #if ENABLE_ASH_CMDCMD
9759                 const char *oldpath = path + 5;
9760 #endif
9761                 path += 5;
9762                 for (;;) {
9763                         find_command(argv[0], &cmdentry, cmd_flag, path);
9764                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9765                                 flush_stdout_stderr();
9766                                 status = 127;
9767                                 goto bail;
9768                         }
9769
9770                         /* implement bltin and command here */
9771                         if (cmdentry.cmdtype != CMDBUILTIN)
9772                                 break;
9773                         if (spclbltin < 0)
9774                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9775                         if (cmdentry.u.cmd == EXECCMD)
9776                                 cmd_is_exec = 1;
9777 #if ENABLE_ASH_CMDCMD
9778                         if (cmdentry.u.cmd == COMMANDCMD) {
9779                                 path = oldpath;
9780                                 nargv = parse_command_args(argv, &path);
9781                                 if (!nargv)
9782                                         break;
9783                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9784                                  * nargv => "PROG". path is updated if -p.
9785                                  */
9786                                 argc -= nargv - argv;
9787                                 argv = nargv;
9788                                 cmd_flag |= DO_NOFUNC;
9789                         } else
9790 #endif
9791                                 break;
9792                 }
9793         }
9794
9795         if (status) {
9796  bail:
9797                 exitstatus = status;
9798
9799                 /* We have a redirection error. */
9800                 if (spclbltin > 0)
9801                         raise_exception(EXERROR);
9802
9803                 goto out;
9804         }
9805
9806         /* Execute the command. */
9807         switch (cmdentry.cmdtype) {
9808         default: {
9809
9810 #if ENABLE_FEATURE_SH_NOFORK
9811 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9812  *     around run_nofork_applet() call.
9813  * (2) Should this check also be done in forkshell()?
9814  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9815  */
9816                 /* find_command() encodes applet_no as (-2 - applet_no) */
9817                 int applet_no = (- cmdentry.u.index - 2);
9818                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9819                         listsetvar(varlist.list, VEXPORT|VSTACK);
9820                         /* run <applet>_main() */
9821                         status = run_nofork_applet(applet_no, argv);
9822                         break;
9823                 }
9824 #endif
9825                 /* Can we avoid forking off? For example, very last command
9826                  * in a script or a subshell does not need forking,
9827                  * we can just exec it.
9828                  */
9829                 if (!(flags & EV_EXIT) || may_have_traps) {
9830                         /* No, forking off a child is necessary */
9831                         INT_OFF;
9832                         get_tty_state();
9833                         jp = makejob(/*cmd,*/ 1);
9834                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9835                                 /* parent */
9836                                 status = waitforjob(jp);
9837                                 INT_ON;
9838                                 TRACE(("forked child exited with %d\n", status));
9839                                 break;
9840                         }
9841                         /* child */
9842                         FORCE_INT_ON;
9843                         /* fall through to exec'ing external program */
9844                 }
9845                 listsetvar(varlist.list, VEXPORT|VSTACK);
9846                 shellexec(argv[0], argv, path, cmdentry.u.index);
9847                 /* NOTREACHED */
9848         } /* default */
9849         case CMDBUILTIN:
9850                 cmdenviron = varlist.list;
9851                 if (cmdenviron) {
9852                         struct strlist *list = cmdenviron;
9853                         int i = VNOSET;
9854                         if (spclbltin > 0 || argc == 0) {
9855                                 i = 0;
9856                                 if (cmd_is_exec && argc > 1)
9857                                         i = VEXPORT;
9858                         }
9859                         listsetvar(list, i);
9860                 }
9861                 /* Tight loop with builtins only:
9862                  * "while kill -0 $child; do true; done"
9863                  * will never exit even if $child died, unless we do this
9864                  * to reap the zombie and make kill detect that it's gone: */
9865                 dowait(DOWAIT_NONBLOCK, NULL);
9866
9867                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9868                         if (exception_type == EXERROR && spclbltin <= 0) {
9869                                 FORCE_INT_ON;
9870                                 goto readstatus;
9871                         }
9872  raise:
9873                         longjmp(exception_handler->loc, 1);
9874                 }
9875                 goto readstatus;
9876
9877         case CMDFUNCTION:
9878                 listsetvar(varlist.list, 0);
9879                 /* See above for the rationale */
9880                 dowait(DOWAIT_NONBLOCK, NULL);
9881                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9882                         goto raise;
9883  readstatus:
9884                 status = exitstatus;
9885                 break;
9886         } /* switch */
9887
9888  out:
9889         if (cmd->ncmd.redirect)
9890                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9891         if (lastarg) {
9892                 /* dsl: I think this is intended to be used to support
9893                  * '_' in 'vi' command mode during line editing...
9894                  * However I implemented that within libedit itself.
9895                  */
9896                 setvar0("_", lastarg);
9897         }
9898         popstackmark(&smark);
9899
9900         return status;
9901 }
9902
9903 static int
9904 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9905 {
9906         char *volatile savecmdname;
9907         struct jmploc *volatile savehandler;
9908         struct jmploc jmploc;
9909         int status;
9910         int i;
9911
9912         savecmdname = commandname;
9913         savehandler = exception_handler;
9914         i = setjmp(jmploc.loc);
9915         if (i)
9916                 goto cmddone;
9917         exception_handler = &jmploc;
9918         commandname = argv[0];
9919         argptr = argv + 1;
9920         optptr = NULL;                  /* initialize nextopt */
9921         if (cmd == EVALCMD)
9922                 status = evalcmd(argc, argv, flags);
9923         else
9924                 status = (*cmd->builtin)(argc, argv);
9925         flush_stdout_stderr();
9926         status |= ferror(stdout);
9927         exitstatus = status;
9928  cmddone:
9929         clearerr(stdout);
9930         commandname = savecmdname;
9931         exception_handler = savehandler;
9932
9933         return i;
9934 }
9935
9936 static int
9937 goodname(const char *p)
9938 {
9939         return endofname(p)[0] == '\0';
9940 }
9941
9942
9943 /*
9944  * Search for a command.  This is called before we fork so that the
9945  * location of the command will be available in the parent as well as
9946  * the child.  The check for "goodname" is an overly conservative
9947  * check that the name will not be subject to expansion.
9948  */
9949 static void
9950 prehash(union node *n)
9951 {
9952         struct cmdentry entry;
9953
9954         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9955                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9956 }
9957
9958
9959 /* ============ Builtin commands
9960  *
9961  * Builtin commands whose functions are closely tied to evaluation
9962  * are implemented here.
9963  */
9964
9965 /*
9966  * Handle break and continue commands.  Break, continue, and return are
9967  * all handled by setting the evalskip flag.  The evaluation routines
9968  * above all check this flag, and if it is set they start skipping
9969  * commands rather than executing them.  The variable skipcount is
9970  * the number of loops to break/continue, or the number of function
9971  * levels to return.  (The latter is always 1.)  It should probably
9972  * be an error to break out of more loops than exist, but it isn't
9973  * in the standard shell so we don't make it one here.
9974  */
9975 static int FAST_FUNC
9976 breakcmd(int argc UNUSED_PARAM, char **argv)
9977 {
9978         int n = argv[1] ? number(argv[1]) : 1;
9979
9980         if (n <= 0)
9981                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9982         if (n > loopnest)
9983                 n = loopnest;
9984         if (n > 0) {
9985                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9986                 skipcount = n;
9987         }
9988         return 0;
9989 }
9990
9991
9992 /*
9993  * This implements the input routines used by the parser.
9994  */
9995
9996 enum {
9997         INPUT_PUSH_FILE = 1,
9998         INPUT_NOFILE_OK = 2,
9999 };
10000
10001 static smallint checkkwd;
10002 /* values of checkkwd variable */
10003 #define CHKALIAS        0x1
10004 #define CHKKWD          0x2
10005 #define CHKNL           0x4
10006
10007 /*
10008  * Push a string back onto the input at this current parsefile level.
10009  * We handle aliases this way.
10010  */
10011 #if !ENABLE_ASH_ALIAS
10012 #define pushstring(s, ap) pushstring(s)
10013 #endif
10014 static void
10015 pushstring(char *s, struct alias *ap)
10016 {
10017         struct strpush *sp;
10018         int len;
10019
10020         len = strlen(s);
10021         INT_OFF;
10022         if (g_parsefile->strpush) {
10023                 sp = ckzalloc(sizeof(*sp));
10024                 sp->prev = g_parsefile->strpush;
10025         } else {
10026                 sp = &(g_parsefile->basestrpush);
10027         }
10028         g_parsefile->strpush = sp;
10029         sp->prev_string = g_parsefile->next_to_pgetc;
10030         sp->prev_left_in_line = g_parsefile->left_in_line;
10031         sp->unget = g_parsefile->unget;
10032         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10033 #if ENABLE_ASH_ALIAS
10034         sp->ap = ap;
10035         if (ap) {
10036                 ap->flag |= ALIASINUSE;
10037                 sp->string = s;
10038         }
10039 #endif
10040         g_parsefile->next_to_pgetc = s;
10041         g_parsefile->left_in_line = len;
10042         g_parsefile->unget = 0;
10043         INT_ON;
10044 }
10045
10046 static void
10047 popstring(void)
10048 {
10049         struct strpush *sp = g_parsefile->strpush;
10050
10051         INT_OFF;
10052 #if ENABLE_ASH_ALIAS
10053         if (sp->ap) {
10054                 if (g_parsefile->next_to_pgetc[-1] == ' '
10055                  || g_parsefile->next_to_pgetc[-1] == '\t'
10056                 ) {
10057                         checkkwd |= CHKALIAS;
10058                 }
10059                 if (sp->string != sp->ap->val) {
10060                         free(sp->string);
10061                 }
10062                 sp->ap->flag &= ~ALIASINUSE;
10063                 if (sp->ap->flag & ALIASDEAD) {
10064                         unalias(sp->ap->name);
10065                 }
10066         }
10067 #endif
10068         g_parsefile->next_to_pgetc = sp->prev_string;
10069         g_parsefile->left_in_line = sp->prev_left_in_line;
10070         g_parsefile->unget = sp->unget;
10071         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10072         g_parsefile->strpush = sp->prev;
10073         if (sp != &(g_parsefile->basestrpush))
10074                 free(sp);
10075         INT_ON;
10076 }
10077
10078 static int
10079 preadfd(void)
10080 {
10081         int nr;
10082         char *buf = g_parsefile->buf;
10083
10084         g_parsefile->next_to_pgetc = buf;
10085 #if ENABLE_FEATURE_EDITING
10086  retry:
10087         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10088                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10089         else {
10090                 int timeout = -1;
10091 # if ENABLE_ASH_IDLE_TIMEOUT
10092                 if (iflag) {
10093                         const char *tmout_var = lookupvar("TMOUT");
10094                         if (tmout_var) {
10095                                 timeout = atoi(tmout_var) * 1000;
10096                                 if (timeout <= 0)
10097                                         timeout = -1;
10098                         }
10099                 }
10100 # endif
10101 # if ENABLE_FEATURE_TAB_COMPLETION
10102                 line_input_state->path_lookup = pathval();
10103 # endif
10104                 reinit_unicode_for_ash();
10105                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10106                 if (nr == 0) {
10107                         /* ^C pressed, "convert" to SIGINT */
10108                         write(STDOUT_FILENO, "^C", 2);
10109                         if (trap[SIGINT]) {
10110                                 buf[0] = '\n';
10111                                 buf[1] = '\0';
10112                                 raise(SIGINT);
10113                                 return 1;
10114                         }
10115                         exitstatus = 128 + SIGINT;
10116                         bb_putchar('\n');
10117                         goto retry;
10118                 }
10119                 if (nr < 0) {
10120                         if (errno == 0) {
10121                                 /* Ctrl+D pressed */
10122                                 nr = 0;
10123                         }
10124 # if ENABLE_ASH_IDLE_TIMEOUT
10125                         else if (errno == EAGAIN && timeout > 0) {
10126                                 puts("\007timed out waiting for input: auto-logout");
10127                                 exitshell();
10128                         }
10129 # endif
10130                 }
10131         }
10132 #else
10133         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10134 #endif
10135
10136 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10137         if (nr < 0) {
10138                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10139                         int flags = fcntl(0, F_GETFL);
10140                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10141                                 flags &= ~O_NONBLOCK;
10142                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10143                                         out2str("sh: turning off NDELAY mode\n");
10144                                         goto retry;
10145                                 }
10146                         }
10147                 }
10148         }
10149 #endif
10150         return nr;
10151 }
10152
10153 /*
10154  * Refill the input buffer and return the next input character:
10155  *
10156  * 1) If a string was pushed back on the input, pop it;
10157  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10158  *    or we are reading from a string so we can't refill the buffer,
10159  *    return EOF.
10160  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10161  * 4) Process input up to the next newline, deleting nul characters.
10162  */
10163 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10164 #define pgetc_debug(...) ((void)0)
10165 static int pgetc(void);
10166 static int
10167 preadbuffer(void)
10168 {
10169         char *q;
10170         int more;
10171
10172         if (g_parsefile->strpush) {
10173 #if ENABLE_ASH_ALIAS
10174                 if (g_parsefile->left_in_line == -1
10175                  && g_parsefile->strpush->ap
10176                  && g_parsefile->next_to_pgetc[-1] != ' '
10177                  && g_parsefile->next_to_pgetc[-1] != '\t'
10178                 ) {
10179                         pgetc_debug("preadbuffer PEOA");
10180                         return PEOA;
10181                 }
10182 #endif
10183                 popstring();
10184                 return pgetc();
10185         }
10186         /* on both branches above g_parsefile->left_in_line < 0.
10187          * "pgetc" needs refilling.
10188          */
10189
10190         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10191          * pungetc() may increment it a few times.
10192          * Assuming it won't increment it to less than -90.
10193          */
10194         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10195                 pgetc_debug("preadbuffer PEOF1");
10196                 /* even in failure keep left_in_line and next_to_pgetc
10197                  * in lock step, for correct multi-layer pungetc.
10198                  * left_in_line was decremented before preadbuffer(),
10199                  * must inc next_to_pgetc: */
10200                 g_parsefile->next_to_pgetc++;
10201                 return PEOF;
10202         }
10203
10204         more = g_parsefile->left_in_buffer;
10205         if (more <= 0) {
10206                 flush_stdout_stderr();
10207  again:
10208                 more = preadfd();
10209                 if (more <= 0) {
10210                         /* don't try reading again */
10211                         g_parsefile->left_in_line = -99;
10212                         pgetc_debug("preadbuffer PEOF2");
10213                         g_parsefile->next_to_pgetc++;
10214                         return PEOF;
10215                 }
10216         }
10217
10218         /* Find out where's the end of line.
10219          * Set g_parsefile->left_in_line
10220          * and g_parsefile->left_in_buffer acordingly.
10221          * NUL chars are deleted.
10222          */
10223         q = g_parsefile->next_to_pgetc;
10224         for (;;) {
10225                 char c;
10226
10227                 more--;
10228
10229                 c = *q;
10230                 if (c == '\0') {
10231                         memmove(q, q + 1, more);
10232                 } else {
10233                         q++;
10234                         if (c == '\n') {
10235                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10236                                 break;
10237                         }
10238                 }
10239
10240                 if (more <= 0) {
10241                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10242                         if (g_parsefile->left_in_line < 0)
10243                                 goto again;
10244                         break;
10245                 }
10246         }
10247         g_parsefile->left_in_buffer = more;
10248
10249         if (vflag) {
10250                 char save = *q;
10251                 *q = '\0';
10252                 out2str(g_parsefile->next_to_pgetc);
10253                 *q = save;
10254         }
10255
10256         pgetc_debug("preadbuffer at %d:%p'%s'",
10257                         g_parsefile->left_in_line,
10258                         g_parsefile->next_to_pgetc,
10259                         g_parsefile->next_to_pgetc);
10260         return (unsigned char)*g_parsefile->next_to_pgetc++;
10261 }
10262
10263 static void
10264 nlprompt(void)
10265 {
10266         g_parsefile->linno++;
10267         setprompt_if(doprompt, 2);
10268 }
10269 static void
10270 nlnoprompt(void)
10271 {
10272         g_parsefile->linno++;
10273         needprompt = doprompt;
10274 }
10275
10276 static int
10277 pgetc(void)
10278 {
10279         int c;
10280
10281         pgetc_debug("pgetc at %d:%p'%s'",
10282                         g_parsefile->left_in_line,
10283                         g_parsefile->next_to_pgetc,
10284                         g_parsefile->next_to_pgetc);
10285         if (g_parsefile->unget)
10286                 return g_parsefile->lastc[--g_parsefile->unget];
10287
10288         if (--g_parsefile->left_in_line >= 0)
10289                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10290         else
10291                 c = preadbuffer();
10292
10293         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10294         g_parsefile->lastc[0] = c;
10295
10296         return c;
10297 }
10298
10299 #if ENABLE_ASH_ALIAS
10300 static int
10301 pgetc_without_PEOA(void)
10302 {
10303         int c;
10304         do {
10305                 pgetc_debug("pgetc at %d:%p'%s'",
10306                                 g_parsefile->left_in_line,
10307                                 g_parsefile->next_to_pgetc,
10308                                 g_parsefile->next_to_pgetc);
10309                 c = pgetc();
10310         } while (c == PEOA);
10311         return c;
10312 }
10313 #else
10314 # define pgetc_without_PEOA() pgetc()
10315 #endif
10316
10317 /*
10318  * Read a line from the script.
10319  */
10320 static char *
10321 pfgets(char *line, int len)
10322 {
10323         char *p = line;
10324         int nleft = len;
10325         int c;
10326
10327         while (--nleft > 0) {
10328                 c = pgetc_without_PEOA();
10329                 if (c == PEOF) {
10330                         if (p == line)
10331                                 return NULL;
10332                         break;
10333                 }
10334                 *p++ = c;
10335                 if (c == '\n')
10336                         break;
10337         }
10338         *p = '\0';
10339         return line;
10340 }
10341
10342 /*
10343  * Undo a call to pgetc.  Only two characters may be pushed back.
10344  * PEOF may be pushed back.
10345  */
10346 static void
10347 pungetc(void)
10348 {
10349         g_parsefile->unget++;
10350 }
10351
10352 /* This one eats backslash+newline */
10353 static int
10354 pgetc_eatbnl(void)
10355 {
10356         int c;
10357
10358         while ((c = pgetc()) == '\\') {
10359                 if (pgetc() != '\n') {
10360                         pungetc();
10361                         break;
10362                 }
10363
10364                 nlprompt();
10365         }
10366
10367         return c;
10368 }
10369
10370 /*
10371  * To handle the "." command, a stack of input files is used.  Pushfile
10372  * adds a new entry to the stack and popfile restores the previous level.
10373  */
10374 static void
10375 pushfile(void)
10376 {
10377         struct parsefile *pf;
10378
10379         pf = ckzalloc(sizeof(*pf));
10380         pf->prev = g_parsefile;
10381         pf->pf_fd = -1;
10382         /*pf->strpush = NULL; - ckzalloc did it */
10383         /*pf->basestrpush.prev = NULL;*/
10384         /*pf->unget = 0;*/
10385         g_parsefile = pf;
10386 }
10387
10388 static void
10389 popfile(void)
10390 {
10391         struct parsefile *pf = g_parsefile;
10392
10393         if (pf == &basepf)
10394                 return;
10395
10396         INT_OFF;
10397         if (pf->pf_fd >= 0)
10398                 close(pf->pf_fd);
10399         free(pf->buf);
10400         while (pf->strpush)
10401                 popstring();
10402         g_parsefile = pf->prev;
10403         free(pf);
10404         INT_ON;
10405 }
10406
10407 /*
10408  * Return to top level.
10409  */
10410 static void
10411 popallfiles(void)
10412 {
10413         while (g_parsefile != &basepf)
10414                 popfile();
10415 }
10416
10417 /*
10418  * Close the file(s) that the shell is reading commands from.  Called
10419  * after a fork is done.
10420  */
10421 static void
10422 closescript(void)
10423 {
10424         popallfiles();
10425         if (g_parsefile->pf_fd > 0) {
10426                 close(g_parsefile->pf_fd);
10427                 g_parsefile->pf_fd = 0;
10428         }
10429 }
10430
10431 /*
10432  * Like setinputfile, but takes an open file descriptor.  Call this with
10433  * interrupts off.
10434  */
10435 static void
10436 setinputfd(int fd, int push)
10437 {
10438         if (push) {
10439                 pushfile();
10440                 g_parsefile->buf = NULL;
10441         }
10442         g_parsefile->pf_fd = fd;
10443         if (g_parsefile->buf == NULL)
10444                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10445         g_parsefile->left_in_buffer = 0;
10446         g_parsefile->left_in_line = 0;
10447         g_parsefile->linno = 1;
10448 }
10449
10450 /*
10451  * Set the input to take input from a file.  If push is set, push the
10452  * old input onto the stack first.
10453  */
10454 static int
10455 setinputfile(const char *fname, int flags)
10456 {
10457         int fd;
10458
10459         INT_OFF;
10460         fd = open(fname, O_RDONLY);
10461         if (fd < 0) {
10462                 if (flags & INPUT_NOFILE_OK)
10463                         goto out;
10464                 exitstatus = 127;
10465                 ash_msg_and_raise_error("can't open '%s'", fname);
10466         }
10467         if (fd < 10)
10468                 fd = savefd(fd);
10469         else
10470                 close_on_exec_on(fd);
10471         setinputfd(fd, flags & INPUT_PUSH_FILE);
10472  out:
10473         INT_ON;
10474         return fd;
10475 }
10476
10477 /*
10478  * Like setinputfile, but takes input from a string.
10479  */
10480 static void
10481 setinputstring(char *string)
10482 {
10483         INT_OFF;
10484         pushfile();
10485         g_parsefile->next_to_pgetc = string;
10486         g_parsefile->left_in_line = strlen(string);
10487         g_parsefile->buf = NULL;
10488         g_parsefile->linno = 1;
10489         INT_ON;
10490 }
10491
10492
10493 /*
10494  * Routines to check for mail.
10495  */
10496
10497 #if ENABLE_ASH_MAIL
10498
10499 /* Hash of mtimes of mailboxes */
10500 static unsigned mailtime_hash;
10501 /* Set if MAIL or MAILPATH is changed. */
10502 static smallint mail_var_path_changed;
10503
10504 /*
10505  * Print appropriate message(s) if mail has arrived.
10506  * If mail_var_path_changed is set,
10507  * then the value of MAIL has mail_var_path_changed,
10508  * so we just update the values.
10509  */
10510 static void
10511 chkmail(void)
10512 {
10513         const char *mpath;
10514         char *p;
10515         char *q;
10516         unsigned new_hash;
10517         struct stackmark smark;
10518         struct stat statb;
10519
10520         setstackmark(&smark);
10521         mpath = mpathset() ? mpathval() : mailval();
10522         new_hash = 0;
10523         for (;;) {
10524                 p = path_advance(&mpath, nullstr);
10525                 if (p == NULL)
10526                         break;
10527                 if (*p == '\0')
10528                         continue;
10529                 for (q = p; *q; q++)
10530                         continue;
10531 #if DEBUG
10532                 if (q[-1] != '/')
10533                         abort();
10534 #endif
10535                 q[-1] = '\0';                   /* delete trailing '/' */
10536                 if (stat(p, &statb) < 0) {
10537                         continue;
10538                 }
10539                 /* Very simplistic "hash": just a sum of all mtimes */
10540                 new_hash += (unsigned)statb.st_mtime;
10541         }
10542         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10543                 if (mailtime_hash != 0)
10544                         out2str("you have mail\n");
10545                 mailtime_hash = new_hash;
10546         }
10547         mail_var_path_changed = 0;
10548         popstackmark(&smark);
10549 }
10550
10551 static void FAST_FUNC
10552 changemail(const char *val UNUSED_PARAM)
10553 {
10554         mail_var_path_changed = 1;
10555 }
10556
10557 #endif /* ASH_MAIL */
10558
10559
10560 /* ============ ??? */
10561
10562 /*
10563  * Set the shell parameters.
10564  */
10565 static void
10566 setparam(char **argv)
10567 {
10568         char **newparam;
10569         char **ap;
10570         int nparam;
10571
10572         for (nparam = 0; argv[nparam]; nparam++)
10573                 continue;
10574         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10575         while (*argv) {
10576                 *ap++ = ckstrdup(*argv++);
10577         }
10578         *ap = NULL;
10579         freeparam(&shellparam);
10580         shellparam.malloced = 1;
10581         shellparam.nparam = nparam;
10582         shellparam.p = newparam;
10583 #if ENABLE_ASH_GETOPTS
10584         shellparam.optind = 1;
10585         shellparam.optoff = -1;
10586 #endif
10587 }
10588
10589 /*
10590  * Process shell options.  The global variable argptr contains a pointer
10591  * to the argument list; we advance it past the options.
10592  *
10593  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10594  * For a non-interactive shell, an error condition encountered
10595  * by a special built-in ... shall cause the shell to write a diagnostic message
10596  * to standard error and exit as shown in the following table:
10597  * Error                                           Special Built-In
10598  * ...
10599  * Utility syntax error (option or operand error)  Shall exit
10600  * ...
10601  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10602  * we see that bash does not do that (set "finishes" with error code 1 instead,
10603  * and shell continues), and people rely on this behavior!
10604  * Testcase:
10605  * set -o barfoo 2>/dev/null
10606  * echo $?
10607  *
10608  * Oh well. Let's mimic that.
10609  */
10610 static int
10611 plus_minus_o(char *name, int val)
10612 {
10613         int i;
10614
10615         if (name) {
10616                 for (i = 0; i < NOPTS; i++) {
10617                         if (strcmp(name, optnames(i)) == 0) {
10618                                 optlist[i] = val;
10619                                 return 0;
10620                         }
10621                 }
10622                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10623                 return 1;
10624         }
10625         for (i = 0; i < NOPTS; i++) {
10626                 if (val) {
10627                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10628                 } else {
10629                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10630                 }
10631         }
10632         return 0;
10633 }
10634 static void
10635 setoption(int flag, int val)
10636 {
10637         int i;
10638
10639         for (i = 0; i < NOPTS; i++) {
10640                 if (optletters(i) == flag) {
10641                         optlist[i] = val;
10642                         return;
10643                 }
10644         }
10645         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10646         /* NOTREACHED */
10647 }
10648 static int
10649 options(int cmdline)
10650 {
10651         char *p;
10652         int val;
10653         int c;
10654
10655         if (cmdline)
10656                 minusc = NULL;
10657         while ((p = *argptr) != NULL) {
10658                 c = *p++;
10659                 if (c != '-' && c != '+')
10660                         break;
10661                 argptr++;
10662                 val = 0; /* val = 0 if c == '+' */
10663                 if (c == '-') {
10664                         val = 1;
10665                         if (p[0] == '\0' || LONE_DASH(p)) {
10666                                 if (!cmdline) {
10667                                         /* "-" means turn off -x and -v */
10668                                         if (p[0] == '\0')
10669                                                 xflag = vflag = 0;
10670                                         /* "--" means reset params */
10671                                         else if (*argptr == NULL)
10672                                                 setparam(argptr);
10673                                 }
10674                                 break;    /* "-" or "--" terminates options */
10675                         }
10676                 }
10677                 /* first char was + or - */
10678                 while ((c = *p++) != '\0') {
10679                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10680                         if (c == 'c' && cmdline) {
10681                                 minusc = p;     /* command is after shell args */
10682                         } else if (c == 'o') {
10683                                 if (plus_minus_o(*argptr, val)) {
10684                                         /* it already printed err message */
10685                                         return 1; /* error */
10686                                 }
10687                                 if (*argptr)
10688                                         argptr++;
10689                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10690                                 isloginsh = 1;
10691                         /* bash does not accept +-login, we also won't */
10692                         } else if (cmdline && val && (c == '-')) { /* long options */
10693                                 if (strcmp(p, "login") == 0)
10694                                         isloginsh = 1;
10695                                 break;
10696                         } else {
10697                                 setoption(c, val);
10698                         }
10699                 }
10700         }
10701         return 0;
10702 }
10703
10704 /*
10705  * The shift builtin command.
10706  */
10707 static int FAST_FUNC
10708 shiftcmd(int argc UNUSED_PARAM, char **argv)
10709 {
10710         int n;
10711         char **ap1, **ap2;
10712
10713         n = 1;
10714         if (argv[1])
10715                 n = number(argv[1]);
10716         if (n > shellparam.nparam)
10717                 n = 0; /* bash compat, was = shellparam.nparam; */
10718         INT_OFF;
10719         shellparam.nparam -= n;
10720         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10721                 if (shellparam.malloced)
10722                         free(*ap1);
10723         }
10724         ap2 = shellparam.p;
10725         while ((*ap2++ = *ap1++) != NULL)
10726                 continue;
10727 #if ENABLE_ASH_GETOPTS
10728         shellparam.optind = 1;
10729         shellparam.optoff = -1;
10730 #endif
10731         INT_ON;
10732         return 0;
10733 }
10734
10735 /*
10736  * POSIX requires that 'set' (but not export or readonly) output the
10737  * variables in lexicographic order - by the locale's collating order (sigh).
10738  * Maybe we could keep them in an ordered balanced binary tree
10739  * instead of hashed lists.
10740  * For now just roll 'em through qsort for printing...
10741  */
10742 static int
10743 showvars(const char *sep_prefix, int on, int off)
10744 {
10745         const char *sep;
10746         char **ep, **epend;
10747
10748         ep = listvars(on, off, &epend);
10749         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10750
10751         sep = *sep_prefix ? " " : sep_prefix;
10752
10753         for (; ep < epend; ep++) {
10754                 const char *p;
10755                 const char *q;
10756
10757                 p = strchrnul(*ep, '=');
10758                 q = nullstr;
10759                 if (*p)
10760                         q = single_quote(++p);
10761                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10762         }
10763         return 0;
10764 }
10765
10766 /*
10767  * The set command builtin.
10768  */
10769 static int FAST_FUNC
10770 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10771 {
10772         int retval;
10773
10774         if (!argv[1])
10775                 return showvars(nullstr, 0, VUNSET);
10776
10777         INT_OFF;
10778         retval = options(/*cmdline:*/ 0);
10779         if (retval == 0) { /* if no parse error... */
10780                 optschanged();
10781                 if (*argptr != NULL) {
10782                         setparam(argptr);
10783                 }
10784         }
10785         INT_ON;
10786         return retval;
10787 }
10788
10789 #if ENABLE_ASH_RANDOM_SUPPORT
10790 static void FAST_FUNC
10791 change_random(const char *value)
10792 {
10793         uint32_t t;
10794
10795         if (value == NULL) {
10796                 /* "get", generate */
10797                 t = next_random(&random_gen);
10798                 /* set without recursion */
10799                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10800                 vrandom.flags &= ~VNOFUNC;
10801         } else {
10802                 /* set/reset */
10803                 t = strtoul(value, NULL, 10);
10804                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10805         }
10806 }
10807 #endif
10808
10809 #if ENABLE_ASH_GETOPTS
10810 static int
10811 getopts(char *optstr, char *optvar, char **optfirst)
10812 {
10813         char *p, *q;
10814         char c = '?';
10815         int done = 0;
10816         char sbuf[2];
10817         char **optnext;
10818         int ind = shellparam.optind;
10819         int off = shellparam.optoff;
10820
10821         sbuf[1] = '\0';
10822
10823         shellparam.optind = -1;
10824         optnext = optfirst + ind - 1;
10825
10826         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10827                 p = NULL;
10828         else
10829                 p = optnext[-1] + off;
10830         if (p == NULL || *p == '\0') {
10831                 /* Current word is done, advance */
10832                 p = *optnext;
10833                 if (p == NULL || *p != '-' || *++p == '\0') {
10834  atend:
10835                         p = NULL;
10836                         done = 1;
10837                         goto out;
10838                 }
10839                 optnext++;
10840                 if (LONE_DASH(p))        /* check for "--" */
10841                         goto atend;
10842         }
10843
10844         c = *p++;
10845         for (q = optstr; *q != c;) {
10846                 if (*q == '\0') {
10847                         if (optstr[0] == ':') {
10848                                 sbuf[0] = c;
10849                                 /*sbuf[1] = '\0'; - already is */
10850                                 setvar0("OPTARG", sbuf);
10851                         } else {
10852                                 fprintf(stderr, "Illegal option -%c\n", c);
10853                                 unsetvar("OPTARG");
10854                         }
10855                         c = '?';
10856                         goto out;
10857                 }
10858                 if (*++q == ':')
10859                         q++;
10860         }
10861
10862         if (*++q == ':') {
10863                 if (*p == '\0' && (p = *optnext) == NULL) {
10864                         if (optstr[0] == ':') {
10865                                 sbuf[0] = c;
10866                                 /*sbuf[1] = '\0'; - already is */
10867                                 setvar0("OPTARG", sbuf);
10868                                 c = ':';
10869                         } else {
10870                                 fprintf(stderr, "No arg for -%c option\n", c);
10871                                 unsetvar("OPTARG");
10872                                 c = '?';
10873                         }
10874                         goto out;
10875                 }
10876
10877                 if (p == *optnext)
10878                         optnext++;
10879                 setvar0("OPTARG", p);
10880                 p = NULL;
10881         } else
10882                 setvar0("OPTARG", nullstr);
10883  out:
10884         ind = optnext - optfirst + 1;
10885         setvar("OPTIND", itoa(ind), VNOFUNC);
10886         sbuf[0] = c;
10887         /*sbuf[1] = '\0'; - already is */
10888         setvar0(optvar, sbuf);
10889
10890         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10891         shellparam.optind = ind;
10892
10893         return done;
10894 }
10895
10896 /*
10897  * The getopts builtin.  Shellparam.optnext points to the next argument
10898  * to be processed.  Shellparam.optptr points to the next character to
10899  * be processed in the current argument.  If shellparam.optnext is NULL,
10900  * then it's the first time getopts has been called.
10901  */
10902 static int FAST_FUNC
10903 getoptscmd(int argc, char **argv)
10904 {
10905         char **optbase;
10906
10907         if (argc < 3)
10908                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10909         if (argc == 3) {
10910                 optbase = shellparam.p;
10911                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10912                         shellparam.optind = 1;
10913                         shellparam.optoff = -1;
10914                 }
10915         } else {
10916                 optbase = &argv[3];
10917                 if ((unsigned)shellparam.optind > argc - 2) {
10918                         shellparam.optind = 1;
10919                         shellparam.optoff = -1;
10920                 }
10921         }
10922
10923         return getopts(argv[1], argv[2], optbase);
10924 }
10925 #endif /* ASH_GETOPTS */
10926
10927
10928 /* ============ Shell parser */
10929
10930 struct heredoc {
10931         struct heredoc *next;   /* next here document in list */
10932         union node *here;       /* redirection node */
10933         char *eofmark;          /* string indicating end of input */
10934         smallint striptabs;     /* if set, strip leading tabs */
10935 };
10936
10937 static smallint tokpushback;           /* last token pushed back */
10938 static smallint quoteflag;             /* set if (part of) last token was quoted */
10939 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10940 static struct heredoc *heredoclist;    /* list of here documents to read */
10941 static char *wordtext;                 /* text of last word returned by readtoken */
10942 static struct nodelist *backquotelist;
10943 static union node *redirnode;
10944 static struct heredoc *heredoc;
10945
10946 static const char *
10947 tokname(char *buf, int tok)
10948 {
10949         if (tok < TSEMI)
10950                 return tokname_array[tok];
10951         sprintf(buf, "\"%s\"", tokname_array[tok]);
10952         return buf;
10953 }
10954
10955 /* raise_error_unexpected_syntax:
10956  * Called when an unexpected token is read during the parse.  The argument
10957  * is the token that is expected, or -1 if more than one type of token can
10958  * occur at this point.
10959  */
10960 static void raise_error_unexpected_syntax(int) NORETURN;
10961 static void
10962 raise_error_unexpected_syntax(int token)
10963 {
10964         char msg[64];
10965         char buf[16];
10966         int l;
10967
10968         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10969         if (token >= 0)
10970                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10971         raise_error_syntax(msg);
10972         /* NOTREACHED */
10973 }
10974
10975 #define EOFMARKLEN 79
10976
10977 /* parsing is heavily cross-recursive, need these forward decls */
10978 static union node *andor(void);
10979 static union node *pipeline(void);
10980 static union node *parse_command(void);
10981 static void parseheredoc(void);
10982 static int peektoken(void);
10983 static int readtoken(void);
10984
10985 static union node *
10986 list(int nlflag)
10987 {
10988         union node *n1, *n2, *n3;
10989         int tok;
10990
10991         n1 = NULL;
10992         for (;;) {
10993                 switch (peektoken()) {
10994                 case TNL:
10995                         if (!(nlflag & 1))
10996                                 break;
10997                         parseheredoc();
10998                         return n1;
10999
11000                 case TEOF:
11001                         if (!n1 && (nlflag & 1))
11002                                 n1 = NODE_EOF;
11003                         parseheredoc();
11004                         return n1;
11005                 }
11006
11007                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11008                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11009                         return n1;
11010                 nlflag |= 2;
11011
11012                 n2 = andor();
11013                 tok = readtoken();
11014                 if (tok == TBACKGND) {
11015                         if (n2->type == NPIPE) {
11016                                 n2->npipe.pipe_backgnd = 1;
11017                         } else {
11018                                 if (n2->type != NREDIR) {
11019                                         n3 = stzalloc(sizeof(struct nredir));
11020                                         n3->nredir.n = n2;
11021                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11022                                         n2 = n3;
11023                                 }
11024                                 n2->type = NBACKGND;
11025                         }
11026                 }
11027                 if (n1 == NULL) {
11028                         n1 = n2;
11029                 } else {
11030                         n3 = stzalloc(sizeof(struct nbinary));
11031                         n3->type = NSEMI;
11032                         n3->nbinary.ch1 = n1;
11033                         n3->nbinary.ch2 = n2;
11034                         n1 = n3;
11035                 }
11036                 switch (tok) {
11037                 case TNL:
11038                 case TEOF:
11039                         tokpushback = 1;
11040                         /* fall through */
11041                 case TBACKGND:
11042                 case TSEMI:
11043                         break;
11044                 default:
11045                         if ((nlflag & 1))
11046                                 raise_error_unexpected_syntax(-1);
11047                         tokpushback = 1;
11048                         return n1;
11049                 }
11050         }
11051 }
11052
11053 static union node *
11054 andor(void)
11055 {
11056         union node *n1, *n2, *n3;
11057         int t;
11058
11059         n1 = pipeline();
11060         for (;;) {
11061                 t = readtoken();
11062                 if (t == TAND) {
11063                         t = NAND;
11064                 } else if (t == TOR) {
11065                         t = NOR;
11066                 } else {
11067                         tokpushback = 1;
11068                         return n1;
11069                 }
11070                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11071                 n2 = pipeline();
11072                 n3 = stzalloc(sizeof(struct nbinary));
11073                 n3->type = t;
11074                 n3->nbinary.ch1 = n1;
11075                 n3->nbinary.ch2 = n2;
11076                 n1 = n3;
11077         }
11078 }
11079
11080 static union node *
11081 pipeline(void)
11082 {
11083         union node *n1, *n2, *pipenode;
11084         struct nodelist *lp, *prev;
11085         int negate;
11086
11087         negate = 0;
11088         TRACE(("pipeline: entered\n"));
11089         if (readtoken() == TNOT) {
11090                 negate = !negate;
11091                 checkkwd = CHKKWD | CHKALIAS;
11092         } else
11093                 tokpushback = 1;
11094         n1 = parse_command();
11095         if (readtoken() == TPIPE) {
11096                 pipenode = stzalloc(sizeof(struct npipe));
11097                 pipenode->type = NPIPE;
11098                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11099                 lp = stzalloc(sizeof(struct nodelist));
11100                 pipenode->npipe.cmdlist = lp;
11101                 lp->n = n1;
11102                 do {
11103                         prev = lp;
11104                         lp = stzalloc(sizeof(struct nodelist));
11105                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11106                         lp->n = parse_command();
11107                         prev->next = lp;
11108                 } while (readtoken() == TPIPE);
11109                 lp->next = NULL;
11110                 n1 = pipenode;
11111         }
11112         tokpushback = 1;
11113         if (negate) {
11114                 n2 = stzalloc(sizeof(struct nnot));
11115                 n2->type = NNOT;
11116                 n2->nnot.com = n1;
11117                 return n2;
11118         }
11119         return n1;
11120 }
11121
11122 static union node *
11123 makename(void)
11124 {
11125         union node *n;
11126
11127         n = stzalloc(sizeof(struct narg));
11128         n->type = NARG;
11129         /*n->narg.next = NULL; - stzalloc did it */
11130         n->narg.text = wordtext;
11131         n->narg.backquote = backquotelist;
11132         return n;
11133 }
11134
11135 static void
11136 fixredir(union node *n, const char *text, int err)
11137 {
11138         int fd;
11139
11140         TRACE(("Fix redir %s %d\n", text, err));
11141         if (!err)
11142                 n->ndup.vname = NULL;
11143
11144         fd = bb_strtou(text, NULL, 10);
11145         if (!errno && fd >= 0)
11146                 n->ndup.dupfd = fd;
11147         else if (LONE_DASH(text))
11148                 n->ndup.dupfd = -1;
11149         else {
11150                 if (err)
11151                         raise_error_syntax("bad fd number");
11152                 n->ndup.vname = makename();
11153         }
11154 }
11155
11156 /*
11157  * Returns true if the text contains nothing to expand (no dollar signs
11158  * or backquotes).
11159  */
11160 static int
11161 noexpand(const char *text)
11162 {
11163         unsigned char c;
11164
11165         while ((c = *text++) != '\0') {
11166                 if (c == CTLQUOTEMARK)
11167                         continue;
11168                 if (c == CTLESC)
11169                         text++;
11170                 else if (SIT(c, BASESYNTAX) == CCTL)
11171                         return 0;
11172         }
11173         return 1;
11174 }
11175
11176 static void
11177 parsefname(void)
11178 {
11179         union node *n = redirnode;
11180
11181         if (readtoken() != TWORD)
11182                 raise_error_unexpected_syntax(-1);
11183         if (n->type == NHERE) {
11184                 struct heredoc *here = heredoc;
11185                 struct heredoc *p;
11186                 int i;
11187
11188                 if (quoteflag == 0)
11189                         n->type = NXHERE;
11190                 TRACE(("Here document %d\n", n->type));
11191                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11192                         raise_error_syntax("illegal eof marker for << redirection");
11193                 rmescapes(wordtext, 0);
11194                 here->eofmark = wordtext;
11195                 here->next = NULL;
11196                 if (heredoclist == NULL)
11197                         heredoclist = here;
11198                 else {
11199                         for (p = heredoclist; p->next; p = p->next)
11200                                 continue;
11201                         p->next = here;
11202                 }
11203         } else if (n->type == NTOFD || n->type == NFROMFD) {
11204                 fixredir(n, wordtext, 0);
11205         } else {
11206                 n->nfile.fname = makename();
11207         }
11208 }
11209
11210 static union node *
11211 simplecmd(void)
11212 {
11213         union node *args, **app;
11214         union node *n = NULL;
11215         union node *vars, **vpp;
11216         union node **rpp, *redir;
11217         int savecheckkwd;
11218 #if BASH_TEST2
11219         smallint double_brackets_flag = 0;
11220 #endif
11221         IF_BASH_FUNCTION(smallint function_flag = 0;)
11222
11223         args = NULL;
11224         app = &args;
11225         vars = NULL;
11226         vpp = &vars;
11227         redir = NULL;
11228         rpp = &redir;
11229
11230         savecheckkwd = CHKALIAS;
11231         for (;;) {
11232                 int t;
11233                 checkkwd = savecheckkwd;
11234                 t = readtoken();
11235                 switch (t) {
11236 #if BASH_FUNCTION
11237                 case TFUNCTION:
11238                         if (peektoken() != TWORD)
11239                                 raise_error_unexpected_syntax(TWORD);
11240                         function_flag = 1;
11241                         break;
11242 #endif
11243 #if BASH_TEST2
11244                 case TAND: /* "&&" */
11245                 case TOR: /* "||" */
11246                         if (!double_brackets_flag) {
11247                                 tokpushback = 1;
11248                                 goto out;
11249                         }
11250                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11251 #endif
11252                 case TWORD:
11253                         n = stzalloc(sizeof(struct narg));
11254                         n->type = NARG;
11255                         /*n->narg.next = NULL; - stzalloc did it */
11256                         n->narg.text = wordtext;
11257 #if BASH_TEST2
11258                         if (strcmp("[[", wordtext) == 0)
11259                                 double_brackets_flag = 1;
11260                         else if (strcmp("]]", wordtext) == 0)
11261                                 double_brackets_flag = 0;
11262 #endif
11263                         n->narg.backquote = backquotelist;
11264                         if (savecheckkwd && isassignment(wordtext)) {
11265                                 *vpp = n;
11266                                 vpp = &n->narg.next;
11267                         } else {
11268                                 *app = n;
11269                                 app = &n->narg.next;
11270                                 savecheckkwd = 0;
11271                         }
11272 #if BASH_FUNCTION
11273                         if (function_flag) {
11274                                 checkkwd = CHKNL | CHKKWD;
11275                                 switch (peektoken()) {
11276                                 case TBEGIN:
11277                                 case TIF:
11278                                 case TCASE:
11279                                 case TUNTIL:
11280                                 case TWHILE:
11281                                 case TFOR:
11282                                         goto do_func;
11283                                 case TLP:
11284                                         function_flag = 0;
11285                                         break;
11286                                 case TWORD:
11287                                         if (strcmp("[[", wordtext) == 0)
11288                                                 goto do_func;
11289                                         /* fall through */
11290                                 default:
11291                                         raise_error_unexpected_syntax(-1);
11292                                 }
11293                         }
11294 #endif
11295                         break;
11296                 case TREDIR:
11297                         *rpp = n = redirnode;
11298                         rpp = &n->nfile.next;
11299                         parsefname();   /* read name of redirection file */
11300                         break;
11301                 case TLP:
11302  IF_BASH_FUNCTION(do_func:)
11303                         if (args && app == &args->narg.next
11304                          && !vars && !redir
11305                         ) {
11306                                 struct builtincmd *bcmd;
11307                                 const char *name;
11308
11309                                 /* We have a function */
11310                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11311                                         raise_error_unexpected_syntax(TRP);
11312                                 name = n->narg.text;
11313                                 if (!goodname(name)
11314                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11315                                 ) {
11316                                         raise_error_syntax("bad function name");
11317                                 }
11318                                 n->type = NDEFUN;
11319                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11320                                 n->narg.next = parse_command();
11321                                 return n;
11322                         }
11323                         IF_BASH_FUNCTION(function_flag = 0;)
11324                         /* fall through */
11325                 default:
11326                         tokpushback = 1;
11327                         goto out;
11328                 }
11329         }
11330  out:
11331         *app = NULL;
11332         *vpp = NULL;
11333         *rpp = NULL;
11334         n = stzalloc(sizeof(struct ncmd));
11335         n->type = NCMD;
11336         n->ncmd.args = args;
11337         n->ncmd.assign = vars;
11338         n->ncmd.redirect = redir;
11339         return n;
11340 }
11341
11342 static union node *
11343 parse_command(void)
11344 {
11345         union node *n1, *n2;
11346         union node *ap, **app;
11347         union node *cp, **cpp;
11348         union node *redir, **rpp;
11349         union node **rpp2;
11350         int t;
11351
11352         redir = NULL;
11353         rpp2 = &redir;
11354
11355         switch (readtoken()) {
11356         default:
11357                 raise_error_unexpected_syntax(-1);
11358                 /* NOTREACHED */
11359         case TIF:
11360                 n1 = stzalloc(sizeof(struct nif));
11361                 n1->type = NIF;
11362                 n1->nif.test = list(0);
11363                 if (readtoken() != TTHEN)
11364                         raise_error_unexpected_syntax(TTHEN);
11365                 n1->nif.ifpart = list(0);
11366                 n2 = n1;
11367                 while (readtoken() == TELIF) {
11368                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11369                         n2 = n2->nif.elsepart;
11370                         n2->type = NIF;
11371                         n2->nif.test = list(0);
11372                         if (readtoken() != TTHEN)
11373                                 raise_error_unexpected_syntax(TTHEN);
11374                         n2->nif.ifpart = list(0);
11375                 }
11376                 if (lasttoken == TELSE)
11377                         n2->nif.elsepart = list(0);
11378                 else {
11379                         n2->nif.elsepart = NULL;
11380                         tokpushback = 1;
11381                 }
11382                 t = TFI;
11383                 break;
11384         case TWHILE:
11385         case TUNTIL: {
11386                 int got;
11387                 n1 = stzalloc(sizeof(struct nbinary));
11388                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11389                 n1->nbinary.ch1 = list(0);
11390                 got = readtoken();
11391                 if (got != TDO) {
11392                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11393                                         got == TWORD ? wordtext : ""));
11394                         raise_error_unexpected_syntax(TDO);
11395                 }
11396                 n1->nbinary.ch2 = list(0);
11397                 t = TDONE;
11398                 break;
11399         }
11400         case TFOR:
11401                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11402                         raise_error_syntax("bad for loop variable");
11403                 n1 = stzalloc(sizeof(struct nfor));
11404                 n1->type = NFOR;
11405                 n1->nfor.var = wordtext;
11406                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11407                 if (readtoken() == TIN) {
11408                         app = &ap;
11409                         while (readtoken() == TWORD) {
11410                                 n2 = stzalloc(sizeof(struct narg));
11411                                 n2->type = NARG;
11412                                 /*n2->narg.next = NULL; - stzalloc did it */
11413                                 n2->narg.text = wordtext;
11414                                 n2->narg.backquote = backquotelist;
11415                                 *app = n2;
11416                                 app = &n2->narg.next;
11417                         }
11418                         *app = NULL;
11419                         n1->nfor.args = ap;
11420                         if (lasttoken != TNL && lasttoken != TSEMI)
11421                                 raise_error_unexpected_syntax(-1);
11422                 } else {
11423                         n2 = stzalloc(sizeof(struct narg));
11424                         n2->type = NARG;
11425                         /*n2->narg.next = NULL; - stzalloc did it */
11426                         n2->narg.text = (char *)dolatstr;
11427                         /*n2->narg.backquote = NULL;*/
11428                         n1->nfor.args = n2;
11429                         /*
11430                          * Newline or semicolon here is optional (but note
11431                          * that the original Bourne shell only allowed NL).
11432                          */
11433                         if (lasttoken != TSEMI)
11434                                 tokpushback = 1;
11435                 }
11436                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11437                 if (readtoken() != TDO)
11438                         raise_error_unexpected_syntax(TDO);
11439                 n1->nfor.body = list(0);
11440                 t = TDONE;
11441                 break;
11442         case TCASE:
11443                 n1 = stzalloc(sizeof(struct ncase));
11444                 n1->type = NCASE;
11445                 if (readtoken() != TWORD)
11446                         raise_error_unexpected_syntax(TWORD);
11447                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11448                 n2->type = NARG;
11449                 /*n2->narg.next = NULL; - stzalloc did it */
11450                 n2->narg.text = wordtext;
11451                 n2->narg.backquote = backquotelist;
11452                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11453                 if (readtoken() != TIN)
11454                         raise_error_unexpected_syntax(TIN);
11455                 cpp = &n1->ncase.cases;
11456  next_case:
11457                 checkkwd = CHKNL | CHKKWD;
11458                 t = readtoken();
11459                 while (t != TESAC) {
11460                         if (lasttoken == TLP)
11461                                 readtoken();
11462                         *cpp = cp = stzalloc(sizeof(struct nclist));
11463                         cp->type = NCLIST;
11464                         app = &cp->nclist.pattern;
11465                         for (;;) {
11466                                 *app = ap = stzalloc(sizeof(struct narg));
11467                                 ap->type = NARG;
11468                                 /*ap->narg.next = NULL; - stzalloc did it */
11469                                 ap->narg.text = wordtext;
11470                                 ap->narg.backquote = backquotelist;
11471                                 if (readtoken() != TPIPE)
11472                                         break;
11473                                 app = &ap->narg.next;
11474                                 readtoken();
11475                         }
11476                         //ap->narg.next = NULL;
11477                         if (lasttoken != TRP)
11478                                 raise_error_unexpected_syntax(TRP);
11479                         cp->nclist.body = list(2);
11480
11481                         cpp = &cp->nclist.next;
11482
11483                         checkkwd = CHKNL | CHKKWD;
11484                         t = readtoken();
11485                         if (t != TESAC) {
11486                                 if (t != TENDCASE)
11487                                         raise_error_unexpected_syntax(TENDCASE);
11488                                 goto next_case;
11489                         }
11490                 }
11491                 *cpp = NULL;
11492                 goto redir;
11493         case TLP:
11494                 n1 = stzalloc(sizeof(struct nredir));
11495                 n1->type = NSUBSHELL;
11496                 n1->nredir.n = list(0);
11497                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11498                 t = TRP;
11499                 break;
11500         case TBEGIN:
11501                 n1 = list(0);
11502                 t = TEND;
11503                 break;
11504         IF_BASH_FUNCTION(case TFUNCTION:)
11505         case TWORD:
11506         case TREDIR:
11507                 tokpushback = 1;
11508                 return simplecmd();
11509         }
11510
11511         if (readtoken() != t)
11512                 raise_error_unexpected_syntax(t);
11513
11514  redir:
11515         /* Now check for redirection which may follow command */
11516         checkkwd = CHKKWD | CHKALIAS;
11517         rpp = rpp2;
11518         while (readtoken() == TREDIR) {
11519                 *rpp = n2 = redirnode;
11520                 rpp = &n2->nfile.next;
11521                 parsefname();
11522         }
11523         tokpushback = 1;
11524         *rpp = NULL;
11525         if (redir) {
11526                 if (n1->type != NSUBSHELL) {
11527                         n2 = stzalloc(sizeof(struct nredir));
11528                         n2->type = NREDIR;
11529                         n2->nredir.n = n1;
11530                         n1 = n2;
11531                 }
11532                 n1->nredir.redirect = redir;
11533         }
11534         return n1;
11535 }
11536
11537 #if BASH_DOLLAR_SQUOTE
11538 static int
11539 decode_dollar_squote(void)
11540 {
11541         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11542         int c, cnt;
11543         char *p;
11544         char buf[4];
11545
11546         c = pgetc();
11547         p = strchr(C_escapes, c);
11548         if (p) {
11549                 buf[0] = c;
11550                 p = buf;
11551                 cnt = 3;
11552                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11553                         do {
11554                                 c = pgetc();
11555                                 *++p = c;
11556                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11557                         pungetc();
11558                 } else if (c == 'x') { /* \xHH */
11559                         do {
11560                                 c = pgetc();
11561                                 *++p = c;
11562                         } while (isxdigit(c) && --cnt);
11563                         pungetc();
11564                         if (cnt == 3) { /* \x but next char is "bad" */
11565                                 c = 'x';
11566                                 goto unrecognized;
11567                         }
11568                 } else { /* simple seq like \\ or \t */
11569                         p++;
11570                 }
11571                 *p = '\0';
11572                 p = buf;
11573                 c = bb_process_escape_sequence((void*)&p);
11574         } else { /* unrecognized "\z": print both chars unless ' or " */
11575                 if (c != '\'' && c != '"') {
11576  unrecognized:
11577                         c |= 0x100; /* "please encode \, then me" */
11578                 }
11579         }
11580         return c;
11581 }
11582 #endif
11583
11584 /*
11585  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11586  * is not NULL, read a here document.  In the latter case, eofmark is the
11587  * word which marks the end of the document and striptabs is true if
11588  * leading tabs should be stripped from the document.  The argument c
11589  * is the first character of the input token or document.
11590  *
11591  * Because C does not have internal subroutines, I have simulated them
11592  * using goto's to implement the subroutine linkage.  The following macros
11593  * will run code that appears at the end of readtoken1.
11594  */
11595 #define CHECKEND()      {goto checkend; checkend_return:;}
11596 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11597 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11598 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11599 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11600 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11601 static int
11602 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11603 {
11604         /* NB: syntax parameter fits into smallint */
11605         /* c parameter is an unsigned char or PEOF or PEOA */
11606         char *out;
11607         size_t len;
11608         char line[EOFMARKLEN + 1];
11609         struct nodelist *bqlist;
11610         smallint quotef;
11611         smallint dblquote;
11612         smallint oldstyle;
11613         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11614         smallint pssyntax;   /* we are expanding a prompt string */
11615         int varnest;         /* levels of variables expansion */
11616         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11617         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11618         int dqvarnest;       /* levels of variables expansion within double quotes */
11619
11620         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11621
11622         startlinno = g_parsefile->linno;
11623         bqlist = NULL;
11624         quotef = 0;
11625         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11626         pssyntax = (syntax == PSSYNTAX);
11627         if (pssyntax)
11628                 syntax = DQSYNTAX;
11629         dblquote = (syntax == DQSYNTAX);
11630         varnest = 0;
11631         IF_FEATURE_SH_MATH(arinest = 0;)
11632         IF_FEATURE_SH_MATH(parenlevel = 0;)
11633         dqvarnest = 0;
11634
11635         STARTSTACKSTR(out);
11636  loop:
11637         /* For each line, until end of word */
11638         CHECKEND();     /* set c to PEOF if at end of here document */
11639         for (;;) {      /* until end of line or end of word */
11640                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11641                 switch (SIT(c, syntax)) {
11642                 case CNL:       /* '\n' */
11643                         if (syntax == BASESYNTAX)
11644                                 goto endword;   /* exit outer loop */
11645                         USTPUTC(c, out);
11646                         nlprompt();
11647                         c = pgetc();
11648                         goto loop;              /* continue outer loop */
11649                 case CWORD:
11650                         USTPUTC(c, out);
11651                         break;
11652                 case CCTL:
11653 #if BASH_DOLLAR_SQUOTE
11654                         if (c == '\\' && bash_dollar_squote) {
11655                                 c = decode_dollar_squote();
11656                                 if (c == '\0') {
11657                                         /* skip $'\000', $'\x00' (like bash) */
11658                                         break;
11659                                 }
11660                                 if (c & 0x100) {
11661                                         /* Unknown escape. Encode as '\z' */
11662                                         c = (unsigned char)c;
11663                                         if (eofmark == NULL || dblquote)
11664                                                 USTPUTC(CTLESC, out);
11665                                         USTPUTC('\\', out);
11666                                 }
11667                         }
11668 #endif
11669                         if (eofmark == NULL || dblquote)
11670                                 USTPUTC(CTLESC, out);
11671                         USTPUTC(c, out);
11672                         break;
11673                 case CBACK:     /* backslash */
11674                         c = pgetc_without_PEOA();
11675                         if (c == PEOF) {
11676                                 USTPUTC(CTLESC, out);
11677                                 USTPUTC('\\', out);
11678                                 pungetc();
11679                         } else if (c == '\n') {
11680                                 nlprompt();
11681                         } else {
11682                                 if (c == '$' && pssyntax) {
11683                                         USTPUTC(CTLESC, out);
11684                                         USTPUTC('\\', out);
11685                                 }
11686                                 /* Backslash is retained if we are in "str" and next char isn't special */
11687                                 if (dblquote
11688                                  && c != '\\'
11689                                  && c != '`'
11690                                  && c != '$'
11691                                  && (c != '"' || eofmark != NULL)
11692                                 ) {
11693                                         USTPUTC('\\', out);
11694                                 }
11695                                 USTPUTC(CTLESC, out);
11696                                 USTPUTC(c, out);
11697                                 quotef = 1;
11698                         }
11699                         break;
11700                 case CSQUOTE:
11701                         syntax = SQSYNTAX;
11702  quotemark:
11703                         if (eofmark == NULL) {
11704                                 USTPUTC(CTLQUOTEMARK, out);
11705                         }
11706                         break;
11707                 case CDQUOTE:
11708                         syntax = DQSYNTAX;
11709                         dblquote = 1;
11710                         goto quotemark;
11711                 case CENDQUOTE:
11712                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11713                         if (eofmark != NULL && varnest == 0) {
11714                                 USTPUTC(c, out);
11715                         } else {
11716                                 if (dqvarnest == 0) {
11717                                         syntax = BASESYNTAX;
11718                                         dblquote = 0;
11719                                 }
11720                                 quotef = 1;
11721                                 goto quotemark;
11722                         }
11723                         break;
11724                 case CVAR:      /* '$' */
11725                         PARSESUB();             /* parse substitution */
11726                         break;
11727                 case CENDVAR:   /* '}' */
11728                         if (varnest > 0) {
11729                                 varnest--;
11730                                 if (dqvarnest > 0) {
11731                                         dqvarnest--;
11732                                 }
11733                                 c = CTLENDVAR;
11734                         }
11735                         USTPUTC(c, out);
11736                         break;
11737 #if ENABLE_FEATURE_SH_MATH
11738                 case CLP:       /* '(' in arithmetic */
11739                         parenlevel++;
11740                         USTPUTC(c, out);
11741                         break;
11742                 case CRP:       /* ')' in arithmetic */
11743                         if (parenlevel > 0) {
11744                                 parenlevel--;
11745                         } else {
11746                                 if (pgetc_eatbnl() == ')') {
11747                                         c = CTLENDARI;
11748                                         if (--arinest == 0) {
11749                                                 syntax = prevsyntax;
11750                                         }
11751                                 } else {
11752                                         /*
11753                                          * unbalanced parens
11754                                          * (don't 2nd guess - no error)
11755                                          */
11756                                         pungetc();
11757                                 }
11758                         }
11759                         USTPUTC(c, out);
11760                         break;
11761 #endif
11762                 case CBQUOTE:   /* '`' */
11763                         PARSEBACKQOLD();
11764                         break;
11765                 case CENDFILE:
11766                         goto endword;           /* exit outer loop */
11767                 case CIGN:
11768                         break;
11769                 default:
11770                         if (varnest == 0) {
11771 #if BASH_REDIR_OUTPUT
11772                                 if (c == '&') {
11773 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11774                                         if (pgetc() == '>')
11775                                                 c = 0x100 + '>'; /* flag &> */
11776                                         pungetc();
11777                                 }
11778 #endif
11779                                 goto endword;   /* exit outer loop */
11780                         }
11781                         IF_ASH_ALIAS(if (c != PEOA))
11782                                 USTPUTC(c, out);
11783                 }
11784                 c = pgetc();
11785         } /* for (;;) */
11786  endword:
11787
11788 #if ENABLE_FEATURE_SH_MATH
11789         if (syntax == ARISYNTAX)
11790                 raise_error_syntax("missing '))'");
11791 #endif
11792         if (syntax != BASESYNTAX && eofmark == NULL)
11793                 raise_error_syntax("unterminated quoted string");
11794         if (varnest != 0) {
11795                 startlinno = g_parsefile->linno;
11796                 /* { */
11797                 raise_error_syntax("missing '}'");
11798         }
11799         USTPUTC('\0', out);
11800         len = out - (char *)stackblock();
11801         out = stackblock();
11802         if (eofmark == NULL) {
11803                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11804                  && quotef == 0
11805                 ) {
11806                         if (isdigit_str9(out)) {
11807                                 PARSEREDIR(); /* passed as params: out, c */
11808                                 lasttoken = TREDIR;
11809                                 return lasttoken;
11810                         }
11811                         /* else: non-number X seen, interpret it
11812                          * as "NNNX>file" = "NNNX >file" */
11813                 }
11814                 pungetc();
11815         }
11816         quoteflag = quotef;
11817         backquotelist = bqlist;
11818         grabstackblock(len);
11819         wordtext = out;
11820         lasttoken = TWORD;
11821         return lasttoken;
11822 /* end of readtoken routine */
11823
11824 /*
11825  * Check to see whether we are at the end of the here document.  When this
11826  * is called, c is set to the first character of the next input line.  If
11827  * we are at the end of the here document, this routine sets the c to PEOF.
11828  */
11829 checkend: {
11830         if (eofmark) {
11831 #if ENABLE_ASH_ALIAS
11832                 if (c == PEOA)
11833                         c = pgetc_without_PEOA();
11834 #endif
11835                 if (striptabs) {
11836                         while (c == '\t') {
11837                                 c = pgetc_without_PEOA();
11838                         }
11839                 }
11840                 if (c == *eofmark) {
11841                         if (pfgets(line, sizeof(line)) != NULL) {
11842                                 char *p, *q;
11843                                 int cc;
11844
11845                                 p = line;
11846                                 for (q = eofmark + 1;; p++, q++) {
11847                                         cc = *p;
11848                                         if (cc == '\n')
11849                                                 cc = 0;
11850                                         if (!*q || cc != *q)
11851                                                 break;
11852                                 }
11853                                 if (cc == *q) {
11854                                         c = PEOF;
11855                                         nlnoprompt();
11856                                 } else {
11857                                         pushstring(line, NULL);
11858                                 }
11859                         }
11860                 }
11861         }
11862         goto checkend_return;
11863 }
11864
11865 /*
11866  * Parse a redirection operator.  The variable "out" points to a string
11867  * specifying the fd to be redirected.  The variable "c" contains the
11868  * first character of the redirection operator.
11869  */
11870 parseredir: {
11871         /* out is already checked to be a valid number or "" */
11872         int fd = (*out == '\0' ? -1 : atoi(out));
11873         union node *np;
11874
11875         np = stzalloc(sizeof(struct nfile));
11876         if (c == '>') {
11877                 np->nfile.fd = 1;
11878                 c = pgetc();
11879                 if (c == '>')
11880                         np->type = NAPPEND;
11881                 else if (c == '|')
11882                         np->type = NCLOBBER;
11883                 else if (c == '&')
11884                         np->type = NTOFD;
11885                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11886                 else {
11887                         np->type = NTO;
11888                         pungetc();
11889                 }
11890         }
11891 #if BASH_REDIR_OUTPUT
11892         else if (c == 0x100 + '>') { /* this flags &> redirection */
11893                 np->nfile.fd = 1;
11894                 pgetc(); /* this is '>', no need to check */
11895                 np->type = NTO2;
11896         }
11897 #endif
11898         else { /* c == '<' */
11899                 /*np->nfile.fd = 0; - stzalloc did it */
11900                 c = pgetc();
11901                 switch (c) {
11902                 case '<':
11903                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11904                                 np = stzalloc(sizeof(struct nhere));
11905                                 /*np->nfile.fd = 0; - stzalloc did it */
11906                         }
11907                         np->type = NHERE;
11908                         heredoc = stzalloc(sizeof(struct heredoc));
11909                         heredoc->here = np;
11910                         c = pgetc();
11911                         if (c == '-') {
11912                                 heredoc->striptabs = 1;
11913                         } else {
11914                                 /*heredoc->striptabs = 0; - stzalloc did it */
11915                                 pungetc();
11916                         }
11917                         break;
11918
11919                 case '&':
11920                         np->type = NFROMFD;
11921                         break;
11922
11923                 case '>':
11924                         np->type = NFROMTO;
11925                         break;
11926
11927                 default:
11928                         np->type = NFROM;
11929                         pungetc();
11930                         break;
11931                 }
11932         }
11933         if (fd >= 0)
11934                 np->nfile.fd = fd;
11935         redirnode = np;
11936         goto parseredir_return;
11937 }
11938
11939 /*
11940  * Parse a substitution.  At this point, we have read the dollar sign
11941  * and nothing else.
11942  */
11943
11944 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11945  * (assuming ascii char codes, as the original implementation did) */
11946 #define is_special(c) \
11947         (((unsigned)(c) - 33 < 32) \
11948                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11949 parsesub: {
11950         unsigned char subtype;
11951         int typeloc;
11952
11953         c = pgetc_eatbnl();
11954         if (c > 255 /* PEOA or PEOF */
11955          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11956         ) {
11957 #if BASH_DOLLAR_SQUOTE
11958                 if (syntax != DQSYNTAX && c == '\'')
11959                         bash_dollar_squote = 1;
11960                 else
11961 #endif
11962                         USTPUTC('$', out);
11963                 pungetc();
11964         } else if (c == '(') {
11965                 /* $(command) or $((arith)) */
11966                 if (pgetc_eatbnl() == '(') {
11967 #if ENABLE_FEATURE_SH_MATH
11968                         PARSEARITH();
11969 #else
11970                         raise_error_syntax("support for $((arith)) is disabled");
11971 #endif
11972                 } else {
11973                         pungetc();
11974                         PARSEBACKQNEW();
11975                 }
11976         } else {
11977                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11978                 USTPUTC(CTLVAR, out);
11979                 typeloc = out - (char *)stackblock();
11980                 STADJUST(1, out);
11981                 subtype = VSNORMAL;
11982                 if (c == '{') {
11983                         c = pgetc_eatbnl();
11984                         subtype = 0;
11985                 }
11986  varname:
11987                 if (is_name(c)) {
11988                         /* $[{[#]]NAME[}] */
11989                         do {
11990                                 STPUTC(c, out);
11991                                 c = pgetc_eatbnl();
11992                         } while (is_in_name(c));
11993                 } else if (isdigit(c)) {
11994                         /* $[{[#]]NUM[}] */
11995                         do {
11996                                 STPUTC(c, out);
11997                                 c = pgetc_eatbnl();
11998                         } while (isdigit(c));
11999                 } else if (is_special(c)) {
12000                         /* $[{[#]]<specialchar>[}] */
12001                         int cc = c;
12002
12003                         c = pgetc_eatbnl();
12004                         if (!subtype && cc == '#') {
12005                                 subtype = VSLENGTH;
12006                                 if (c == '_' || isalnum(c))
12007                                         goto varname;
12008                                 cc = c;
12009                                 c = pgetc_eatbnl();
12010                                 if (cc == '}' || c != '}') {
12011                                         pungetc();
12012                                         subtype = 0;
12013                                         c = cc;
12014                                         cc = '#';
12015                                 }
12016                         }
12017                         USTPUTC(cc, out);
12018                 } else {
12019                         goto badsub;
12020                 }
12021                 if (c != '}' && subtype == VSLENGTH) {
12022                         /* ${#VAR didn't end with } */
12023                         goto badsub;
12024                 }
12025
12026                 if (subtype == 0) {
12027                         static const char types[] ALIGN1 = "}-+?=";
12028                         /* ${VAR...} but not $VAR or ${#VAR} */
12029                         /* c == first char after VAR */
12030                         switch (c) {
12031                         case ':':
12032                                 c = pgetc_eatbnl();
12033 #if BASH_SUBSTR
12034                                 /* This check is only needed to not misinterpret
12035                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12036                                  * constructs.
12037                                  */
12038                                 if (!strchr(types, c)) {
12039                                         subtype = VSSUBSTR;
12040                                         pungetc();
12041                                         break; /* "goto badsub" is bigger (!) */
12042                                 }
12043 #endif
12044                                 subtype = VSNUL;
12045                                 /*FALLTHROUGH*/
12046                         default: {
12047                                 const char *p = strchr(types, c);
12048                                 if (p == NULL)
12049                                         break;
12050                                 subtype |= p - types + VSNORMAL;
12051                                 break;
12052                         }
12053                         case '%':
12054                         case '#': {
12055                                 int cc = c;
12056                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12057                                 c = pgetc_eatbnl();
12058                                 if (c != cc)
12059                                         goto badsub;
12060                                 subtype++;
12061                                 break;
12062                         }
12063 #if BASH_PATTERN_SUBST
12064                         case '/':
12065                                 /* ${v/[/]pattern/repl} */
12066 //TODO: encode pattern and repl separately.
12067 // Currently ${v/$var_with_slash/repl} is horribly broken
12068                                 subtype = VSREPLACE;
12069                                 c = pgetc_eatbnl();
12070                                 if (c != '/')
12071                                         goto badsub;
12072                                 subtype++; /* VSREPLACEALL */
12073                                 break;
12074 #endif
12075                         }
12076                 } else {
12077  badsub:
12078                         pungetc();
12079                 }
12080                 ((unsigned char *)stackblock())[typeloc] = subtype;
12081                 if (subtype != VSNORMAL) {
12082                         varnest++;
12083                         if (dblquote)
12084                                 dqvarnest++;
12085                 }
12086                 STPUTC('=', out);
12087         }
12088         goto parsesub_return;
12089 }
12090
12091 /*
12092  * Called to parse command substitutions.  Newstyle is set if the command
12093  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12094  * list of commands (passed by reference), and savelen is the number of
12095  * characters on the top of the stack which must be preserved.
12096  */
12097 parsebackq: {
12098         struct nodelist **nlpp;
12099         union node *n;
12100         char *str;
12101         size_t savelen;
12102         smallint saveprompt = 0;
12103
12104         str = NULL;
12105         savelen = out - (char *)stackblock();
12106         if (savelen > 0) {
12107                 /*
12108                  * FIXME: this can allocate very large block on stack and SEGV.
12109                  * Example:
12110                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12111                  * allocates 100kb for every command subst. With about
12112                  * a hundred command substitutions stack overflows.
12113                  * With larger prepended string, SEGV happens sooner.
12114                  */
12115                 str = alloca(savelen);
12116                 memcpy(str, stackblock(), savelen);
12117         }
12118
12119         if (oldstyle) {
12120                 /* We must read until the closing backquote, giving special
12121                  * treatment to some slashes, and then push the string and
12122                  * reread it as input, interpreting it normally.
12123                  */
12124                 char *pout;
12125                 size_t psavelen;
12126                 char *pstr;
12127
12128                 STARTSTACKSTR(pout);
12129                 for (;;) {
12130                         int pc;
12131
12132                         setprompt_if(needprompt, 2);
12133                         pc = pgetc();
12134                         switch (pc) {
12135                         case '`':
12136                                 goto done;
12137
12138                         case '\\':
12139                                 pc = pgetc();
12140                                 if (pc == '\n') {
12141                                         nlprompt();
12142                                         /*
12143                                          * If eating a newline, avoid putting
12144                                          * the newline into the new character
12145                                          * stream (via the STPUTC after the
12146                                          * switch).
12147                                          */
12148                                         continue;
12149                                 }
12150                                 if (pc != '\\' && pc != '`' && pc != '$'
12151                                  && (!dblquote || pc != '"')
12152                                 ) {
12153                                         STPUTC('\\', pout);
12154                                 }
12155                                 if (pc <= 255 /* not PEOA or PEOF */) {
12156                                         break;
12157                                 }
12158                                 /* fall through */
12159
12160                         case PEOF:
12161                         IF_ASH_ALIAS(case PEOA:)
12162                                 startlinno = g_parsefile->linno;
12163                                 raise_error_syntax("EOF in backquote substitution");
12164
12165                         case '\n':
12166                                 nlnoprompt();
12167                                 break;
12168
12169                         default:
12170                                 break;
12171                         }
12172                         STPUTC(pc, pout);
12173                 }
12174  done:
12175                 STPUTC('\0', pout);
12176                 psavelen = pout - (char *)stackblock();
12177                 if (psavelen > 0) {
12178                         pstr = grabstackstr(pout);
12179                         setinputstring(pstr);
12180                 }
12181         }
12182         nlpp = &bqlist;
12183         while (*nlpp)
12184                 nlpp = &(*nlpp)->next;
12185         *nlpp = stzalloc(sizeof(**nlpp));
12186         /* (*nlpp)->next = NULL; - stzalloc did it */
12187
12188         if (oldstyle) {
12189                 saveprompt = doprompt;
12190                 doprompt = 0;
12191         }
12192
12193         n = list(2);
12194
12195         if (oldstyle)
12196                 doprompt = saveprompt;
12197         else if (readtoken() != TRP)
12198                 raise_error_unexpected_syntax(TRP);
12199
12200         (*nlpp)->n = n;
12201         if (oldstyle) {
12202                 /*
12203                  * Start reading from old file again, ignoring any pushed back
12204                  * tokens left from the backquote parsing
12205                  */
12206                 popfile();
12207                 tokpushback = 0;
12208         }
12209         while (stackblocksize() <= savelen)
12210                 growstackblock();
12211         STARTSTACKSTR(out);
12212         if (str) {
12213                 memcpy(out, str, savelen);
12214                 STADJUST(savelen, out);
12215         }
12216         USTPUTC(CTLBACKQ, out);
12217         if (oldstyle)
12218                 goto parsebackq_oldreturn;
12219         goto parsebackq_newreturn;
12220 }
12221
12222 #if ENABLE_FEATURE_SH_MATH
12223 /*
12224  * Parse an arithmetic expansion (indicate start of one and set state)
12225  */
12226 parsearith: {
12227         if (++arinest == 1) {
12228                 prevsyntax = syntax;
12229                 syntax = ARISYNTAX;
12230         }
12231         USTPUTC(CTLARI, out);
12232         goto parsearith_return;
12233 }
12234 #endif
12235 } /* end of readtoken */
12236
12237 /*
12238  * Read the next input token.
12239  * If the token is a word, we set backquotelist to the list of cmds in
12240  *      backquotes.  We set quoteflag to true if any part of the word was
12241  *      quoted.
12242  * If the token is TREDIR, then we set redirnode to a structure containing
12243  *      the redirection.
12244  * In all cases, the variable startlinno is set to the number of the line
12245  *      on which the token starts.
12246  *
12247  * [Change comment:  here documents and internal procedures]
12248  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12249  *  word parsing code into a separate routine.  In this case, readtoken
12250  *  doesn't need to have any internal procedures, but parseword does.
12251  *  We could also make parseoperator in essence the main routine, and
12252  *  have parseword (readtoken1?) handle both words and redirection.]
12253  */
12254 #define NEW_xxreadtoken
12255 #ifdef NEW_xxreadtoken
12256 /* singles must be first! */
12257 static const char xxreadtoken_chars[7] ALIGN1 = {
12258         '\n', '(', ')', /* singles */
12259         '&', '|', ';',  /* doubles */
12260         0
12261 };
12262
12263 #define xxreadtoken_singles 3
12264 #define xxreadtoken_doubles 3
12265
12266 static const char xxreadtoken_tokens[] ALIGN1 = {
12267         TNL, TLP, TRP,          /* only single occurrence allowed */
12268         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12269         TEOF,                   /* corresponds to trailing nul */
12270         TAND, TOR, TENDCASE     /* if double occurrence */
12271 };
12272
12273 static int
12274 xxreadtoken(void)
12275 {
12276         int c;
12277
12278         if (tokpushback) {
12279                 tokpushback = 0;
12280                 return lasttoken;
12281         }
12282         setprompt_if(needprompt, 2);
12283         startlinno = g_parsefile->linno;
12284         for (;;) {                      /* until token or start of word found */
12285                 c = pgetc();
12286                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12287                         continue;
12288
12289                 if (c == '#') {
12290                         while ((c = pgetc()) != '\n' && c != PEOF)
12291                                 continue;
12292                         pungetc();
12293                 } else if (c == '\\') {
12294                         if (pgetc() != '\n') {
12295                                 pungetc();
12296                                 break; /* return readtoken1(...) */
12297                         }
12298                         nlprompt();
12299                 } else {
12300                         const char *p;
12301
12302                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12303                         if (c != PEOF) {
12304                                 if (c == '\n') {
12305                                         nlnoprompt();
12306                                 }
12307
12308                                 p = strchr(xxreadtoken_chars, c);
12309                                 if (p == NULL)
12310                                         break; /* return readtoken1(...) */
12311
12312                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12313                                         int cc = pgetc();
12314                                         if (cc == c) {    /* double occurrence? */
12315                                                 p += xxreadtoken_doubles + 1;
12316                                         } else {
12317                                                 pungetc();
12318 #if BASH_REDIR_OUTPUT
12319                                                 if (c == '&' && cc == '>') /* &> */
12320                                                         break; /* return readtoken1(...) */
12321 #endif
12322                                         }
12323                                 }
12324                         }
12325                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12326                         return lasttoken;
12327                 }
12328         } /* for (;;) */
12329
12330         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12331 }
12332 #else /* old xxreadtoken */
12333 #define RETURN(token)   return lasttoken = token
12334 static int
12335 xxreadtoken(void)
12336 {
12337         int c;
12338
12339         if (tokpushback) {
12340                 tokpushback = 0;
12341                 return lasttoken;
12342         }
12343         setprompt_if(needprompt, 2);
12344         startlinno = g_parsefile->linno;
12345         for (;;) {      /* until token or start of word found */
12346                 c = pgetc();
12347                 switch (c) {
12348                 case ' ': case '\t':
12349                 IF_ASH_ALIAS(case PEOA:)
12350                         continue;
12351                 case '#':
12352                         while ((c = pgetc()) != '\n' && c != PEOF)
12353                                 continue;
12354                         pungetc();
12355                         continue;
12356                 case '\\':
12357                         if (pgetc() == '\n') {
12358                                 nlprompt();
12359                                 continue;
12360                         }
12361                         pungetc();
12362                         goto breakloop;
12363                 case '\n':
12364                         nlnoprompt();
12365                         RETURN(TNL);
12366                 case PEOF:
12367                         RETURN(TEOF);
12368                 case '&':
12369                         if (pgetc() == '&')
12370                                 RETURN(TAND);
12371                         pungetc();
12372                         RETURN(TBACKGND);
12373                 case '|':
12374                         if (pgetc() == '|')
12375                                 RETURN(TOR);
12376                         pungetc();
12377                         RETURN(TPIPE);
12378                 case ';':
12379                         if (pgetc() == ';')
12380                                 RETURN(TENDCASE);
12381                         pungetc();
12382                         RETURN(TSEMI);
12383                 case '(':
12384                         RETURN(TLP);
12385                 case ')':
12386                         RETURN(TRP);
12387                 default:
12388                         goto breakloop;
12389                 }
12390         }
12391  breakloop:
12392         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12393 #undef RETURN
12394 }
12395 #endif /* old xxreadtoken */
12396
12397 static int
12398 readtoken(void)
12399 {
12400         int t;
12401         int kwd = checkkwd;
12402 #if DEBUG
12403         smallint alreadyseen = tokpushback;
12404 #endif
12405
12406 #if ENABLE_ASH_ALIAS
12407  top:
12408 #endif
12409
12410         t = xxreadtoken();
12411
12412         /*
12413          * eat newlines
12414          */
12415         if (kwd & CHKNL) {
12416                 while (t == TNL) {
12417                         parseheredoc();
12418                         t = xxreadtoken();
12419                 }
12420         }
12421
12422         if (t != TWORD || quoteflag) {
12423                 goto out;
12424         }
12425
12426         /*
12427          * check for keywords
12428          */
12429         if (kwd & CHKKWD) {
12430                 const char *const *pp;
12431
12432                 pp = findkwd(wordtext);
12433                 if (pp) {
12434                         lasttoken = t = pp - tokname_array;
12435                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12436                         goto out;
12437                 }
12438         }
12439
12440         if (checkkwd & CHKALIAS) {
12441 #if ENABLE_ASH_ALIAS
12442                 struct alias *ap;
12443                 ap = lookupalias(wordtext, 1);
12444                 if (ap != NULL) {
12445                         if (*ap->val) {
12446                                 pushstring(ap->val, ap);
12447                         }
12448                         goto top;
12449                 }
12450 #endif
12451         }
12452  out:
12453         checkkwd = 0;
12454 #if DEBUG
12455         if (!alreadyseen)
12456                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12457         else
12458                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12459 #endif
12460         return t;
12461 }
12462
12463 static int
12464 peektoken(void)
12465 {
12466         int t;
12467
12468         t = readtoken();
12469         tokpushback = 1;
12470         return t;
12471 }
12472
12473 /*
12474  * Read and parse a command.  Returns NODE_EOF on end of file.
12475  * (NULL is a valid parse tree indicating a blank line.)
12476  */
12477 static union node *
12478 parsecmd(int interact)
12479 {
12480         tokpushback = 0;
12481         checkkwd = 0;
12482         heredoclist = 0;
12483         doprompt = interact;
12484         setprompt_if(doprompt, doprompt);
12485         needprompt = 0;
12486         return list(1);
12487 }
12488
12489 /*
12490  * Input any here documents.
12491  */
12492 static void
12493 parseheredoc(void)
12494 {
12495         struct heredoc *here;
12496         union node *n;
12497
12498         here = heredoclist;
12499         heredoclist = NULL;
12500
12501         while (here) {
12502                 setprompt_if(needprompt, 2);
12503                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12504                                 here->eofmark, here->striptabs);
12505                 n = stzalloc(sizeof(struct narg));
12506                 n->narg.type = NARG;
12507                 /*n->narg.next = NULL; - stzalloc did it */
12508                 n->narg.text = wordtext;
12509                 n->narg.backquote = backquotelist;
12510                 here->here->nhere.doc = n;
12511                 here = here->next;
12512         }
12513 }
12514
12515
12516 /*
12517  * called by editline -- any expansions to the prompt should be added here.
12518  */
12519 static const char *
12520 expandstr(const char *ps)
12521 {
12522         union node n;
12523         int saveprompt;
12524
12525         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12526          * and token processing _can_ alter it (delete NULs etc). */
12527         setinputstring((char *)ps);
12528
12529         saveprompt = doprompt;
12530         doprompt = 0;
12531         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12532         doprompt = saveprompt;
12533
12534         popfile();
12535
12536         n.narg.type = NARG;
12537         n.narg.next = NULL;
12538         n.narg.text = wordtext;
12539         n.narg.backquote = backquotelist;
12540
12541         expandarg(&n, NULL, EXP_QUOTED);
12542         return stackblock();
12543 }
12544
12545 /*
12546  * Execute a command or commands contained in a string.
12547  */
12548 static int
12549 evalstring(char *s, int flags)
12550 {
12551         struct jmploc *volatile savehandler;
12552         struct jmploc jmploc;
12553         int ex;
12554
12555         union node *n;
12556         struct stackmark smark;
12557         int status;
12558
12559         s = sstrdup(s);
12560         setinputstring(s);
12561         setstackmark(&smark);
12562
12563         status = 0;
12564         /* On exception inside execution loop, we must popfile().
12565          * Try interactively:
12566          *      readonly a=a
12567          *      command eval "a=b"  # throws "is read only" error
12568          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12569          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12570          */
12571         savehandler = exception_handler;
12572         ex = setjmp(jmploc.loc);
12573         if (ex)
12574                 goto out;
12575         exception_handler = &jmploc;
12576
12577         while ((n = parsecmd(0)) != NODE_EOF) {
12578                 int i;
12579
12580                 i = evaltree(n, flags);
12581                 if (n)
12582                         status = i;
12583                 popstackmark(&smark);
12584                 if (evalskip)
12585                         break;
12586         }
12587  out:
12588         popstackmark(&smark);
12589         popfile();
12590         stunalloc(s);
12591
12592         exception_handler = savehandler;
12593         if (ex)
12594                 longjmp(exception_handler->loc, ex);
12595
12596         return status;
12597 }
12598
12599 /*
12600  * The eval command.
12601  */
12602 static int FAST_FUNC
12603 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12604 {
12605         char *p;
12606         char *concat;
12607
12608         if (argv[1]) {
12609                 p = argv[1];
12610                 argv += 2;
12611                 if (argv[0]) {
12612                         STARTSTACKSTR(concat);
12613                         for (;;) {
12614                                 concat = stack_putstr(p, concat);
12615                                 p = *argv++;
12616                                 if (p == NULL)
12617                                         break;
12618                                 STPUTC(' ', concat);
12619                         }
12620                         STPUTC('\0', concat);
12621                         p = grabstackstr(concat);
12622                 }
12623                 return evalstring(p, flags & EV_TESTED);
12624         }
12625         return 0;
12626 }
12627
12628 /*
12629  * Read and execute commands.
12630  * "Top" is nonzero for the top level command loop;
12631  * it turns on prompting if the shell is interactive.
12632  */
12633 static int
12634 cmdloop(int top)
12635 {
12636         union node *n;
12637         struct stackmark smark;
12638         int inter;
12639         int status = 0;
12640         int numeof = 0;
12641
12642         TRACE(("cmdloop(%d) called\n", top));
12643         for (;;) {
12644                 int skip;
12645
12646                 setstackmark(&smark);
12647 #if JOBS
12648                 if (doing_jobctl)
12649                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12650 #endif
12651                 inter = 0;
12652                 if (iflag && top) {
12653                         inter++;
12654                         chkmail();
12655                 }
12656                 n = parsecmd(inter);
12657 #if DEBUG
12658                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12659                         showtree(n);
12660 #endif
12661                 if (n == NODE_EOF) {
12662                         if (!top || numeof >= 50)
12663                                 break;
12664                         if (!stoppedjobs()) {
12665                                 if (!Iflag)
12666                                         break;
12667                                 out2str("\nUse \"exit\" to leave shell.\n");
12668                         }
12669                         numeof++;
12670                 } else if (nflag == 0) {
12671                         int i;
12672
12673                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12674                         job_warning >>= 1;
12675                         numeof = 0;
12676                         i = evaltree(n, 0);
12677                         if (n)
12678                                 status = i;
12679                 }
12680                 popstackmark(&smark);
12681                 skip = evalskip;
12682
12683                 if (skip) {
12684                         evalskip &= ~SKIPFUNC;
12685                         break;
12686                 }
12687         }
12688         return status;
12689 }
12690
12691 /*
12692  * Take commands from a file.  To be compatible we should do a path
12693  * search for the file, which is necessary to find sub-commands.
12694  */
12695 static char *
12696 find_dot_file(char *name)
12697 {
12698         char *fullname;
12699         const char *path = pathval();
12700         struct stat statb;
12701
12702         /* don't try this for absolute or relative paths */
12703         if (strchr(name, '/'))
12704                 return name;
12705
12706         while ((fullname = path_advance(&path, name)) != NULL) {
12707                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12708                         /*
12709                          * Don't bother freeing here, since it will
12710                          * be freed by the caller.
12711                          */
12712                         return fullname;
12713                 }
12714                 if (fullname != name)
12715                         stunalloc(fullname);
12716         }
12717
12718         /* not found in the PATH */
12719         ash_msg_and_raise_error("%s: not found", name);
12720         /* NOTREACHED */
12721 }
12722
12723 static int FAST_FUNC
12724 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12725 {
12726         /* "false; . empty_file; echo $?" should print 0, not 1: */
12727         int status = 0;
12728         char *fullname;
12729         char **argv;
12730         char *args_need_save;
12731         struct strlist *sp;
12732         volatile struct shparam saveparam;
12733
12734         for (sp = cmdenviron; sp; sp = sp->next)
12735                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12736
12737         nextopt(nullstr); /* handle possible "--" */
12738         argv = argptr;
12739
12740         if (!argv[0]) {
12741                 /* bash says: "bash: .: filename argument required" */
12742                 return 2; /* bash compat */
12743         }
12744
12745         /* This aborts if file isn't found, which is POSIXly correct.
12746          * bash returns exitcode 1 instead.
12747          */
12748         fullname = find_dot_file(argv[0]);
12749         argv++;
12750         args_need_save = argv[0];
12751         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12752                 int argc;
12753                 saveparam = shellparam;
12754                 shellparam.malloced = 0;
12755                 argc = 1;
12756                 while (argv[argc])
12757                         argc++;
12758                 shellparam.nparam = argc;
12759                 shellparam.p = argv;
12760         };
12761
12762         /* This aborts if file can't be opened, which is POSIXly correct.
12763          * bash returns exitcode 1 instead.
12764          */
12765         setinputfile(fullname, INPUT_PUSH_FILE);
12766         commandname = fullname;
12767         status = cmdloop(0);
12768         popfile();
12769
12770         if (args_need_save) {
12771                 freeparam(&shellparam);
12772                 shellparam = saveparam;
12773         };
12774
12775         return status;
12776 }
12777
12778 static int FAST_FUNC
12779 exitcmd(int argc UNUSED_PARAM, char **argv)
12780 {
12781         if (stoppedjobs())
12782                 return 0;
12783         if (argv[1])
12784                 exitstatus = number(argv[1]);
12785         raise_exception(EXEXIT);
12786         /* NOTREACHED */
12787 }
12788
12789 /*
12790  * Read a file containing shell functions.
12791  */
12792 static void
12793 readcmdfile(char *name)
12794 {
12795         setinputfile(name, INPUT_PUSH_FILE);
12796         cmdloop(0);
12797         popfile();
12798 }
12799
12800
12801 /* ============ find_command inplementation */
12802
12803 /*
12804  * Resolve a command name.  If you change this routine, you may have to
12805  * change the shellexec routine as well.
12806  */
12807 static void
12808 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12809 {
12810         struct tblentry *cmdp;
12811         int idx;
12812         int prev;
12813         char *fullname;
12814         struct stat statb;
12815         int e;
12816         int updatetbl;
12817         struct builtincmd *bcmd;
12818
12819         /* If name contains a slash, don't use PATH or hash table */
12820         if (strchr(name, '/') != NULL) {
12821                 entry->u.index = -1;
12822                 if (act & DO_ABS) {
12823                         while (stat(name, &statb) < 0) {
12824 #ifdef SYSV
12825                                 if (errno == EINTR)
12826                                         continue;
12827 #endif
12828                                 entry->cmdtype = CMDUNKNOWN;
12829                                 return;
12830                         }
12831                 }
12832                 entry->cmdtype = CMDNORMAL;
12833                 return;
12834         }
12835
12836 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12837
12838         updatetbl = (path == pathval());
12839         if (!updatetbl) {
12840                 act |= DO_ALTPATH;
12841                 if (strstr(path, "%builtin") != NULL)
12842                         act |= DO_ALTBLTIN;
12843         }
12844
12845         /* If name is in the table, check answer will be ok */
12846         cmdp = cmdlookup(name, 0);
12847         if (cmdp != NULL) {
12848                 int bit;
12849
12850                 switch (cmdp->cmdtype) {
12851                 default:
12852 #if DEBUG
12853                         abort();
12854 #endif
12855                 case CMDNORMAL:
12856                         bit = DO_ALTPATH;
12857                         break;
12858                 case CMDFUNCTION:
12859                         bit = DO_NOFUNC;
12860                         break;
12861                 case CMDBUILTIN:
12862                         bit = DO_ALTBLTIN;
12863                         break;
12864                 }
12865                 if (act & bit) {
12866                         updatetbl = 0;
12867                         cmdp = NULL;
12868                 } else if (cmdp->rehash == 0)
12869                         /* if not invalidated by cd, we're done */
12870                         goto success;
12871         }
12872
12873         /* If %builtin not in path, check for builtin next */
12874         bcmd = find_builtin(name);
12875         if (bcmd) {
12876                 if (IS_BUILTIN_REGULAR(bcmd))
12877                         goto builtin_success;
12878                 if (act & DO_ALTPATH) {
12879                         if (!(act & DO_ALTBLTIN))
12880                                 goto builtin_success;
12881                 } else if (builtinloc <= 0) {
12882                         goto builtin_success;
12883                 }
12884         }
12885
12886 #if ENABLE_FEATURE_SH_STANDALONE
12887         {
12888                 int applet_no = find_applet_by_name(name);
12889                 if (applet_no >= 0) {
12890                         entry->cmdtype = CMDNORMAL;
12891                         entry->u.index = -2 - applet_no;
12892                         return;
12893                 }
12894         }
12895 #endif
12896
12897         /* We have to search path. */
12898         prev = -1;              /* where to start */
12899         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12900                 if (cmdp->cmdtype == CMDBUILTIN)
12901                         prev = builtinloc;
12902                 else
12903                         prev = cmdp->param.index;
12904         }
12905
12906         e = ENOENT;
12907         idx = -1;
12908  loop:
12909         while ((fullname = path_advance(&path, name)) != NULL) {
12910                 stunalloc(fullname);
12911                 /* NB: code below will still use fullname
12912                  * despite it being "unallocated" */
12913                 idx++;
12914                 if (pathopt) {
12915                         if (prefix(pathopt, "builtin")) {
12916                                 if (bcmd)
12917                                         goto builtin_success;
12918                                 continue;
12919                         }
12920                         if ((act & DO_NOFUNC)
12921                          || !prefix(pathopt, "func")
12922                         ) {     /* ignore unimplemented options */
12923                                 continue;
12924                         }
12925                 }
12926                 /* if rehash, don't redo absolute path names */
12927                 if (fullname[0] == '/' && idx <= prev) {
12928                         if (idx < prev)
12929                                 continue;
12930                         TRACE(("searchexec \"%s\": no change\n", name));
12931                         goto success;
12932                 }
12933                 while (stat(fullname, &statb) < 0) {
12934 #ifdef SYSV
12935                         if (errno == EINTR)
12936                                 continue;
12937 #endif
12938                         if (errno != ENOENT && errno != ENOTDIR)
12939                                 e = errno;
12940                         goto loop;
12941                 }
12942                 e = EACCES;     /* if we fail, this will be the error */
12943                 if (!S_ISREG(statb.st_mode))
12944                         continue;
12945                 if (pathopt) {          /* this is a %func directory */
12946                         stalloc(strlen(fullname) + 1);
12947                         /* NB: stalloc will return space pointed by fullname
12948                          * (because we don't have any intervening allocations
12949                          * between stunalloc above and this stalloc) */
12950                         readcmdfile(fullname);
12951                         cmdp = cmdlookup(name, 0);
12952                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12953                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12954                         stunalloc(fullname);
12955                         goto success;
12956                 }
12957                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12958                 if (!updatetbl) {
12959                         entry->cmdtype = CMDNORMAL;
12960                         entry->u.index = idx;
12961                         return;
12962                 }
12963                 INT_OFF;
12964                 cmdp = cmdlookup(name, 1);
12965                 cmdp->cmdtype = CMDNORMAL;
12966                 cmdp->param.index = idx;
12967                 INT_ON;
12968                 goto success;
12969         }
12970
12971         /* We failed.  If there was an entry for this command, delete it */
12972         if (cmdp && updatetbl)
12973                 delete_cmd_entry();
12974         if (act & DO_ERR)
12975                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12976         entry->cmdtype = CMDUNKNOWN;
12977         return;
12978
12979  builtin_success:
12980         if (!updatetbl) {
12981                 entry->cmdtype = CMDBUILTIN;
12982                 entry->u.cmd = bcmd;
12983                 return;
12984         }
12985         INT_OFF;
12986         cmdp = cmdlookup(name, 1);
12987         cmdp->cmdtype = CMDBUILTIN;
12988         cmdp->param.cmd = bcmd;
12989         INT_ON;
12990  success:
12991         cmdp->rehash = 0;
12992         entry->cmdtype = cmdp->cmdtype;
12993         entry->u = cmdp->param;
12994 }
12995
12996
12997 /*
12998  * The trap builtin.
12999  */
13000 static int FAST_FUNC
13001 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13002 {
13003         char *action;
13004         char **ap;
13005         int signo, exitcode;
13006
13007         nextopt(nullstr);
13008         ap = argptr;
13009         if (!*ap) {
13010                 for (signo = 0; signo < NSIG; signo++) {
13011                         char *tr = trap_ptr[signo];
13012                         if (tr) {
13013                                 /* note: bash adds "SIG", but only if invoked
13014                                  * as "bash". If called as "sh", or if set -o posix,
13015                                  * then it prints short signal names.
13016                                  * We are printing short names: */
13017                                 out1fmt("trap -- %s %s\n",
13018                                                 single_quote(tr),
13019                                                 get_signame(signo));
13020                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13021                  * In this case, we will exit very soon, no need to free(). */
13022                                 /* if (trap_ptr != trap && tp[0]) */
13023                                 /*      free(tr); */
13024                         }
13025                 }
13026                 /*
13027                 if (trap_ptr != trap) {
13028                         free(trap_ptr);
13029                         trap_ptr = trap;
13030                 }
13031                 */
13032                 return 0;
13033         }
13034
13035         action = NULL;
13036         if (ap[1])
13037                 action = *ap++;
13038         exitcode = 0;
13039         while (*ap) {
13040                 signo = get_signum(*ap);
13041                 if (signo < 0 || signo >= NSIG) {
13042                         /* Mimic bash message exactly */
13043                         ash_msg("%s: invalid signal specification", *ap);
13044                         exitcode = 1;
13045                         goto next;
13046                 }
13047                 INT_OFF;
13048                 if (action) {
13049                         if (LONE_DASH(action))
13050                                 action = NULL;
13051                         else {
13052                                 if (action[0]) /* not NULL and not "" and not "-" */
13053                                         may_have_traps = 1;
13054                                 action = ckstrdup(action);
13055                         }
13056                 }
13057                 free(trap[signo]);
13058                 trap[signo] = action;
13059                 if (signo != 0)
13060                         setsignal(signo);
13061                 INT_ON;
13062  next:
13063                 ap++;
13064         }
13065         return exitcode;
13066 }
13067
13068
13069 /* ============ Builtins */
13070
13071 #if ENABLE_ASH_HELP
13072 static int FAST_FUNC
13073 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13074 {
13075         unsigned col;
13076         unsigned i;
13077
13078         out1fmt(
13079                 "Built-in commands:\n"
13080                 "------------------\n");
13081         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13082                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13083                                         builtintab[i].name + 1);
13084                 if (col > 60) {
13085                         out1fmt("\n");
13086                         col = 0;
13087                 }
13088         }
13089 # if ENABLE_FEATURE_SH_STANDALONE
13090         {
13091                 const char *a = applet_names;
13092                 while (*a) {
13093                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13094                         if (col > 60) {
13095                                 out1fmt("\n");
13096                                 col = 0;
13097                         }
13098                         while (*a++ != '\0')
13099                                 continue;
13100                 }
13101         }
13102 # endif
13103         newline_and_flush(stdout);
13104         return EXIT_SUCCESS;
13105 }
13106 #endif
13107
13108 #if MAX_HISTORY
13109 static int FAST_FUNC
13110 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13111 {
13112         show_history(line_input_state);
13113         return EXIT_SUCCESS;
13114 }
13115 #endif
13116
13117 /*
13118  * The export and readonly commands.
13119  */
13120 static int FAST_FUNC
13121 exportcmd(int argc UNUSED_PARAM, char **argv)
13122 {
13123         struct var *vp;
13124         char *name;
13125         const char *p;
13126         char **aptr;
13127         char opt;
13128         int flag;
13129         int flag_off;
13130
13131         /* "readonly" in bash accepts, but ignores -n.
13132          * We do the same: it saves a conditional in nextopt's param.
13133          */
13134         flag_off = 0;
13135         while ((opt = nextopt("np")) != '\0') {
13136                 if (opt == 'n')
13137                         flag_off = VEXPORT;
13138         }
13139         flag = VEXPORT;
13140         if (argv[0][0] == 'r') {
13141                 flag = VREADONLY;
13142                 flag_off = 0; /* readonly ignores -n */
13143         }
13144         flag_off = ~flag_off;
13145
13146         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13147         {
13148                 aptr = argptr;
13149                 name = *aptr;
13150                 if (name) {
13151                         do {
13152                                 p = strchr(name, '=');
13153                                 if (p != NULL) {
13154                                         p++;
13155                                 } else {
13156                                         vp = *findvar(hashvar(name), name);
13157                                         if (vp) {
13158                                                 vp->flags = ((vp->flags | flag) & flag_off);
13159                                                 continue;
13160                                         }
13161                                 }
13162                                 setvar(name, p, (flag & flag_off));
13163                         } while ((name = *++aptr) != NULL);
13164                         return 0;
13165                 }
13166         }
13167
13168         /* No arguments. Show the list of exported or readonly vars.
13169          * -n is ignored.
13170          */
13171         showvars(argv[0], flag, 0);
13172         return 0;
13173 }
13174
13175 /*
13176  * Delete a function if it exists.
13177  */
13178 static void
13179 unsetfunc(const char *name)
13180 {
13181         struct tblentry *cmdp;
13182
13183         cmdp = cmdlookup(name, 0);
13184         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13185                 delete_cmd_entry();
13186 }
13187
13188 /*
13189  * The unset builtin command.  We unset the function before we unset the
13190  * variable to allow a function to be unset when there is a readonly variable
13191  * with the same name.
13192  */
13193 static int FAST_FUNC
13194 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13195 {
13196         char **ap;
13197         int i;
13198         int flag = 0;
13199
13200         while ((i = nextopt("vf")) != 0) {
13201                 flag = i;
13202         }
13203
13204         for (ap = argptr; *ap; ap++) {
13205                 if (flag != 'f') {
13206                         unsetvar(*ap);
13207                         continue;
13208                 }
13209                 if (flag != 'v')
13210                         unsetfunc(*ap);
13211         }
13212         return 0;
13213 }
13214
13215 static const unsigned char timescmd_str[] ALIGN1 = {
13216         ' ',  offsetof(struct tms, tms_utime),
13217         '\n', offsetof(struct tms, tms_stime),
13218         ' ',  offsetof(struct tms, tms_cutime),
13219         '\n', offsetof(struct tms, tms_cstime),
13220         0
13221 };
13222 static int FAST_FUNC
13223 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13224 {
13225         unsigned long clk_tck, s, t;
13226         const unsigned char *p;
13227         struct tms buf;
13228
13229         clk_tck = bb_clk_tck();
13230         times(&buf);
13231
13232         p = timescmd_str;
13233         do {
13234                 t = *(clock_t *)(((char *) &buf) + p[1]);
13235                 s = t / clk_tck;
13236                 t = t % clk_tck;
13237                 out1fmt("%lum%lu.%03lus%c",
13238                         s / 60, s % 60,
13239                         (t * 1000) / clk_tck,
13240                         p[0]);
13241                 p += 2;
13242         } while (*p);
13243
13244         return 0;
13245 }
13246
13247 #if ENABLE_FEATURE_SH_MATH
13248 /*
13249  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13250  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13251  *
13252  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13253  */
13254 static int FAST_FUNC
13255 letcmd(int argc UNUSED_PARAM, char **argv)
13256 {
13257         arith_t i;
13258
13259         argv++;
13260         if (!*argv)
13261                 ash_msg_and_raise_error("expression expected");
13262         do {
13263                 i = ash_arith(*argv);
13264         } while (*++argv);
13265
13266         return !i;
13267 }
13268 #endif
13269
13270 /*
13271  * The read builtin. Options:
13272  *      -r              Do not interpret '\' specially
13273  *      -s              Turn off echo (tty only)
13274  *      -n NCHARS       Read NCHARS max
13275  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13276  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13277  *      -u FD           Read from given FD instead of fd 0
13278  * This uses unbuffered input, which may be avoidable in some cases.
13279  * TODO: bash also has:
13280  *      -a ARRAY        Read into array[0],[1],etc
13281  *      -d DELIM        End on DELIM char, not newline
13282  *      -e              Use line editing (tty only)
13283  */
13284 static int FAST_FUNC
13285 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13286 {
13287         char *opt_n = NULL;
13288         char *opt_p = NULL;
13289         char *opt_t = NULL;
13290         char *opt_u = NULL;
13291         int read_flags = 0;
13292         const char *r;
13293         int i;
13294
13295         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13296                 switch (i) {
13297                 case 'p':
13298                         opt_p = optionarg;
13299                         break;
13300                 case 'n':
13301                         opt_n = optionarg;
13302                         break;
13303                 case 's':
13304                         read_flags |= BUILTIN_READ_SILENT;
13305                         break;
13306                 case 't':
13307                         opt_t = optionarg;
13308                         break;
13309                 case 'r':
13310                         read_flags |= BUILTIN_READ_RAW;
13311                         break;
13312                 case 'u':
13313                         opt_u = optionarg;
13314                         break;
13315                 default:
13316                         break;
13317                 }
13318         }
13319
13320         /* "read -s" needs to save/restore termios, can't allow ^C
13321          * to jump out of it.
13322          */
13323  again:
13324         INT_OFF;
13325         r = shell_builtin_read(setvar0,
13326                 argptr,
13327                 bltinlookup("IFS"), /* can be NULL */
13328                 read_flags,
13329                 opt_n,
13330                 opt_p,
13331                 opt_t,
13332                 opt_u
13333         );
13334         INT_ON;
13335
13336         if ((uintptr_t)r == 1 && errno == EINTR) {
13337                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13338                 if (pending_sig == 0)
13339                         goto again;
13340         }
13341
13342         if ((uintptr_t)r > 1)
13343                 ash_msg_and_raise_error(r);
13344
13345         return (uintptr_t)r;
13346 }
13347
13348 static int FAST_FUNC
13349 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13350 {
13351         static const char permuser[3] ALIGN1 = "ogu";
13352
13353         mode_t mask;
13354         int symbolic_mode = 0;
13355
13356         while (nextopt("S") != '\0') {
13357                 symbolic_mode = 1;
13358         }
13359
13360         INT_OFF;
13361         mask = umask(0);
13362         umask(mask);
13363         INT_ON;
13364
13365         if (*argptr == NULL) {
13366                 if (symbolic_mode) {
13367                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13368                         char *p = buf;
13369                         int i;
13370
13371                         i = 2;
13372                         for (;;) {
13373                                 *p++ = ',';
13374                                 *p++ = permuser[i];
13375                                 *p++ = '=';
13376                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13377                                 if (!(mask & 0400)) *p++ = 'r';
13378                                 if (!(mask & 0200)) *p++ = 'w';
13379                                 if (!(mask & 0100)) *p++ = 'x';
13380                                 mask <<= 3;
13381                                 if (--i < 0)
13382                                         break;
13383                         }
13384                         *p = '\0';
13385                         puts(buf + 1);
13386                 } else {
13387                         out1fmt("%04o\n", mask);
13388                 }
13389         } else {
13390                 char *modestr = *argptr;
13391                 /* numeric umasks are taken as-is */
13392                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13393                 if (!isdigit(modestr[0]))
13394                         mask ^= 0777;
13395                 mask = bb_parse_mode(modestr, mask);
13396                 if ((unsigned)mask > 0777) {
13397                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13398                 }
13399                 if (!isdigit(modestr[0]))
13400                         mask ^= 0777;
13401                 umask(mask);
13402         }
13403         return 0;
13404 }
13405
13406 static int FAST_FUNC
13407 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13408 {
13409         return shell_builtin_ulimit(argv);
13410 }
13411
13412 /* ============ main() and helpers */
13413
13414 /*
13415  * Called to exit the shell.
13416  */
13417 static void
13418 exitshell(void)
13419 {
13420         struct jmploc loc;
13421         char *p;
13422         int status;
13423
13424 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13425         save_history(line_input_state);
13426 #endif
13427         status = exitstatus;
13428         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13429         if (setjmp(loc.loc)) {
13430                 if (exception_type == EXEXIT)
13431                         status = exitstatus;
13432                 goto out;
13433         }
13434         exception_handler = &loc;
13435         p = trap[0];
13436         if (p) {
13437                 trap[0] = NULL;
13438                 evalskip = 0;
13439                 evalstring(p, 0);
13440                 /*free(p); - we'll exit soon */
13441         }
13442  out:
13443         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13444          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13445          */
13446         setjobctl(0);
13447         flush_stdout_stderr();
13448         _exit(status);
13449         /* NOTREACHED */
13450 }
13451
13452 static void
13453 init(void)
13454 {
13455         /* we will never free this */
13456         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13457
13458         sigmode[SIGCHLD - 1] = S_DFL;
13459         setsignal(SIGCHLD);
13460
13461         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13462          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13463          */
13464         signal(SIGHUP, SIG_DFL);
13465
13466         {
13467                 char **envp;
13468                 const char *p;
13469                 struct stat st1, st2;
13470
13471                 initvar();
13472                 for (envp = environ; envp && *envp; envp++) {
13473                         p = endofname(*envp);
13474                         if (p != *envp && *p == '=') {
13475                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13476                         }
13477                 }
13478
13479                 setvareq((char*)defoptindvar, VTEXTFIXED);
13480
13481                 setvar0("PPID", utoa(getppid()));
13482 #if BASH_SHLVL_VAR
13483                 p = lookupvar("SHLVL");
13484                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13485 #endif
13486 #if BASH_HOSTNAME_VAR
13487                 if (!lookupvar("HOSTNAME")) {
13488                         struct utsname uts;
13489                         uname(&uts);
13490                         setvar0("HOSTNAME", uts.nodename);
13491                 }
13492 #endif
13493                 p = lookupvar("PWD");
13494                 if (p) {
13495                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13496                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13497                         ) {
13498                                 p = NULL;
13499                         }
13500                 }
13501                 setpwd(p, 0);
13502         }
13503 }
13504
13505
13506 //usage:#define ash_trivial_usage
13507 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13508 //usage:#define ash_full_usage "\n\n"
13509 //usage:        "Unix shell interpreter"
13510
13511 /*
13512  * Process the shell command line arguments.
13513  */
13514 static void
13515 procargs(char **argv)
13516 {
13517         int i;
13518         const char *xminusc;
13519         char **xargv;
13520
13521         xargv = argv;
13522         arg0 = xargv[0];
13523         /* if (xargv[0]) - mmm, this is always true! */
13524                 xargv++;
13525         for (i = 0; i < NOPTS; i++)
13526                 optlist[i] = 2;
13527         argptr = xargv;
13528         if (options(/*cmdline:*/ 1)) {
13529                 /* it already printed err message */
13530                 raise_exception(EXERROR);
13531         }
13532         xargv = argptr;
13533         xminusc = minusc;
13534         if (*xargv == NULL) {
13535                 if (xminusc)
13536                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13537                 sflag = 1;
13538         }
13539         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13540                 iflag = 1;
13541         if (mflag == 2)
13542                 mflag = iflag;
13543         for (i = 0; i < NOPTS; i++)
13544                 if (optlist[i] == 2)
13545                         optlist[i] = 0;
13546 #if DEBUG == 2
13547         debug = 1;
13548 #endif
13549         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13550         if (xminusc) {
13551                 minusc = *xargv++;
13552                 if (*xargv)
13553                         goto setarg0;
13554         } else if (!sflag) {
13555                 setinputfile(*xargv, 0);
13556  setarg0:
13557                 arg0 = *xargv++;
13558                 commandname = arg0;
13559         }
13560
13561         shellparam.p = xargv;
13562 #if ENABLE_ASH_GETOPTS
13563         shellparam.optind = 1;
13564         shellparam.optoff = -1;
13565 #endif
13566         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13567         while (*xargv) {
13568                 shellparam.nparam++;
13569                 xargv++;
13570         }
13571         optschanged();
13572 }
13573
13574 /*
13575  * Read /etc/profile, ~/.profile, $ENV.
13576  */
13577 static void
13578 read_profile(const char *name)
13579 {
13580         name = expandstr(name);
13581         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13582                 return;
13583         cmdloop(0);
13584         popfile();
13585 }
13586
13587 /*
13588  * This routine is called when an error or an interrupt occurs in an
13589  * interactive shell and control is returned to the main command loop.
13590  * (In dash, this function is auto-generated by build machinery).
13591  */
13592 static void
13593 reset(void)
13594 {
13595         /* from eval.c: */
13596         evalskip = 0;
13597         loopnest = 0;
13598
13599         /* from expand.c: */
13600         ifsfree();
13601
13602         /* from input.c: */
13603         g_parsefile->left_in_buffer = 0;
13604         g_parsefile->left_in_line = 0;      /* clear input buffer */
13605         popallfiles();
13606
13607         /* from redir.c: */
13608         while (redirlist)
13609                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13610 }
13611
13612 #if PROFILE
13613 static short profile_buf[16384];
13614 extern int etext();
13615 #endif
13616
13617 /*
13618  * Main routine.  We initialize things, parse the arguments, execute
13619  * profiles if we're a login shell, and then call cmdloop to execute
13620  * commands.  The setjmp call sets up the location to jump to when an
13621  * exception occurs.  When an exception occurs the variable "state"
13622  * is used to figure out how far we had gotten.
13623  */
13624 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13625 int ash_main(int argc UNUSED_PARAM, char **argv)
13626 {
13627         volatile smallint state;
13628         struct jmploc jmploc;
13629         struct stackmark smark;
13630
13631         /* Initialize global data */
13632         INIT_G_misc();
13633         INIT_G_memstack();
13634         INIT_G_var();
13635 #if ENABLE_ASH_ALIAS
13636         INIT_G_alias();
13637 #endif
13638         INIT_G_cmdtable();
13639
13640 #if PROFILE
13641         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13642 #endif
13643
13644 #if ENABLE_FEATURE_EDITING
13645         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13646 #endif
13647         state = 0;
13648         if (setjmp(jmploc.loc)) {
13649                 smallint e;
13650                 smallint s;
13651
13652                 reset();
13653
13654                 e = exception_type;
13655                 s = state;
13656                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13657                         exitshell();
13658                 }
13659                 if (e == EXINT) {
13660                         newline_and_flush(stderr);
13661                 }
13662
13663                 popstackmark(&smark);
13664                 FORCE_INT_ON; /* enable interrupts */
13665                 if (s == 1)
13666                         goto state1;
13667                 if (s == 2)
13668                         goto state2;
13669                 if (s == 3)
13670                         goto state3;
13671                 goto state4;
13672         }
13673         exception_handler = &jmploc;
13674         rootpid = getpid();
13675
13676         init();
13677         setstackmark(&smark);
13678         procargs(argv);
13679 #if DEBUG
13680         TRACE(("Shell args: "));
13681         trace_puts_args(argv);
13682 #endif
13683
13684         if (argv[0] && argv[0][0] == '-')
13685                 isloginsh = 1;
13686         if (isloginsh) {
13687                 const char *hp;
13688
13689                 state = 1;
13690                 read_profile("/etc/profile");
13691  state1:
13692                 state = 2;
13693                 hp = lookupvar("HOME");
13694                 if (hp)
13695                         read_profile("$HOME/.profile");
13696         }
13697  state2:
13698         state = 3;
13699         if (
13700 #ifndef linux
13701          getuid() == geteuid() && getgid() == getegid() &&
13702 #endif
13703          iflag
13704         ) {
13705                 const char *shinit = lookupvar("ENV");
13706                 if (shinit != NULL && *shinit != '\0')
13707                         read_profile(shinit);
13708         }
13709         popstackmark(&smark);
13710  state3:
13711         state = 4;
13712         if (minusc) {
13713                 /* evalstring pushes parsefile stack.
13714                  * Ensure we don't falsely claim that 0 (stdin)
13715                  * is one of stacked source fds.
13716                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13717                 // if (!sflag) g_parsefile->pf_fd = -1;
13718                 // ^^ not necessary since now we special-case fd 0
13719                 // in is_hidden_fd() to not be considered "hidden fd"
13720                 evalstring(minusc, 0);
13721         }
13722
13723         if (sflag || minusc == NULL) {
13724 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13725                 if (iflag) {
13726                         const char *hp = lookupvar("HISTFILE");
13727                         if (!hp) {
13728                                 hp = lookupvar("HOME");
13729                                 if (hp) {
13730                                         INT_OFF;
13731                                         hp = concat_path_file(hp, ".ash_history");
13732                                         setvar0("HISTFILE", hp);
13733                                         free((char*)hp);
13734                                         INT_ON;
13735                                         hp = lookupvar("HISTFILE");
13736                                 }
13737                         }
13738                         if (hp)
13739                                 line_input_state->hist_file = hp;
13740 # if ENABLE_FEATURE_SH_HISTFILESIZE
13741                         hp = lookupvar("HISTFILESIZE");
13742                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13743 # endif
13744                 }
13745 #endif
13746  state4: /* XXX ??? - why isn't this before the "if" statement */
13747                 cmdloop(1);
13748         }
13749 #if PROFILE
13750         monitor(0);
13751 #endif
13752 #ifdef GPROF
13753         {
13754                 extern void _mcleanup(void);
13755                 _mcleanup();
13756         }
13757 #endif
13758         TRACE(("End of main reached\n"));
13759         exitshell();
13760         /* NOTREACHED */
13761 }
13762
13763
13764 /*-
13765  * Copyright (c) 1989, 1991, 1993, 1994
13766  *      The Regents of the University of California.  All rights reserved.
13767  *
13768  * This code is derived from software contributed to Berkeley by
13769  * Kenneth Almquist.
13770  *
13771  * Redistribution and use in source and binary forms, with or without
13772  * modification, are permitted provided that the following conditions
13773  * are met:
13774  * 1. Redistributions of source code must retain the above copyright
13775  *    notice, this list of conditions and the following disclaimer.
13776  * 2. Redistributions in binary form must reproduce the above copyright
13777  *    notice, this list of conditions and the following disclaimer in the
13778  *    documentation and/or other materials provided with the distribution.
13779  * 3. Neither the name of the University nor the names of its contributors
13780  *    may be used to endorse or promote products derived from this software
13781  *    without specific prior written permission.
13782  *
13783  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13784  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13785  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13786  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13787  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13788  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13789  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13790  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13791  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13792  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13793  * SUCH DAMAGE.
13794  */