hush: fix readonly2.tests failure
[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"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:         Tha 'ash' shell adds about 60k in the default configuration and is
24 //config:         the most complete and most pedantically correct shell included with
25 //config:         busybox. This shell is actually a derivative of the Debian 'dash'
26 //config:         shell (by Herbert Xu), which was created by porting the 'ash' shell
27 //config:         (written by Kenneth Almquist) from NetBSD.
28 //config:
29 //config:# ash options
30 //config:# note: Don't remove !NOMMU part in the next line; it would break
31 //config:# menuconfig's indenting.
32 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
33 //config:
34 //config:config ASH_OPTIMIZE_FOR_SIZE
35 //config:       bool "Optimize for size instead of speed"
36 //config:       default y
37 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
38 //config:
39 //config:config ASH_INTERNAL_GLOB
40 //config:       bool "Use internal glob() implementation"
41 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
42 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
43 //config:       help
44 //config:         Do not use glob() function from libc, use internal implementation.
45 //config:         Use this if you are getting "glob.h: No such file or directory"
46 //config:         or similar build errors.
47 //config:         Note that as of now (2017-01), uclibc and musl glob() both have bugs
48 //config:         which would break ash if you select N here.
49 //config:
50 //config:config ASH_BASH_COMPAT
51 //config:       bool "bash-compatible extensions"
52 //config:       default y
53 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
54 //config:
55 //config:config ASH_JOB_CONTROL
56 //config:       bool "Job control"
57 //config:       default y
58 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
59 //config:
60 //config:config ASH_ALIAS
61 //config:       bool "Alias support"
62 //config:       default y
63 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
64 //config:
65 //config:config ASH_RANDOM_SUPPORT
66 //config:       bool "Pseudorandom generator and $RANDOM variable"
67 //config:       default y
68 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
69 //config:       help
70 //config:         Enable pseudorandom generator and dynamic variable "$RANDOM".
71 //config:         Each read of "$RANDOM" will generate a new pseudorandom value.
72 //config:         You can reset the generator by using a specified start value.
73 //config:         After "unset RANDOM" the generator will switch off and this
74 //config:         variable will no longer have special treatment.
75 //config:
76 //config:config ASH_EXPAND_PRMT
77 //config:       bool "Expand prompt string"
78 //config:       default y
79 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
80 //config:       help
81 //config:         $PS# may contain volatile content, such as backquote commands.
82 //config:         This option recreates the prompt string from the environment
83 //config:         variable each time it is displayed.
84 //config:
85 //config:config ASH_IDLE_TIMEOUT
86 //config:       bool "Idle timeout variable $TMOUT"
87 //config:       default y
88 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
89 //config:       help
90 //config:         Enable bash-like auto-logout after $TMOUT seconds of idle time.
91 //config:
92 //config:config ASH_MAIL
93 //config:       bool "Check for new mail in interactive shell"
94 //config:       default y
95 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
96 //config:       help
97 //config:         Enable "check for new mail" function:
98 //config:         if set, $MAIL file and $MAILPATH list of files
99 //config:         are checked for mtime changes, and "you have mail"
100 //config:         message is printed if change is detected.
101 //config:
102 //config:config ASH_ECHO
103 //config:       bool "echo builtin"
104 //config:       default y
105 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
106 //config:
107 //config:config ASH_PRINTF
108 //config:       bool "printf builtin"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:
112 //config:config ASH_TEST
113 //config:       bool "test builtin"
114 //config:       default y
115 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
116 //config:
117 //config:config ASH_HELP
118 //config:       bool "help builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_GETOPTS
123 //config:       bool "getopts builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_CMDCMD
128 //config:       bool "command builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:       help
132 //config:         Enable support for the 'command' builtin, which allows
133 //config:         you to run the specified command or builtin,
134 //config:         even when there is a function with the same name.
135 //config:
136 //config:endif # ash options
137
138 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
139 //                      APPLET_ODDNAME:name  main location    suid_type     help
140 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
142
143 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
146 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
147
148 /*
149  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
150  * DEBUG=2 to compile in and turn on debugging.
151  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
152  * debugging info is written to ./trace, quit signal generates core dump.
153  */
154 #define DEBUG 0
155 /* Tweak debug output verbosity here */
156 #define DEBUG_TIME 0
157 #define DEBUG_PID 1
158 #define DEBUG_SIG 1
159 #define DEBUG_INTONOFF 0
160
161 #define PROFILE 0
162
163 #define JOBS ENABLE_ASH_JOB_CONTROL
164
165 #include <setjmp.h>
166 #include <fnmatch.h>
167 #include <sys/times.h>
168 #include <sys/utsname.h> /* for setting $HOSTNAME */
169 #include "busybox.h" /* for applet_names */
170
171 /* So far, all bash compat is controlled by one config option */
172 /* Separate defines document which part of code implements what */
173 /* function keyword */
174 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
175 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
176 /* &>file */
177 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
178 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
179 /* $'...' */
180 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
181 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
182 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
183 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
184 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
185 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
186 /* [[ EXPR ]] */
187 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
188 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
189 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
190 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
191 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
192
193 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
194 /* Bionic at least up to version 24 has no glob() */
195 # undef  ENABLE_ASH_INTERNAL_GLOB
196 # define ENABLE_ASH_INTERNAL_GLOB 1
197 #endif
198
199 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
200 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
201 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
202 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
203 # error glob() should unbackslash them and match. uClibc does not unbackslash,
204 # error fails to match dirname, subsequently not expanding <pattern> in it.
205 // Testcase:
206 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
207 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
208 #endif
209
210 #if !ENABLE_ASH_INTERNAL_GLOB
211 # include <glob.h>
212 #endif
213
214 #include "unicode.h"
215 #include "shell_common.h"
216 #if ENABLE_FEATURE_SH_MATH
217 # include "math.h"
218 #endif
219 #if ENABLE_ASH_RANDOM_SUPPORT
220 # include "random.h"
221 #else
222 # define CLEAR_RANDOM_T(rnd) ((void)0)
223 #endif
224
225 #include "NUM_APPLETS.h"
226 #if NUM_APPLETS == 1
227 /* STANDALONE does not make sense, and won't compile */
228 # undef CONFIG_FEATURE_SH_STANDALONE
229 # undef ENABLE_FEATURE_SH_STANDALONE
230 # undef IF_FEATURE_SH_STANDALONE
231 # undef IF_NOT_FEATURE_SH_STANDALONE
232 # define ENABLE_FEATURE_SH_STANDALONE 0
233 # define IF_FEATURE_SH_STANDALONE(...)
234 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
235 #endif
236
237 #ifndef PIPE_BUF
238 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
239 #endif
240
241 #if !BB_MMU
242 # error "Do not even bother, ash will not run on NOMMU machine"
243 #endif
244
245
246 /* ============ Hash table sizes. Configurable. */
247
248 #define VTABSIZE 39
249 #define ATABSIZE 39
250 #define CMDTABLESIZE 31         /* should be prime */
251
252
253 /* ============ Shell options */
254
255 static const char *const optletters_optnames[] = {
256         "e"   "errexit",
257         "f"   "noglob",
258         "I"   "ignoreeof",
259         "i"   "interactive",
260         "m"   "monitor",
261         "n"   "noexec",
262         "s"   "stdin",
263         "x"   "xtrace",
264         "v"   "verbose",
265         "C"   "noclobber",
266         "a"   "allexport",
267         "b"   "notify",
268         "u"   "nounset",
269         "\0"  "vi"
270 #if BASH_PIPEFAIL
271         ,"\0"  "pipefail"
272 #endif
273 #if DEBUG
274         ,"\0"  "nolog"
275         ,"\0"  "debug"
276 #endif
277 };
278
279 #define optletters(n)  optletters_optnames[n][0]
280 #define optnames(n)   (optletters_optnames[n] + 1)
281
282 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
283
284
285 /* ============ Misc data */
286
287 #define msg_illnum "Illegal number: %s"
288
289 /*
290  * We enclose jmp_buf in a structure so that we can declare pointers to
291  * jump locations.  The global variable handler contains the location to
292  * jump to when an exception occurs, and the global variable exception_type
293  * contains a code identifying the exception.  To implement nested
294  * exception handlers, the user should save the value of handler on entry
295  * to an inner scope, set handler to point to a jmploc structure for the
296  * inner scope, and restore handler on exit from the scope.
297  */
298 struct jmploc {
299         jmp_buf loc;
300 };
301
302 struct globals_misc {
303         uint8_t exitstatus;     /* exit status of last command */
304         uint8_t back_exitstatus;/* exit status of backquoted command */
305         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
306         int rootpid;            /* pid of main shell */
307         /* shell level: 0 for the main shell, 1 for its children, and so on */
308         int shlvl;
309 #define rootshell (!shlvl)
310         char *minusc;  /* argument to -c option */
311
312         char *curdir; // = nullstr;     /* current working directory */
313         char *physdir; // = nullstr;    /* physical working directory */
314
315         char *arg0; /* value of $0 */
316
317         struct jmploc *exception_handler;
318
319         volatile int suppress_int; /* counter */
320         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
321         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
322         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
323         smallint exception_type; /* kind of exception (0..5) */
324         /* exceptions */
325 #define EXINT 0         /* SIGINT received */
326 #define EXERROR 1       /* a generic error */
327 #define EXEXIT 4        /* exit the shell */
328
329         smallint isloginsh;
330         char nullstr[1];        /* zero length string */
331
332         char optlist[NOPTS];
333 #define eflag optlist[0]
334 #define fflag optlist[1]
335 #define Iflag optlist[2]
336 #define iflag optlist[3]
337 #define mflag optlist[4]
338 #define nflag optlist[5]
339 #define sflag optlist[6]
340 #define xflag optlist[7]
341 #define vflag optlist[8]
342 #define Cflag optlist[9]
343 #define aflag optlist[10]
344 #define bflag optlist[11]
345 #define uflag optlist[12]
346 #define viflag optlist[13]
347 #if BASH_PIPEFAIL
348 # define pipefail optlist[14]
349 #else
350 # define pipefail 0
351 #endif
352 #if DEBUG
353 # define nolog optlist[14 + BASH_PIPEFAIL]
354 # define debug optlist[15 + BASH_PIPEFAIL]
355 #endif
356
357         /* trap handler commands */
358         /*
359          * Sigmode records the current value of the signal handlers for the various
360          * modes.  A value of zero means that the current handler is not known.
361          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
362          */
363         char sigmode[NSIG - 1];
364 #define S_DFL      1            /* default signal handling (SIG_DFL) */
365 #define S_CATCH    2            /* signal is caught */
366 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
367 #define S_HARD_IGN 4            /* signal is ignored permanently */
368
369         /* indicates specified signal received */
370         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
371         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
372         char *trap[NSIG];
373         char **trap_ptr;        /* used only by "trap hack" */
374
375         /* Rarely referenced stuff */
376 #if ENABLE_ASH_RANDOM_SUPPORT
377         random_t random_gen;
378 #endif
379         pid_t backgndpid;        /* pid of last background process */
380 };
381 extern struct globals_misc *const ash_ptr_to_globals_misc;
382 #define G_misc (*ash_ptr_to_globals_misc)
383 #define exitstatus        (G_misc.exitstatus )
384 #define back_exitstatus   (G_misc.back_exitstatus )
385 #define job_warning       (G_misc.job_warning)
386 #define rootpid     (G_misc.rootpid    )
387 #define shlvl       (G_misc.shlvl      )
388 #define minusc      (G_misc.minusc     )
389 #define curdir      (G_misc.curdir     )
390 #define physdir     (G_misc.physdir    )
391 #define arg0        (G_misc.arg0       )
392 #define exception_handler (G_misc.exception_handler)
393 #define exception_type    (G_misc.exception_type   )
394 #define suppress_int      (G_misc.suppress_int     )
395 #define pending_int       (G_misc.pending_int      )
396 #define got_sigchld       (G_misc.got_sigchld      )
397 #define pending_sig       (G_misc.pending_sig      )
398 #define isloginsh   (G_misc.isloginsh  )
399 #define nullstr     (G_misc.nullstr    )
400 #define optlist     (G_misc.optlist    )
401 #define sigmode     (G_misc.sigmode    )
402 #define gotsig      (G_misc.gotsig     )
403 #define may_have_traps    (G_misc.may_have_traps   )
404 #define trap        (G_misc.trap       )
405 #define trap_ptr    (G_misc.trap_ptr   )
406 #define random_gen  (G_misc.random_gen )
407 #define backgndpid  (G_misc.backgndpid )
408 #define INIT_G_misc() do { \
409         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
410         barrier(); \
411         curdir = nullstr; \
412         physdir = nullstr; \
413         trap_ptr = trap; \
414 } while (0)
415
416
417 /* ============ DEBUG */
418 #if DEBUG
419 static void trace_printf(const char *fmt, ...);
420 static void trace_vprintf(const char *fmt, va_list va);
421 # define TRACE(param)    trace_printf param
422 # define TRACEV(param)   trace_vprintf param
423 # define close(fd) do { \
424         int dfd = (fd); \
425         if (close(dfd) < 0) \
426                 bb_error_msg("bug on %d: closing %d(0x%x)", \
427                         __LINE__, dfd, dfd); \
428 } while (0)
429 #else
430 # define TRACE(param)
431 # define TRACEV(param)
432 #endif
433
434
435 /* ============ Utility functions */
436 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
437 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
438
439 static int
440 isdigit_str9(const char *str)
441 {
442         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
443         while (--maxlen && isdigit(*str))
444                 str++;
445         return (*str == '\0');
446 }
447
448 static const char *
449 var_end(const char *var)
450 {
451         while (*var)
452                 if (*var++ == '=')
453                         break;
454         return var;
455 }
456
457
458 /* ============ Interrupts / exceptions */
459
460 static void exitshell(void) NORETURN;
461
462 /*
463  * These macros allow the user to suspend the handling of interrupt signals
464  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
465  * much more efficient and portable.  (But hacking the kernel is so much
466  * more fun than worrying about efficiency and portability. :-))
467  */
468 #if DEBUG_INTONOFF
469 # define INT_OFF do { \
470         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
471         suppress_int++; \
472         barrier(); \
473 } while (0)
474 #else
475 # define INT_OFF do { \
476         suppress_int++; \
477         barrier(); \
478 } while (0)
479 #endif
480
481 /*
482  * Called to raise an exception.  Since C doesn't include exceptions, we
483  * just do a longjmp to the exception handler.  The type of exception is
484  * stored in the global variable "exception_type".
485  */
486 static void raise_exception(int) NORETURN;
487 static void
488 raise_exception(int e)
489 {
490 #if DEBUG
491         if (exception_handler == NULL)
492                 abort();
493 #endif
494         INT_OFF;
495         exception_type = e;
496         longjmp(exception_handler->loc, 1);
497 }
498 #if DEBUG
499 #define raise_exception(e) do { \
500         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
501         raise_exception(e); \
502 } while (0)
503 #endif
504
505 /*
506  * Called when a SIGINT is received.  (If the user specifies
507  * that SIGINT is to be trapped or ignored using the trap builtin, then
508  * this routine is not called.)  Suppressint is nonzero when interrupts
509  * are held using the INT_OFF macro.  (The test for iflag is just
510  * defensive programming.)
511  */
512 static void raise_interrupt(void) NORETURN;
513 static void
514 raise_interrupt(void)
515 {
516         pending_int = 0;
517         /* Signal is not automatically unmasked after it is raised,
518          * do it ourself - unmask all signals */
519         sigprocmask_allsigs(SIG_UNBLOCK);
520         /* pending_sig = 0; - now done in signal_handler() */
521
522         if (!(rootshell && iflag)) {
523                 /* Kill ourself with SIGINT */
524                 signal(SIGINT, SIG_DFL);
525                 raise(SIGINT);
526         }
527         /* bash: ^C even on empty command line sets $? */
528         exitstatus = SIGINT + 128;
529         raise_exception(EXINT);
530         /* NOTREACHED */
531 }
532 #if DEBUG
533 #define raise_interrupt() do { \
534         TRACE(("raising interrupt on line %d\n", __LINE__)); \
535         raise_interrupt(); \
536 } while (0)
537 #endif
538
539 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
540 int_on(void)
541 {
542         barrier();
543         if (--suppress_int == 0 && pending_int) {
544                 raise_interrupt();
545         }
546 }
547 #if DEBUG_INTONOFF
548 # define INT_ON do { \
549         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
550         int_on(); \
551 } while (0)
552 #else
553 # define INT_ON int_on()
554 #endif
555 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
556 force_int_on(void)
557 {
558         barrier();
559         suppress_int = 0;
560         if (pending_int)
561                 raise_interrupt();
562 }
563 #define FORCE_INT_ON force_int_on()
564
565 #define SAVE_INT(v) ((v) = suppress_int)
566
567 #define RESTORE_INT(v) do { \
568         barrier(); \
569         suppress_int = (v); \
570         if (suppress_int == 0 && pending_int) \
571                 raise_interrupt(); \
572 } while (0)
573
574
575 /* ============ Stdout/stderr output */
576
577 static void
578 outstr(const char *p, FILE *file)
579 {
580         INT_OFF;
581         fputs(p, file);
582         INT_ON;
583 }
584
585 static void
586 flush_stdout_stderr(void)
587 {
588         INT_OFF;
589         fflush_all();
590         INT_ON;
591 }
592
593 /* Was called outcslow(c,FILE*), but c was always '\n' */
594 static void
595 newline_and_flush(FILE *dest)
596 {
597         INT_OFF;
598         putc('\n', dest);
599         fflush(dest);
600         INT_ON;
601 }
602
603 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
604 static int
605 out1fmt(const char *fmt, ...)
606 {
607         va_list ap;
608         int r;
609
610         INT_OFF;
611         va_start(ap, fmt);
612         r = vprintf(fmt, ap);
613         va_end(ap);
614         INT_ON;
615         return r;
616 }
617
618 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
619 static int
620 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
621 {
622         va_list ap;
623         int ret;
624
625         va_start(ap, fmt);
626         INT_OFF;
627         ret = vsnprintf(outbuf, length, fmt, ap);
628         va_end(ap);
629         INT_ON;
630         return ret;
631 }
632
633 static void
634 out1str(const char *p)
635 {
636         outstr(p, stdout);
637 }
638
639 static void
640 out2str(const char *p)
641 {
642         outstr(p, stderr);
643         flush_stdout_stderr();
644 }
645
646
647 /* ============ Parser structures */
648
649 /* control characters in argument strings */
650 #define CTL_FIRST CTLESC
651 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
652 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
653 #define CTLENDVAR    ((unsigned char)'\203')
654 #define CTLBACKQ     ((unsigned char)'\204')
655 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
656 #define CTLENDARI    ((unsigned char)'\207')
657 #define CTLQUOTEMARK ((unsigned char)'\210')
658 #define CTL_LAST CTLQUOTEMARK
659
660 /* variable substitution byte (follows CTLVAR) */
661 #define VSTYPE  0x0f            /* type of variable substitution */
662 #define VSNUL   0x10            /* colon--treat the empty string as unset */
663
664 /* values of VSTYPE field */
665 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
666 #define VSMINUS         0x2     /* ${var-text} */
667 #define VSPLUS          0x3     /* ${var+text} */
668 #define VSQUESTION      0x4     /* ${var?message} */
669 #define VSASSIGN        0x5     /* ${var=text} */
670 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
671 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
672 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
673 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
674 #define VSLENGTH        0xa     /* ${#var} */
675 #if BASH_SUBSTR
676 #define VSSUBSTR        0xc     /* ${var:position:length} */
677 #endif
678 #if BASH_PATTERN_SUBST
679 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
680 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
681 #endif
682
683 static const char dolatstr[] ALIGN1 = {
684         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
685 };
686 #define DOLATSTRLEN 6
687
688 #define NCMD      0
689 #define NPIPE     1
690 #define NREDIR    2
691 #define NBACKGND  3
692 #define NSUBSHELL 4
693 #define NAND      5
694 #define NOR       6
695 #define NSEMI     7
696 #define NIF       8
697 #define NWHILE    9
698 #define NUNTIL   10
699 #define NFOR     11
700 #define NCASE    12
701 #define NCLIST   13
702 #define NDEFUN   14
703 #define NARG     15
704 #define NTO      16
705 #if BASH_REDIR_OUTPUT
706 #define NTO2     17
707 #endif
708 #define NCLOBBER 18
709 #define NFROM    19
710 #define NFROMTO  20
711 #define NAPPEND  21
712 #define NTOFD    22
713 #define NFROMFD  23
714 #define NHERE    24
715 #define NXHERE   25
716 #define NNOT     26
717 #define N_NUMBER 27
718
719 union node;
720
721 struct ncmd {
722         smallint type; /* Nxxxx */
723         union node *assign;
724         union node *args;
725         union node *redirect;
726 };
727
728 struct npipe {
729         smallint type;
730         smallint pipe_backgnd;
731         struct nodelist *cmdlist;
732 };
733
734 struct nredir {
735         smallint type;
736         union node *n;
737         union node *redirect;
738 };
739
740 struct nbinary {
741         smallint type;
742         union node *ch1;
743         union node *ch2;
744 };
745
746 struct nif {
747         smallint type;
748         union node *test;
749         union node *ifpart;
750         union node *elsepart;
751 };
752
753 struct nfor {
754         smallint type;
755         union node *args;
756         union node *body;
757         char *var;
758 };
759
760 struct ncase {
761         smallint type;
762         union node *expr;
763         union node *cases;
764 };
765
766 struct nclist {
767         smallint type;
768         union node *next;
769         union node *pattern;
770         union node *body;
771 };
772
773 struct narg {
774         smallint type;
775         union node *next;
776         char *text;
777         struct nodelist *backquote;
778 };
779
780 /* nfile and ndup layout must match!
781  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
782  * that it is actually NTO2 (>&file), and change its type.
783  */
784 struct nfile {
785         smallint type;
786         union node *next;
787         int fd;
788         int _unused_dupfd;
789         union node *fname;
790         char *expfname;
791 };
792
793 struct ndup {
794         smallint type;
795         union node *next;
796         int fd;
797         int dupfd;
798         union node *vname;
799         char *_unused_expfname;
800 };
801
802 struct nhere {
803         smallint type;
804         union node *next;
805         int fd;
806         union node *doc;
807 };
808
809 struct nnot {
810         smallint type;
811         union node *com;
812 };
813
814 union node {
815         smallint type;
816         struct ncmd ncmd;
817         struct npipe npipe;
818         struct nredir nredir;
819         struct nbinary nbinary;
820         struct nif nif;
821         struct nfor nfor;
822         struct ncase ncase;
823         struct nclist nclist;
824         struct narg narg;
825         struct nfile nfile;
826         struct ndup ndup;
827         struct nhere nhere;
828         struct nnot nnot;
829 };
830
831 /*
832  * NODE_EOF is returned by parsecmd when it encounters an end of file.
833  * It must be distinct from NULL.
834  */
835 #define NODE_EOF ((union node *) -1L)
836
837 struct nodelist {
838         struct nodelist *next;
839         union node *n;
840 };
841
842 struct funcnode {
843         int count;
844         union node n;
845 };
846
847 /*
848  * Free a parse tree.
849  */
850 static void
851 freefunc(struct funcnode *f)
852 {
853         if (f && --f->count < 0)
854                 free(f);
855 }
856
857
858 /* ============ Debugging output */
859
860 #if DEBUG
861
862 static FILE *tracefile;
863
864 static void
865 trace_printf(const char *fmt, ...)
866 {
867         va_list va;
868
869         if (debug != 1)
870                 return;
871         if (DEBUG_TIME)
872                 fprintf(tracefile, "%u ", (int) time(NULL));
873         if (DEBUG_PID)
874                 fprintf(tracefile, "[%u] ", (int) getpid());
875         if (DEBUG_SIG)
876                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
877         va_start(va, fmt);
878         vfprintf(tracefile, fmt, va);
879         va_end(va);
880 }
881
882 static void
883 trace_vprintf(const char *fmt, va_list va)
884 {
885         if (debug != 1)
886                 return;
887         vfprintf(tracefile, fmt, va);
888         fprintf(tracefile, "\n");
889 }
890
891 static void
892 trace_puts(const char *s)
893 {
894         if (debug != 1)
895                 return;
896         fputs(s, tracefile);
897 }
898
899 static void
900 trace_puts_quoted(char *s)
901 {
902         char *p;
903         char c;
904
905         if (debug != 1)
906                 return;
907         putc('"', tracefile);
908         for (p = s; *p; p++) {
909                 switch ((unsigned char)*p) {
910                 case '\n': c = 'n'; goto backslash;
911                 case '\t': c = 't'; goto backslash;
912                 case '\r': c = 'r'; goto backslash;
913                 case '\"': c = '\"'; goto backslash;
914                 case '\\': c = '\\'; goto backslash;
915                 case CTLESC: c = 'e'; goto backslash;
916                 case CTLVAR: c = 'v'; goto backslash;
917                 case CTLBACKQ: c = 'q'; goto backslash;
918  backslash:
919                         putc('\\', tracefile);
920                         putc(c, tracefile);
921                         break;
922                 default:
923                         if (*p >= ' ' && *p <= '~')
924                                 putc(*p, tracefile);
925                         else {
926                                 putc('\\', tracefile);
927                                 putc((*p >> 6) & 03, tracefile);
928                                 putc((*p >> 3) & 07, tracefile);
929                                 putc(*p & 07, tracefile);
930                         }
931                         break;
932                 }
933         }
934         putc('"', tracefile);
935 }
936
937 static void
938 trace_puts_args(char **ap)
939 {
940         if (debug != 1)
941                 return;
942         if (!*ap)
943                 return;
944         while (1) {
945                 trace_puts_quoted(*ap);
946                 if (!*++ap) {
947                         putc('\n', tracefile);
948                         break;
949                 }
950                 putc(' ', tracefile);
951         }
952 }
953
954 static void
955 opentrace(void)
956 {
957         char s[100];
958 #ifdef O_APPEND
959         int flags;
960 #endif
961
962         if (debug != 1) {
963                 if (tracefile)
964                         fflush(tracefile);
965                 /* leave open because libedit might be using it */
966                 return;
967         }
968         strcpy(s, "./trace");
969         if (tracefile) {
970                 if (!freopen(s, "a", tracefile)) {
971                         fprintf(stderr, "Can't re-open %s\n", s);
972                         debug = 0;
973                         return;
974                 }
975         } else {
976                 tracefile = fopen(s, "a");
977                 if (tracefile == NULL) {
978                         fprintf(stderr, "Can't open %s\n", s);
979                         debug = 0;
980                         return;
981                 }
982         }
983 #ifdef O_APPEND
984         flags = fcntl(fileno(tracefile), F_GETFL);
985         if (flags >= 0)
986                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
987 #endif
988         setlinebuf(tracefile);
989         fputs("\nTracing started.\n", tracefile);
990 }
991
992 static void
993 indent(int amount, char *pfx, FILE *fp)
994 {
995         int i;
996
997         for (i = 0; i < amount; i++) {
998                 if (pfx && i == amount - 1)
999                         fputs(pfx, fp);
1000                 putc('\t', fp);
1001         }
1002 }
1003
1004 /* little circular references here... */
1005 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1006
1007 static void
1008 sharg(union node *arg, FILE *fp)
1009 {
1010         char *p;
1011         struct nodelist *bqlist;
1012         unsigned char subtype;
1013
1014         if (arg->type != NARG) {
1015                 out1fmt("<node type %d>\n", arg->type);
1016                 abort();
1017         }
1018         bqlist = arg->narg.backquote;
1019         for (p = arg->narg.text; *p; p++) {
1020                 switch ((unsigned char)*p) {
1021                 case CTLESC:
1022                         p++;
1023                         putc(*p, fp);
1024                         break;
1025                 case CTLVAR:
1026                         putc('$', fp);
1027                         putc('{', fp);
1028                         subtype = *++p;
1029                         if (subtype == VSLENGTH)
1030                                 putc('#', fp);
1031
1032                         while (*p != '=') {
1033                                 putc(*p, fp);
1034                                 p++;
1035                         }
1036
1037                         if (subtype & VSNUL)
1038                                 putc(':', fp);
1039
1040                         switch (subtype & VSTYPE) {
1041                         case VSNORMAL:
1042                                 putc('}', fp);
1043                                 break;
1044                         case VSMINUS:
1045                                 putc('-', fp);
1046                                 break;
1047                         case VSPLUS:
1048                                 putc('+', fp);
1049                                 break;
1050                         case VSQUESTION:
1051                                 putc('?', fp);
1052                                 break;
1053                         case VSASSIGN:
1054                                 putc('=', fp);
1055                                 break;
1056                         case VSTRIMLEFT:
1057                                 putc('#', fp);
1058                                 break;
1059                         case VSTRIMLEFTMAX:
1060                                 putc('#', fp);
1061                                 putc('#', fp);
1062                                 break;
1063                         case VSTRIMRIGHT:
1064                                 putc('%', fp);
1065                                 break;
1066                         case VSTRIMRIGHTMAX:
1067                                 putc('%', fp);
1068                                 putc('%', fp);
1069                                 break;
1070                         case VSLENGTH:
1071                                 break;
1072                         default:
1073                                 out1fmt("<subtype %d>", subtype);
1074                         }
1075                         break;
1076                 case CTLENDVAR:
1077                         putc('}', fp);
1078                         break;
1079                 case CTLBACKQ:
1080                         putc('$', fp);
1081                         putc('(', fp);
1082                         shtree(bqlist->n, -1, NULL, fp);
1083                         putc(')', fp);
1084                         break;
1085                 default:
1086                         putc(*p, fp);
1087                         break;
1088                 }
1089         }
1090 }
1091
1092 static void
1093 shcmd(union node *cmd, FILE *fp)
1094 {
1095         union node *np;
1096         int first;
1097         const char *s;
1098         int dftfd;
1099
1100         first = 1;
1101         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1102                 if (!first)
1103                         putc(' ', fp);
1104                 sharg(np, fp);
1105                 first = 0;
1106         }
1107         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1108                 if (!first)
1109                         putc(' ', fp);
1110                 dftfd = 0;
1111                 switch (np->nfile.type) {
1112                 case NTO:      s = ">>"+1; dftfd = 1; break;
1113                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1114                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1115 #if BASH_REDIR_OUTPUT
1116                 case NTO2:
1117 #endif
1118                 case NTOFD:    s = ">&"; dftfd = 1; break;
1119                 case NFROM:    s = "<"; break;
1120                 case NFROMFD:  s = "<&"; break;
1121                 case NFROMTO:  s = "<>"; break;
1122                 default:       s = "*error*"; break;
1123                 }
1124                 if (np->nfile.fd != dftfd)
1125                         fprintf(fp, "%d", np->nfile.fd);
1126                 fputs(s, fp);
1127                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1128                         fprintf(fp, "%d", np->ndup.dupfd);
1129                 } else {
1130                         sharg(np->nfile.fname, fp);
1131                 }
1132                 first = 0;
1133         }
1134 }
1135
1136 static void
1137 shtree(union node *n, int ind, char *pfx, FILE *fp)
1138 {
1139         struct nodelist *lp;
1140         const char *s;
1141
1142         if (n == NULL)
1143                 return;
1144
1145         indent(ind, pfx, fp);
1146
1147         if (n == NODE_EOF) {
1148                 fputs("<EOF>", fp);
1149                 return;
1150         }
1151
1152         switch (n->type) {
1153         case NSEMI:
1154                 s = "; ";
1155                 goto binop;
1156         case NAND:
1157                 s = " && ";
1158                 goto binop;
1159         case NOR:
1160                 s = " || ";
1161  binop:
1162                 shtree(n->nbinary.ch1, ind, NULL, fp);
1163                 /* if (ind < 0) */
1164                         fputs(s, fp);
1165                 shtree(n->nbinary.ch2, ind, NULL, fp);
1166                 break;
1167         case NCMD:
1168                 shcmd(n, fp);
1169                 if (ind >= 0)
1170                         putc('\n', fp);
1171                 break;
1172         case NPIPE:
1173                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1174                         shtree(lp->n, 0, NULL, fp);
1175                         if (lp->next)
1176                                 fputs(" | ", fp);
1177                 }
1178                 if (n->npipe.pipe_backgnd)
1179                         fputs(" &", fp);
1180                 if (ind >= 0)
1181                         putc('\n', fp);
1182                 break;
1183         default:
1184                 fprintf(fp, "<node type %d>", n->type);
1185                 if (ind >= 0)
1186                         putc('\n', fp);
1187                 break;
1188         }
1189 }
1190
1191 static void
1192 showtree(union node *n)
1193 {
1194         trace_puts("showtree called\n");
1195         shtree(n, 1, NULL, stderr);
1196 }
1197
1198 #endif /* DEBUG */
1199
1200
1201 /* ============ Parser data */
1202
1203 /*
1204  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1205  */
1206 struct strlist {
1207         struct strlist *next;
1208         char *text;
1209 };
1210
1211 struct alias;
1212
1213 struct strpush {
1214         struct strpush *prev;   /* preceding string on stack */
1215         char *prev_string;
1216         int prev_left_in_line;
1217 #if ENABLE_ASH_ALIAS
1218         struct alias *ap;       /* if push was associated with an alias */
1219 #endif
1220         char *string;           /* remember the string since it may change */
1221
1222         /* Remember last two characters for pungetc. */
1223         int lastc[2];
1224
1225         /* Number of outstanding calls to pungetc. */
1226         int unget;
1227 };
1228
1229 struct parsefile {
1230         struct parsefile *prev; /* preceding file on stack */
1231         int linno;              /* current line */
1232         int pf_fd;              /* file descriptor (or -1 if string) */
1233         int left_in_line;       /* number of chars left in this line */
1234         int left_in_buffer;     /* number of chars left in this buffer past the line */
1235         char *next_to_pgetc;    /* next char in buffer */
1236         char *buf;              /* input buffer */
1237         struct strpush *strpush; /* for pushing strings at this level */
1238         struct strpush basestrpush; /* so pushing one is fast */
1239
1240         /* Remember last two characters for pungetc. */
1241         int lastc[2];
1242
1243         /* Number of outstanding calls to pungetc. */
1244         int unget;
1245 };
1246
1247 static struct parsefile basepf;        /* top level input file */
1248 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1249 static int startlinno;                 /* line # where last token started */
1250 static char *commandname;              /* currently executing command */
1251 static struct strlist *cmdenviron;     /* environment for builtin command */
1252
1253
1254 /* ============ Message printing */
1255
1256 static void
1257 ash_vmsg(const char *msg, va_list ap)
1258 {
1259         fprintf(stderr, "%s: ", arg0);
1260         if (commandname) {
1261                 if (strcmp(arg0, commandname))
1262                         fprintf(stderr, "%s: ", commandname);
1263                 if (!iflag || g_parsefile->pf_fd > 0)
1264                         fprintf(stderr, "line %d: ", startlinno);
1265         }
1266         vfprintf(stderr, msg, ap);
1267         newline_and_flush(stderr);
1268 }
1269
1270 /*
1271  * Exverror is called to raise the error exception.  If the second argument
1272  * is not NULL then error prints an error message using printf style
1273  * formatting.  It then raises the error exception.
1274  */
1275 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1276 static void
1277 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1278 {
1279 #if DEBUG
1280         if (msg) {
1281                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1282                 TRACEV((msg, ap));
1283         } else
1284                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1285         if (msg)
1286 #endif
1287                 ash_vmsg(msg, ap);
1288
1289         flush_stdout_stderr();
1290         raise_exception(cond);
1291         /* NOTREACHED */
1292 }
1293
1294 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1295 static void
1296 ash_msg_and_raise_error(const char *msg, ...)
1297 {
1298         va_list ap;
1299
1300         exitstatus = 2;
1301
1302         va_start(ap, msg);
1303         ash_vmsg_and_raise(EXERROR, msg, ap);
1304         /* NOTREACHED */
1305         va_end(ap);
1306 }
1307
1308 static void raise_error_syntax(const char *) NORETURN;
1309 static void
1310 raise_error_syntax(const char *msg)
1311 {
1312         ash_msg_and_raise_error("syntax error: %s", msg);
1313         /* NOTREACHED */
1314 }
1315
1316 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1317 static void
1318 ash_msg_and_raise(int cond, const char *msg, ...)
1319 {
1320         va_list ap;
1321
1322         va_start(ap, msg);
1323         ash_vmsg_and_raise(cond, msg, ap);
1324         /* NOTREACHED */
1325         va_end(ap);
1326 }
1327
1328 /*
1329  * error/warning routines for external builtins
1330  */
1331 static void
1332 ash_msg(const char *fmt, ...)
1333 {
1334         va_list ap;
1335
1336         va_start(ap, fmt);
1337         ash_vmsg(fmt, ap);
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * Return a string describing an error.  The returned string may be a
1343  * pointer to a static buffer that will be overwritten on the next call.
1344  * Action describes the operation that got the error.
1345  */
1346 static const char *
1347 errmsg(int e, const char *em)
1348 {
1349         if (e == ENOENT || e == ENOTDIR) {
1350                 return em;
1351         }
1352         return strerror(e);
1353 }
1354
1355
1356 /* ============ Memory allocation */
1357
1358 #if 0
1359 /* I consider these wrappers nearly useless:
1360  * ok, they return you to nearest exception handler, but
1361  * how much memory do you leak in the process, making
1362  * memory starvation worse?
1363  */
1364 static void *
1365 ckrealloc(void * p, size_t nbytes)
1366 {
1367         p = realloc(p, nbytes);
1368         if (!p)
1369                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1370         return p;
1371 }
1372
1373 static void *
1374 ckmalloc(size_t nbytes)
1375 {
1376         return ckrealloc(NULL, nbytes);
1377 }
1378
1379 static void *
1380 ckzalloc(size_t nbytes)
1381 {
1382         return memset(ckmalloc(nbytes), 0, nbytes);
1383 }
1384
1385 static char *
1386 ckstrdup(const char *s)
1387 {
1388         char *p = strdup(s);
1389         if (!p)
1390                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1391         return p;
1392 }
1393 #else
1394 /* Using bbox equivalents. They exit if out of memory */
1395 # define ckrealloc xrealloc
1396 # define ckmalloc  xmalloc
1397 # define ckzalloc  xzalloc
1398 # define ckstrdup  xstrdup
1399 #endif
1400
1401 /*
1402  * It appears that grabstackstr() will barf with such alignments
1403  * because stalloc() will return a string allocated in a new stackblock.
1404  */
1405 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1406 enum {
1407         /* Most machines require the value returned from malloc to be aligned
1408          * in some way.  The following macro will get this right
1409          * on many machines.  */
1410         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1411         /* Minimum size of a block */
1412         MINSIZE = SHELL_ALIGN(504),
1413 };
1414
1415 struct stack_block {
1416         struct stack_block *prev;
1417         char space[MINSIZE];
1418 };
1419
1420 struct stackmark {
1421         struct stack_block *stackp;
1422         char *stacknxt;
1423         size_t stacknleft;
1424 };
1425
1426
1427 struct globals_memstack {
1428         struct stack_block *g_stackp; // = &stackbase;
1429         char *g_stacknxt; // = stackbase.space;
1430         char *sstrend; // = stackbase.space + MINSIZE;
1431         size_t g_stacknleft; // = MINSIZE;
1432         struct stack_block stackbase;
1433 };
1434 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1435 #define G_memstack (*ash_ptr_to_globals_memstack)
1436 #define g_stackp     (G_memstack.g_stackp    )
1437 #define g_stacknxt   (G_memstack.g_stacknxt  )
1438 #define sstrend      (G_memstack.sstrend     )
1439 #define g_stacknleft (G_memstack.g_stacknleft)
1440 #define stackbase    (G_memstack.stackbase   )
1441 #define INIT_G_memstack() do { \
1442         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1443         barrier(); \
1444         g_stackp = &stackbase; \
1445         g_stacknxt = stackbase.space; \
1446         g_stacknleft = MINSIZE; \
1447         sstrend = stackbase.space + MINSIZE; \
1448 } while (0)
1449
1450
1451 #define stackblock()     ((void *)g_stacknxt)
1452 #define stackblocksize() g_stacknleft
1453
1454 /*
1455  * Parse trees for commands are allocated in lifo order, so we use a stack
1456  * to make this more efficient, and also to avoid all sorts of exception
1457  * handling code to handle interrupts in the middle of a parse.
1458  *
1459  * The size 504 was chosen because the Ultrix malloc handles that size
1460  * well.
1461  */
1462 static void *
1463 stalloc(size_t nbytes)
1464 {
1465         char *p;
1466         size_t aligned;
1467
1468         aligned = SHELL_ALIGN(nbytes);
1469         if (aligned > g_stacknleft) {
1470                 size_t len;
1471                 size_t blocksize;
1472                 struct stack_block *sp;
1473
1474                 blocksize = aligned;
1475                 if (blocksize < MINSIZE)
1476                         blocksize = MINSIZE;
1477                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1478                 if (len < blocksize)
1479                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1480                 INT_OFF;
1481                 sp = ckmalloc(len);
1482                 sp->prev = g_stackp;
1483                 g_stacknxt = sp->space;
1484                 g_stacknleft = blocksize;
1485                 sstrend = g_stacknxt + blocksize;
1486                 g_stackp = sp;
1487                 INT_ON;
1488         }
1489         p = g_stacknxt;
1490         g_stacknxt += aligned;
1491         g_stacknleft -= aligned;
1492         return p;
1493 }
1494
1495 static void *
1496 stzalloc(size_t nbytes)
1497 {
1498         return memset(stalloc(nbytes), 0, nbytes);
1499 }
1500
1501 static void
1502 stunalloc(void *p)
1503 {
1504 #if DEBUG
1505         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1506                 write(STDERR_FILENO, "stunalloc\n", 10);
1507                 abort();
1508         }
1509 #endif
1510         g_stacknleft += g_stacknxt - (char *)p;
1511         g_stacknxt = p;
1512 }
1513
1514 /*
1515  * Like strdup but works with the ash stack.
1516  */
1517 static char *
1518 sstrdup(const char *p)
1519 {
1520         size_t len = strlen(p) + 1;
1521         return memcpy(stalloc(len), p, len);
1522 }
1523
1524 static inline void
1525 grabstackblock(size_t len)
1526 {
1527         stalloc(len);
1528 }
1529
1530 static void
1531 pushstackmark(struct stackmark *mark, size_t len)
1532 {
1533         mark->stackp = g_stackp;
1534         mark->stacknxt = g_stacknxt;
1535         mark->stacknleft = g_stacknleft;
1536         grabstackblock(len);
1537 }
1538
1539 static void
1540 setstackmark(struct stackmark *mark)
1541 {
1542         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1543 }
1544
1545 static void
1546 popstackmark(struct stackmark *mark)
1547 {
1548         struct stack_block *sp;
1549
1550         if (!mark->stackp)
1551                 return;
1552
1553         INT_OFF;
1554         while (g_stackp != mark->stackp) {
1555                 sp = g_stackp;
1556                 g_stackp = sp->prev;
1557                 free(sp);
1558         }
1559         g_stacknxt = mark->stacknxt;
1560         g_stacknleft = mark->stacknleft;
1561         sstrend = mark->stacknxt + mark->stacknleft;
1562         INT_ON;
1563 }
1564
1565 /*
1566  * When the parser reads in a string, it wants to stick the string on the
1567  * stack and only adjust the stack pointer when it knows how big the
1568  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1569  * of space on top of the stack and stackblocklen returns the length of
1570  * this block.  Growstackblock will grow this space by at least one byte,
1571  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1572  * part of the block that has been used.
1573  */
1574 static void
1575 growstackblock(void)
1576 {
1577         size_t newlen;
1578
1579         newlen = g_stacknleft * 2;
1580         if (newlen < g_stacknleft)
1581                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1582         if (newlen < 128)
1583                 newlen += 128;
1584
1585         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1586                 struct stack_block *sp;
1587                 struct stack_block *prevstackp;
1588                 size_t grosslen;
1589
1590                 INT_OFF;
1591                 sp = g_stackp;
1592                 prevstackp = sp->prev;
1593                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1594                 sp = ckrealloc(sp, grosslen);
1595                 sp->prev = prevstackp;
1596                 g_stackp = sp;
1597                 g_stacknxt = sp->space;
1598                 g_stacknleft = newlen;
1599                 sstrend = sp->space + newlen;
1600                 INT_ON;
1601         } else {
1602                 char *oldspace = g_stacknxt;
1603                 size_t oldlen = g_stacknleft;
1604                 char *p = stalloc(newlen);
1605
1606                 /* free the space we just allocated */
1607                 g_stacknxt = memcpy(p, oldspace, oldlen);
1608                 g_stacknleft += newlen;
1609         }
1610 }
1611
1612 /*
1613  * The following routines are somewhat easier to use than the above.
1614  * The user declares a variable of type STACKSTR, which may be declared
1615  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1616  * the user uses the macro STPUTC to add characters to the string.  In
1617  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1618  * grown as necessary.  When the user is done, she can just leave the
1619  * string there and refer to it using stackblock().  Or she can allocate
1620  * the space for it using grabstackstr().  If it is necessary to allow
1621  * someone else to use the stack temporarily and then continue to grow
1622  * the string, the user should use grabstack to allocate the space, and
1623  * then call ungrabstr(p) to return to the previous mode of operation.
1624  *
1625  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1626  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1627  * is space for at least one character.
1628  */
1629 static void *
1630 growstackstr(void)
1631 {
1632         size_t len = stackblocksize();
1633         growstackblock();
1634         return (char *)stackblock() + len;
1635 }
1636
1637 /*
1638  * Called from CHECKSTRSPACE.
1639  */
1640 static char *
1641 makestrspace(size_t newlen, char *p)
1642 {
1643         size_t len = p - g_stacknxt;
1644         size_t size;
1645
1646         for (;;) {
1647                 size_t nleft;
1648
1649                 size = stackblocksize();
1650                 nleft = size - len;
1651                 if (nleft >= newlen)
1652                         break;
1653                 growstackblock();
1654         }
1655         return (char *)stackblock() + len;
1656 }
1657
1658 static char *
1659 stack_nputstr(const char *s, size_t n, char *p)
1660 {
1661         p = makestrspace(n, p);
1662         p = (char *)memcpy(p, s, n) + n;
1663         return p;
1664 }
1665
1666 static char *
1667 stack_putstr(const char *s, char *p)
1668 {
1669         return stack_nputstr(s, strlen(s), p);
1670 }
1671
1672 static char *
1673 _STPUTC(int c, char *p)
1674 {
1675         if (p == sstrend)
1676                 p = growstackstr();
1677         *p++ = c;
1678         return p;
1679 }
1680
1681 #define STARTSTACKSTR(p)        ((p) = stackblock())
1682 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1683 #define CHECKSTRSPACE(n, p) do { \
1684         char *q = (p); \
1685         size_t l = (n); \
1686         size_t m = sstrend - q; \
1687         if (l > m) \
1688                 (p) = makestrspace(l, q); \
1689 } while (0)
1690 #define USTPUTC(c, p)           (*(p)++ = (c))
1691 #define STACKSTRNUL(p) do { \
1692         if ((p) == sstrend) \
1693                 (p) = growstackstr(); \
1694         *(p) = '\0'; \
1695 } while (0)
1696 #define STUNPUTC(p)             (--(p))
1697 #define STTOPC(p)               ((p)[-1])
1698 #define STADJUST(amount, p)     ((p) += (amount))
1699
1700 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1701 #define ungrabstackstr(s, p)    stunalloc(s)
1702 #define stackstrend()           ((void *)sstrend)
1703
1704
1705 /* ============ String helpers */
1706
1707 /*
1708  * prefix -- see if pfx is a prefix of string.
1709  */
1710 static char *
1711 prefix(const char *string, const char *pfx)
1712 {
1713         while (*pfx) {
1714                 if (*pfx++ != *string++)
1715                         return NULL;
1716         }
1717         return (char *) string;
1718 }
1719
1720 /*
1721  * Check for a valid number.  This should be elsewhere.
1722  */
1723 static int
1724 is_number(const char *p)
1725 {
1726         do {
1727                 if (!isdigit(*p))
1728                         return 0;
1729         } while (*++p != '\0');
1730         return 1;
1731 }
1732
1733 /*
1734  * Convert a string of digits to an integer, printing an error message on
1735  * failure.
1736  */
1737 static int
1738 number(const char *s)
1739 {
1740         if (!is_number(s))
1741                 ash_msg_and_raise_error(msg_illnum, s);
1742         return atoi(s);
1743 }
1744
1745 /*
1746  * Produce a possibly single quoted string suitable as input to the shell.
1747  * The return string is allocated on the stack.
1748  */
1749 static char *
1750 single_quote(const char *s)
1751 {
1752         char *p;
1753
1754         STARTSTACKSTR(p);
1755
1756         do {
1757                 char *q;
1758                 size_t len;
1759
1760                 len = strchrnul(s, '\'') - s;
1761
1762                 q = p = makestrspace(len + 3, p);
1763
1764                 *q++ = '\'';
1765                 q = (char *)memcpy(q, s, len) + len;
1766                 *q++ = '\'';
1767                 s += len;
1768
1769                 STADJUST(q - p, p);
1770
1771                 if (*s != '\'')
1772                         break;
1773                 len = 0;
1774                 do len++; while (*++s == '\'');
1775
1776                 q = p = makestrspace(len + 3, p);
1777
1778                 *q++ = '"';
1779                 q = (char *)memcpy(q, s - len, len) + len;
1780                 *q++ = '"';
1781
1782                 STADJUST(q - p, p);
1783         } while (*s);
1784
1785         USTPUTC('\0', p);
1786
1787         return stackblock();
1788 }
1789
1790
1791 /* ============ nextopt */
1792
1793 static char **argptr;                  /* argument list for builtin commands */
1794 static char *optionarg;                /* set by nextopt (like getopt) */
1795 static char *optptr;                   /* used by nextopt */
1796
1797 /*
1798  * XXX - should get rid of. Have all builtins use getopt(3).
1799  * The library getopt must have the BSD extension static variable
1800  * "optreset", otherwise it can't be used within the shell safely.
1801  *
1802  * Standard option processing (a la getopt) for builtin routines.
1803  * The only argument that is passed to nextopt is the option string;
1804  * the other arguments are unnecessary. It returns the character,
1805  * or '\0' on end of input.
1806  */
1807 static int
1808 nextopt(const char *optstring)
1809 {
1810         char *p;
1811         const char *q;
1812         char c;
1813
1814         p = optptr;
1815         if (p == NULL || *p == '\0') {
1816                 /* We ate entire "-param", take next one */
1817                 p = *argptr;
1818                 if (p == NULL)
1819                         return '\0';
1820                 if (*p != '-')
1821                         return '\0';
1822                 if (*++p == '\0') /* just "-" ? */
1823                         return '\0';
1824                 argptr++;
1825                 if (LONE_DASH(p)) /* "--" ? */
1826                         return '\0';
1827                 /* p => next "-param" */
1828         }
1829         /* p => some option char in the middle of a "-param" */
1830         c = *p++;
1831         for (q = optstring; *q != c;) {
1832                 if (*q == '\0')
1833                         ash_msg_and_raise_error("illegal option -%c", c);
1834                 if (*++q == ':')
1835                         q++;
1836         }
1837         if (*++q == ':') {
1838                 if (*p == '\0') {
1839                         p = *argptr++;
1840                         if (p == NULL)
1841                                 ash_msg_and_raise_error("no arg for -%c option", c);
1842                 }
1843                 optionarg = p;
1844                 p = NULL;
1845         }
1846         optptr = p;
1847         return c;
1848 }
1849
1850
1851 /* ============ Shell variables */
1852
1853 /*
1854  * The parsefile structure pointed to by the global variable parsefile
1855  * contains information about the current file being read.
1856  */
1857 struct shparam {
1858         int nparam;             /* # of positional parameters (without $0) */
1859 #if ENABLE_ASH_GETOPTS
1860         int optind;             /* next parameter to be processed by getopts */
1861         int optoff;             /* used by getopts */
1862 #endif
1863         unsigned char malloced; /* if parameter list dynamically allocated */
1864         char **p;               /* parameter list */
1865 };
1866
1867 /*
1868  * Free the list of positional parameters.
1869  */
1870 static void
1871 freeparam(volatile struct shparam *param)
1872 {
1873         if (param->malloced) {
1874                 char **ap, **ap1;
1875                 ap = ap1 = param->p;
1876                 while (*ap)
1877                         free(*ap++);
1878                 free(ap1);
1879         }
1880 }
1881
1882 #if ENABLE_ASH_GETOPTS
1883 static void FAST_FUNC getoptsreset(const char *value);
1884 #endif
1885
1886 struct var {
1887         struct var *next;               /* next entry in hash list */
1888         int flags;                      /* flags are defined above */
1889         const char *var_text;           /* name=value */
1890         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1891                                         /* the variable gets set/unset */
1892 };
1893
1894 struct localvar {
1895         struct localvar *next;          /* next local variable in list */
1896         struct var *vp;                 /* the variable that was made local */
1897         int flags;                      /* saved flags */
1898         const char *text;               /* saved text */
1899 };
1900
1901 /* flags */
1902 #define VEXPORT         0x01    /* variable is exported */
1903 #define VREADONLY       0x02    /* variable cannot be modified */
1904 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1905 #define VTEXTFIXED      0x08    /* text is statically allocated */
1906 #define VSTACK          0x10    /* text is allocated on the stack */
1907 #define VUNSET          0x20    /* the variable is not set */
1908 #define VNOFUNC         0x40    /* don't call the callback function */
1909 #define VNOSET          0x80    /* do not set variable - just readonly test */
1910 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1911 #if ENABLE_ASH_RANDOM_SUPPORT
1912 # define VDYNAMIC       0x200   /* dynamic variable */
1913 #else
1914 # define VDYNAMIC       0
1915 #endif
1916
1917
1918 /* Need to be before varinit_data[] */
1919 #if ENABLE_LOCALE_SUPPORT
1920 static void FAST_FUNC
1921 change_lc_all(const char *value)
1922 {
1923         if (value && *value != '\0')
1924                 setlocale(LC_ALL, value);
1925 }
1926 static void FAST_FUNC
1927 change_lc_ctype(const char *value)
1928 {
1929         if (value && *value != '\0')
1930                 setlocale(LC_CTYPE, value);
1931 }
1932 #endif
1933 #if ENABLE_ASH_MAIL
1934 static void chkmail(void);
1935 static void changemail(const char *var_value) FAST_FUNC;
1936 #else
1937 # define chkmail()  ((void)0)
1938 #endif
1939 static void changepath(const char *) FAST_FUNC;
1940 #if ENABLE_ASH_RANDOM_SUPPORT
1941 static void change_random(const char *) FAST_FUNC;
1942 #endif
1943
1944 static const struct {
1945         int flags;
1946         const char *var_text;
1947         void (*var_func)(const char *) FAST_FUNC;
1948 } varinit_data[] = {
1949         /*
1950          * Note: VEXPORT would not work correctly here for NOFORK applets:
1951          * some environment strings may be constant.
1952          */
1953         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1954 #if ENABLE_ASH_MAIL
1955         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1956         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1957 #endif
1958         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1959         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1960         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1961         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1962 #if ENABLE_ASH_GETOPTS
1963         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
1964 #endif
1965 #if ENABLE_ASH_RANDOM_SUPPORT
1966         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1967 #endif
1968 #if ENABLE_LOCALE_SUPPORT
1969         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
1970         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
1971 #endif
1972 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1973         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
1974 #endif
1975 };
1976
1977 struct redirtab;
1978
1979 struct globals_var {
1980         struct shparam shellparam;      /* $@ current positional parameters */
1981         struct redirtab *redirlist;
1982         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1983         struct var *vartab[VTABSIZE];
1984         struct var varinit[ARRAY_SIZE(varinit_data)];
1985 };
1986 extern struct globals_var *const ash_ptr_to_globals_var;
1987 #define G_var (*ash_ptr_to_globals_var)
1988 #define shellparam    (G_var.shellparam   )
1989 //#define redirlist     (G_var.redirlist    )
1990 #define preverrout_fd (G_var.preverrout_fd)
1991 #define vartab        (G_var.vartab       )
1992 #define varinit       (G_var.varinit      )
1993 #define INIT_G_var() do { \
1994         unsigned i; \
1995         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1996         barrier(); \
1997         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1998                 varinit[i].flags    = varinit_data[i].flags; \
1999                 varinit[i].var_text = varinit_data[i].var_text; \
2000                 varinit[i].var_func = varinit_data[i].var_func; \
2001         } \
2002 } while (0)
2003
2004 #define vifs      varinit[0]
2005 #if ENABLE_ASH_MAIL
2006 # define vmail    (&vifs)[1]
2007 # define vmpath   (&vmail)[1]
2008 # define vpath    (&vmpath)[1]
2009 #else
2010 # define vpath    (&vifs)[1]
2011 #endif
2012 #define vps1      (&vpath)[1]
2013 #define vps2      (&vps1)[1]
2014 #define vps4      (&vps2)[1]
2015 #if ENABLE_ASH_GETOPTS
2016 # define voptind  (&vps4)[1]
2017 # if ENABLE_ASH_RANDOM_SUPPORT
2018 #  define vrandom (&voptind)[1]
2019 # endif
2020 #else
2021 # if ENABLE_ASH_RANDOM_SUPPORT
2022 #  define vrandom (&vps4)[1]
2023 # endif
2024 #endif
2025
2026 /*
2027  * The following macros access the values of the above variables.
2028  * They have to skip over the name.  They return the null string
2029  * for unset variables.
2030  */
2031 #define ifsval()        (vifs.var_text + 4)
2032 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2033 #if ENABLE_ASH_MAIL
2034 # define mailval()      (vmail.var_text + 5)
2035 # define mpathval()     (vmpath.var_text + 9)
2036 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2037 #endif
2038 #define pathval()       (vpath.var_text + 5)
2039 #define ps1val()        (vps1.var_text + 4)
2040 #define ps2val()        (vps2.var_text + 4)
2041 #define ps4val()        (vps4.var_text + 4)
2042 #if ENABLE_ASH_GETOPTS
2043 # define optindval()    (voptind.var_text + 7)
2044 #endif
2045
2046 #if ENABLE_ASH_GETOPTS
2047 static void FAST_FUNC
2048 getoptsreset(const char *value)
2049 {
2050         shellparam.optind = number(value) ?: 1;
2051         shellparam.optoff = -1;
2052 }
2053 #endif
2054
2055 /*
2056  * Compares two strings up to the first = or '\0'.  The first
2057  * string must be terminated by '='; the second may be terminated by
2058  * either '=' or '\0'.
2059  */
2060 static int
2061 varcmp(const char *p, const char *q)
2062 {
2063         int c, d;
2064
2065         while ((c = *p) == (d = *q)) {
2066                 if (c == '\0' || c == '=')
2067                         goto out;
2068                 p++;
2069                 q++;
2070         }
2071         if (c == '=')
2072                 c = '\0';
2073         if (d == '=')
2074                 d = '\0';
2075  out:
2076         return c - d;
2077 }
2078
2079 /*
2080  * Find the appropriate entry in the hash table from the name.
2081  */
2082 static struct var **
2083 hashvar(const char *p)
2084 {
2085         unsigned hashval;
2086
2087         hashval = ((unsigned char) *p) << 4;
2088         while (*p && *p != '=')
2089                 hashval += (unsigned char) *p++;
2090         return &vartab[hashval % VTABSIZE];
2091 }
2092
2093 static int
2094 vpcmp(const void *a, const void *b)
2095 {
2096         return varcmp(*(const char **)a, *(const char **)b);
2097 }
2098
2099 /*
2100  * This routine initializes the builtin variables.
2101  */
2102 static void
2103 initvar(void)
2104 {
2105         struct var *vp;
2106         struct var *end;
2107         struct var **vpp;
2108
2109         /*
2110          * PS1 depends on uid
2111          */
2112 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2113         vps1.var_text = "PS1=\\w \\$ ";
2114 #else
2115         if (!geteuid())
2116                 vps1.var_text = "PS1=# ";
2117 #endif
2118         vp = varinit;
2119         end = vp + ARRAY_SIZE(varinit);
2120         do {
2121                 vpp = hashvar(vp->var_text);
2122                 vp->next = *vpp;
2123                 *vpp = vp;
2124         } while (++vp < end);
2125 }
2126
2127 static struct var **
2128 findvar(struct var **vpp, const char *name)
2129 {
2130         for (; *vpp; vpp = &(*vpp)->next) {
2131                 if (varcmp((*vpp)->var_text, name) == 0) {
2132                         break;
2133                 }
2134         }
2135         return vpp;
2136 }
2137
2138 /*
2139  * Find the value of a variable.  Returns NULL if not set.
2140  */
2141 static const char* FAST_FUNC
2142 lookupvar(const char *name)
2143 {
2144         struct var *v;
2145
2146         v = *findvar(hashvar(name), name);
2147         if (v) {
2148 #if ENABLE_ASH_RANDOM_SUPPORT
2149         /*
2150          * Dynamic variables are implemented roughly the same way they are
2151          * in bash. Namely, they're "special" so long as they aren't unset.
2152          * As soon as they're unset, they're no longer dynamic, and dynamic
2153          * lookup will no longer happen at that point. -- PFM.
2154          */
2155                 if (v->flags & VDYNAMIC)
2156                         v->var_func(NULL);
2157 #endif
2158                 if (!(v->flags & VUNSET))
2159                         return var_end(v->var_text);
2160         }
2161         return NULL;
2162 }
2163
2164 #if ENABLE_UNICODE_SUPPORT
2165 static void
2166 reinit_unicode_for_ash(void)
2167 {
2168         /* Unicode support should be activated even if LANG is set
2169          * _during_ shell execution, not only if it was set when
2170          * shell was started. Therefore, re-check LANG every time:
2171          */
2172         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2173          || ENABLE_UNICODE_USING_LOCALE
2174         ) {
2175                 const char *s = lookupvar("LC_ALL");
2176                 if (!s) s = lookupvar("LC_CTYPE");
2177                 if (!s) s = lookupvar("LANG");
2178                 reinit_unicode(s);
2179         }
2180 }
2181 #else
2182 # define reinit_unicode_for_ash() ((void)0)
2183 #endif
2184
2185 /*
2186  * Search the environment of a builtin command.
2187  */
2188 static const char *
2189 bltinlookup(const char *name)
2190 {
2191         struct strlist *sp;
2192
2193         for (sp = cmdenviron; sp; sp = sp->next) {
2194                 if (varcmp(sp->text, name) == 0)
2195                         return var_end(sp->text);
2196         }
2197         return lookupvar(name);
2198 }
2199
2200 /*
2201  * Same as setvar except that the variable and value are passed in
2202  * the first argument as name=value.  Since the first argument will
2203  * be actually stored in the table, it should not be a string that
2204  * will go away.
2205  * Called with interrupts off.
2206  */
2207 static void
2208 setvareq(char *s, int flags)
2209 {
2210         struct var *vp, **vpp;
2211
2212         vpp = hashvar(s);
2213         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2214         vp = *findvar(vpp, s);
2215         if (vp) {
2216                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2217                         const char *n;
2218
2219                         if (flags & VNOSAVE)
2220                                 free(s);
2221                         n = vp->var_text;
2222                         exitstatus = 1;
2223                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2224                 }
2225
2226                 if (flags & VNOSET)
2227                         return;
2228
2229                 if (vp->var_func && !(flags & VNOFUNC))
2230                         vp->var_func(var_end(s));
2231
2232                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2233                         free((char*)vp->var_text);
2234
2235                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2236         } else {
2237                 /* variable s is not found */
2238                 if (flags & VNOSET)
2239                         return;
2240                 vp = ckzalloc(sizeof(*vp));
2241                 vp->next = *vpp;
2242                 /*vp->func = NULL; - ckzalloc did it */
2243                 *vpp = vp;
2244         }
2245         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2246                 s = ckstrdup(s);
2247         vp->var_text = s;
2248         vp->flags = flags;
2249 }
2250
2251 /*
2252  * Set the value of a variable.  The flags argument is ored with the
2253  * flags of the variable.  If val is NULL, the variable is unset.
2254  */
2255 static void
2256 setvar(const char *name, const char *val, int flags)
2257 {
2258         const char *q;
2259         char *p;
2260         char *nameeq;
2261         size_t namelen;
2262         size_t vallen;
2263
2264         q = endofname(name);
2265         p = strchrnul(q, '=');
2266         namelen = p - name;
2267         if (!namelen || p != q)
2268                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2269         vallen = 0;
2270         if (val == NULL) {
2271                 flags |= VUNSET;
2272         } else {
2273                 vallen = strlen(val);
2274         }
2275
2276         INT_OFF;
2277         nameeq = ckmalloc(namelen + vallen + 2);
2278         p = memcpy(nameeq, name, namelen) + namelen;
2279         if (val) {
2280                 *p++ = '=';
2281                 p = memcpy(p, val, vallen) + vallen;
2282         }
2283         *p = '\0';
2284         setvareq(nameeq, flags | VNOSAVE);
2285         INT_ON;
2286 }
2287
2288 static void FAST_FUNC
2289 setvar0(const char *name, const char *val)
2290 {
2291         setvar(name, val, 0);
2292 }
2293
2294 /*
2295  * Unset the specified variable.
2296  */
2297 static int
2298 unsetvar(const char *s)
2299 {
2300         struct var **vpp;
2301         struct var *vp;
2302         int retval;
2303
2304         vpp = findvar(hashvar(s), s);
2305         vp = *vpp;
2306         retval = 2;
2307         if (vp) {
2308                 int flags = vp->flags;
2309
2310                 retval = 1;
2311                 if (flags & VREADONLY)
2312                         goto out;
2313 #if ENABLE_ASH_RANDOM_SUPPORT
2314                 vp->flags &= ~VDYNAMIC;
2315 #endif
2316                 if (flags & VUNSET)
2317                         goto ok;
2318                 if ((flags & VSTRFIXED) == 0) {
2319                         INT_OFF;
2320                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2321                                 free((char*)vp->var_text);
2322                         *vpp = vp->next;
2323                         free(vp);
2324                         INT_ON;
2325                 } else {
2326                         setvar0(s, NULL);
2327                         vp->flags &= ~VEXPORT;
2328                 }
2329  ok:
2330                 retval = 0;
2331         }
2332  out:
2333         return retval;
2334 }
2335
2336 /*
2337  * Process a linked list of variable assignments.
2338  */
2339 static void
2340 listsetvar(struct strlist *list_set_var, int flags)
2341 {
2342         struct strlist *lp = list_set_var;
2343
2344         if (!lp)
2345                 return;
2346         INT_OFF;
2347         do {
2348                 setvareq(lp->text, flags);
2349                 lp = lp->next;
2350         } while (lp);
2351         INT_ON;
2352 }
2353
2354 /*
2355  * Generate a list of variables satisfying the given conditions.
2356  */
2357 static char **
2358 listvars(int on, int off, char ***end)
2359 {
2360         struct var **vpp;
2361         struct var *vp;
2362         char **ep;
2363         int mask;
2364
2365         STARTSTACKSTR(ep);
2366         vpp = vartab;
2367         mask = on | off;
2368         do {
2369                 for (vp = *vpp; vp; vp = vp->next) {
2370                         if ((vp->flags & mask) == on) {
2371                                 if (ep == stackstrend())
2372                                         ep = growstackstr();
2373                                 *ep++ = (char*)vp->var_text;
2374                         }
2375                 }
2376         } while (++vpp < vartab + VTABSIZE);
2377         if (ep == stackstrend())
2378                 ep = growstackstr();
2379         if (end)
2380                 *end = ep;
2381         *ep++ = NULL;
2382         return grabstackstr(ep);
2383 }
2384
2385
2386 /* ============ Path search helper
2387  *
2388  * The variable path (passed by reference) should be set to the start
2389  * of the path before the first call; path_advance will update
2390  * this value as it proceeds.  Successive calls to path_advance will return
2391  * the possible path expansions in sequence.  If an option (indicated by
2392  * a percent sign) appears in the path entry then the global variable
2393  * pathopt will be set to point to it; otherwise pathopt will be set to
2394  * NULL.
2395  */
2396 static const char *pathopt;     /* set by path_advance */
2397
2398 static char *
2399 path_advance(const char **path, const char *name)
2400 {
2401         const char *p;
2402         char *q;
2403         const char *start;
2404         size_t len;
2405
2406         if (*path == NULL)
2407                 return NULL;
2408         start = *path;
2409         for (p = start; *p && *p != ':' && *p != '%'; p++)
2410                 continue;
2411         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2412         while (stackblocksize() < len)
2413                 growstackblock();
2414         q = stackblock();
2415         if (p != start) {
2416                 memcpy(q, start, p - start);
2417                 q += p - start;
2418                 *q++ = '/';
2419         }
2420         strcpy(q, name);
2421         pathopt = NULL;
2422         if (*p == '%') {
2423                 pathopt = ++p;
2424                 while (*p && *p != ':')
2425                         p++;
2426         }
2427         if (*p == ':')
2428                 *path = p + 1;
2429         else
2430                 *path = NULL;
2431         return stalloc(len);
2432 }
2433
2434
2435 /* ============ Prompt */
2436
2437 static smallint doprompt;                   /* if set, prompt the user */
2438 static smallint needprompt;                 /* true if interactive and at start of line */
2439
2440 #if ENABLE_FEATURE_EDITING
2441 static line_input_t *line_input_state;
2442 static const char *cmdedit_prompt;
2443 static void
2444 putprompt(const char *s)
2445 {
2446         if (ENABLE_ASH_EXPAND_PRMT) {
2447                 free((char*)cmdedit_prompt);
2448                 cmdedit_prompt = ckstrdup(s);
2449                 return;
2450         }
2451         cmdedit_prompt = s;
2452 }
2453 #else
2454 static void
2455 putprompt(const char *s)
2456 {
2457         out2str(s);
2458 }
2459 #endif
2460
2461 /* expandstr() needs parsing machinery, so it is far away ahead... */
2462 static const char *expandstr(const char *ps);
2463
2464 static void
2465 setprompt_if(smallint do_set, int whichprompt)
2466 {
2467         const char *prompt;
2468         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2469
2470         if (!do_set)
2471                 return;
2472
2473         needprompt = 0;
2474
2475         switch (whichprompt) {
2476         case 1:
2477                 prompt = ps1val();
2478                 break;
2479         case 2:
2480                 prompt = ps2val();
2481                 break;
2482         default:                        /* 0 */
2483                 prompt = nullstr;
2484         }
2485 #if ENABLE_ASH_EXPAND_PRMT
2486         pushstackmark(&smark, stackblocksize());
2487         putprompt(expandstr(prompt));
2488         popstackmark(&smark);
2489 #else
2490         putprompt(prompt);
2491 #endif
2492 }
2493
2494
2495 /* ============ The cd and pwd commands */
2496
2497 #define CD_PHYSICAL 1
2498 #define CD_PRINT 2
2499
2500 static int
2501 cdopt(void)
2502 {
2503         int flags = 0;
2504         int i, j;
2505
2506         j = 'L';
2507         while ((i = nextopt("LP")) != '\0') {
2508                 if (i != j) {
2509                         flags ^= CD_PHYSICAL;
2510                         j = i;
2511                 }
2512         }
2513
2514         return flags;
2515 }
2516
2517 /*
2518  * Update curdir (the name of the current directory) in response to a
2519  * cd command.
2520  */
2521 static const char *
2522 updatepwd(const char *dir)
2523 {
2524         char *new;
2525         char *p;
2526         char *cdcomppath;
2527         const char *lim;
2528
2529         cdcomppath = sstrdup(dir);
2530         STARTSTACKSTR(new);
2531         if (*dir != '/') {
2532                 if (curdir == nullstr)
2533                         return 0;
2534                 new = stack_putstr(curdir, new);
2535         }
2536         new = makestrspace(strlen(dir) + 2, new);
2537         lim = (char *)stackblock() + 1;
2538         if (*dir != '/') {
2539                 if (new[-1] != '/')
2540                         USTPUTC('/', new);
2541                 if (new > lim && *lim == '/')
2542                         lim++;
2543         } else {
2544                 USTPUTC('/', new);
2545                 cdcomppath++;
2546                 if (dir[1] == '/' && dir[2] != '/') {
2547                         USTPUTC('/', new);
2548                         cdcomppath++;
2549                         lim++;
2550                 }
2551         }
2552         p = strtok(cdcomppath, "/");
2553         while (p) {
2554                 switch (*p) {
2555                 case '.':
2556                         if (p[1] == '.' && p[2] == '\0') {
2557                                 while (new > lim) {
2558                                         STUNPUTC(new);
2559                                         if (new[-1] == '/')
2560                                                 break;
2561                                 }
2562                                 break;
2563                         }
2564                         if (p[1] == '\0')
2565                                 break;
2566                         /* fall through */
2567                 default:
2568                         new = stack_putstr(p, new);
2569                         USTPUTC('/', new);
2570                 }
2571                 p = strtok(NULL, "/");
2572         }
2573         if (new > lim)
2574                 STUNPUTC(new);
2575         *new = 0;
2576         return stackblock();
2577 }
2578
2579 /*
2580  * Find out what the current directory is. If we already know the current
2581  * directory, this routine returns immediately.
2582  */
2583 static char *
2584 getpwd(void)
2585 {
2586         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2587         return dir ? dir : nullstr;
2588 }
2589
2590 static void
2591 setpwd(const char *val, int setold)
2592 {
2593         char *oldcur, *dir;
2594
2595         oldcur = dir = curdir;
2596
2597         if (setold) {
2598                 setvar("OLDPWD", oldcur, VEXPORT);
2599         }
2600         INT_OFF;
2601         if (physdir != nullstr) {
2602                 if (physdir != oldcur)
2603                         free(physdir);
2604                 physdir = nullstr;
2605         }
2606         if (oldcur == val || !val) {
2607                 char *s = getpwd();
2608                 physdir = s;
2609                 if (!val)
2610                         dir = s;
2611         } else
2612                 dir = ckstrdup(val);
2613         if (oldcur != dir && oldcur != nullstr) {
2614                 free(oldcur);
2615         }
2616         curdir = dir;
2617         INT_ON;
2618         setvar("PWD", dir, VEXPORT);
2619 }
2620
2621 static void hashcd(void);
2622
2623 /*
2624  * Actually do the chdir.  We also call hashcd to let other routines
2625  * know that the current directory has changed.
2626  */
2627 static int
2628 docd(const char *dest, int flags)
2629 {
2630         const char *dir = NULL;
2631         int err;
2632
2633         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2634
2635         INT_OFF;
2636         if (!(flags & CD_PHYSICAL)) {
2637                 dir = updatepwd(dest);
2638                 if (dir)
2639                         dest = dir;
2640         }
2641         err = chdir(dest);
2642         if (err)
2643                 goto out;
2644         setpwd(dir, 1);
2645         hashcd();
2646  out:
2647         INT_ON;
2648         return err;
2649 }
2650
2651 static int FAST_FUNC
2652 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2653 {
2654         const char *dest;
2655         const char *path;
2656         const char *p;
2657         char c;
2658         struct stat statb;
2659         int flags;
2660
2661         flags = cdopt();
2662         dest = *argptr;
2663         if (!dest)
2664                 dest = bltinlookup("HOME");
2665         else if (LONE_DASH(dest)) {
2666                 dest = bltinlookup("OLDPWD");
2667                 flags |= CD_PRINT;
2668         }
2669         if (!dest)
2670                 dest = nullstr;
2671         if (*dest == '/')
2672                 goto step6;
2673         if (*dest == '.') {
2674                 c = dest[1];
2675  dotdot:
2676                 switch (c) {
2677                 case '\0':
2678                 case '/':
2679                         goto step6;
2680                 case '.':
2681                         c = dest[2];
2682                         if (c != '.')
2683                                 goto dotdot;
2684                 }
2685         }
2686         if (!*dest)
2687                 dest = ".";
2688         path = bltinlookup("CDPATH");
2689         while (path) {
2690                 c = *path;
2691                 p = path_advance(&path, dest);
2692                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2693                         if (c && c != ':')
2694                                 flags |= CD_PRINT;
2695  docd:
2696                         if (!docd(p, flags))
2697                                 goto out;
2698                         goto err;
2699                 }
2700         }
2701
2702  step6:
2703         p = dest;
2704         goto docd;
2705
2706  err:
2707         ash_msg_and_raise_error("can't cd to %s", dest);
2708         /* NOTREACHED */
2709  out:
2710         if (flags & CD_PRINT)
2711                 out1fmt("%s\n", curdir);
2712         return 0;
2713 }
2714
2715 static int FAST_FUNC
2716 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2717 {
2718         int flags;
2719         const char *dir = curdir;
2720
2721         flags = cdopt();
2722         if (flags) {
2723                 if (physdir == nullstr)
2724                         setpwd(dir, 0);
2725                 dir = physdir;
2726         }
2727         out1fmt("%s\n", dir);
2728         return 0;
2729 }
2730
2731
2732 /* ============ ... */
2733
2734
2735 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2736
2737 /* Syntax classes */
2738 #define CWORD     0             /* character is nothing special */
2739 #define CNL       1             /* newline character */
2740 #define CBACK     2             /* a backslash character */
2741 #define CSQUOTE   3             /* single quote */
2742 #define CDQUOTE   4             /* double quote */
2743 #define CENDQUOTE 5             /* a terminating quote */
2744 #define CBQUOTE   6             /* backwards single quote */
2745 #define CVAR      7             /* a dollar sign */
2746 #define CENDVAR   8             /* a '}' character */
2747 #define CLP       9             /* a left paren in arithmetic */
2748 #define CRP      10             /* a right paren in arithmetic */
2749 #define CENDFILE 11             /* end of file */
2750 #define CCTL     12             /* like CWORD, except it must be escaped */
2751 #define CSPCL    13             /* these terminate a word */
2752 #define CIGN     14             /* character should be ignored */
2753
2754 #define PEOF     256
2755 #if ENABLE_ASH_ALIAS
2756 # define PEOA    257
2757 #endif
2758
2759 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2760
2761 #if ENABLE_FEATURE_SH_MATH
2762 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2763 #else
2764 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2765 #endif
2766 static const uint16_t S_I_T[] ALIGN2 = {
2767 #if ENABLE_ASH_ALIAS
2768         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2769 #endif
2770         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2771         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2772         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2773         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2774         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2775         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2776         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2777         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2778         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2779         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2780         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2781 #if !USE_SIT_FUNCTION
2782         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2783         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2784         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2785 #endif
2786 #undef SIT_ITEM
2787 };
2788 /* Constants below must match table above */
2789 enum {
2790 #if ENABLE_ASH_ALIAS
2791         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2792 #endif
2793         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2794         CNL_CNL_CNL_CNL                    , /*  2 */
2795         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2796         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2797         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2798         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2799         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2800         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2801         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2802         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2803         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2804         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2805         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2806         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2807 };
2808
2809 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2810  * caller must ensure proper cast on it if c is *char_ptr!
2811  */
2812 /* Values for syntax param */
2813 #define BASESYNTAX 0    /* not in quotes */
2814 #define DQSYNTAX   1    /* in double quotes */
2815 #define SQSYNTAX   2    /* in single quotes */
2816 #define ARISYNTAX  3    /* in arithmetic */
2817 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2818
2819 #if USE_SIT_FUNCTION
2820
2821 static int
2822 SIT(int c, int syntax)
2823 {
2824         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2825         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2826         /*
2827          * This causes '/' to be prepended with CTLESC in dquoted string,
2828          * making "./file"* treated incorrectly because we feed
2829          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2830          * The "homegrown" glob implementation is okay with that,
2831          * but glibc one isn't. With '/' always treated as CWORD,
2832          * both work fine.
2833          */
2834 # if ENABLE_ASH_ALIAS
2835         static const uint8_t syntax_index_table[] ALIGN1 = {
2836                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2837                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2838                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2839                 11, 3                           /* "}~" */
2840         };
2841 # else
2842         static const uint8_t syntax_index_table[] ALIGN1 = {
2843                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2844                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2845                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2846                 10, 2                           /* "}~" */
2847         };
2848 # endif
2849         const char *s;
2850         int indx;
2851
2852         if (c == PEOF)
2853                 return CENDFILE;
2854 # if ENABLE_ASH_ALIAS
2855         if (c == PEOA)
2856                 indx = 0;
2857         else
2858 # endif
2859         {
2860                 /* Cast is purely for paranoia here,
2861                  * just in case someone passed signed char to us */
2862                 if ((unsigned char)c >= CTL_FIRST
2863                  && (unsigned char)c <= CTL_LAST
2864                 ) {
2865                         return CCTL;
2866                 }
2867                 s = strchrnul(spec_symbls, c);
2868                 if (*s == '\0')
2869                         return CWORD;
2870                 indx = syntax_index_table[s - spec_symbls];
2871         }
2872         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2873 }
2874
2875 #else   /* !USE_SIT_FUNCTION */
2876
2877 static const uint8_t syntax_index_table[] ALIGN1 = {
2878         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2879         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2880         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2881         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2882         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2883         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2884         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2885         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2886         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2887         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2888         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2889         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2890         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2891         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2892         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2893         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2894         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2895         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2896         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2897         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2898         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2899         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2900         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2901         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2902         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2903         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2904         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2912         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2913         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2914         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2915         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2916         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2917         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2918         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2919         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2920         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2921         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2922         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2923         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2924         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2925         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2926 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2927         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2928         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2930         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2939         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2940         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2941         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2942         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2943         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2944         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2972         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2973         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2974         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2977         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2980         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2981         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2982         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2983         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2984         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2985         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2986         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2987         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2988         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2989         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3005         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3006         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3007         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3008         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3009         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3010         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3011         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3012         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3013         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3014         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3015         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3016         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3017         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3018         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3019         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3020         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3021         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3136         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3137 # if ENABLE_ASH_ALIAS
3138         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3139 # endif
3140 };
3141
3142 #if 1
3143 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3144 #else /* debug version, caught one signed char bug */
3145 # define SIT(c, syntax) \
3146         ({ \
3147                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3148                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3149                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3150                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3151                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3152         })
3153 #endif
3154
3155 #endif  /* !USE_SIT_FUNCTION */
3156
3157
3158 /* ============ Alias handling */
3159
3160 #if ENABLE_ASH_ALIAS
3161
3162 #define ALIASINUSE 1
3163 #define ALIASDEAD  2
3164
3165 struct alias {
3166         struct alias *next;
3167         char *name;
3168         char *val;
3169         int flag;
3170 };
3171
3172
3173 static struct alias **atab; // [ATABSIZE];
3174 #define INIT_G_alias() do { \
3175         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3176 } while (0)
3177
3178
3179 static struct alias **
3180 __lookupalias(const char *name)
3181 {
3182         unsigned int hashval;
3183         struct alias **app;
3184         const char *p;
3185         unsigned int ch;
3186
3187         p = name;
3188
3189         ch = (unsigned char)*p;
3190         hashval = ch << 4;
3191         while (ch) {
3192                 hashval += ch;
3193                 ch = (unsigned char)*++p;
3194         }
3195         app = &atab[hashval % ATABSIZE];
3196
3197         for (; *app; app = &(*app)->next) {
3198                 if (strcmp(name, (*app)->name) == 0) {
3199                         break;
3200                 }
3201         }
3202
3203         return app;
3204 }
3205
3206 static struct alias *
3207 lookupalias(const char *name, int check)
3208 {
3209         struct alias *ap = *__lookupalias(name);
3210
3211         if (check && ap && (ap->flag & ALIASINUSE))
3212                 return NULL;
3213         return ap;
3214 }
3215
3216 static struct alias *
3217 freealias(struct alias *ap)
3218 {
3219         struct alias *next;
3220
3221         if (ap->flag & ALIASINUSE) {
3222                 ap->flag |= ALIASDEAD;
3223                 return ap;
3224         }
3225
3226         next = ap->next;
3227         free(ap->name);
3228         free(ap->val);
3229         free(ap);
3230         return next;
3231 }
3232
3233 static void
3234 setalias(const char *name, const char *val)
3235 {
3236         struct alias *ap, **app;
3237
3238         app = __lookupalias(name);
3239         ap = *app;
3240         INT_OFF;
3241         if (ap) {
3242                 if (!(ap->flag & ALIASINUSE)) {
3243                         free(ap->val);
3244                 }
3245                 ap->val = ckstrdup(val);
3246                 ap->flag &= ~ALIASDEAD;
3247         } else {
3248                 /* not found */
3249                 ap = ckzalloc(sizeof(struct alias));
3250                 ap->name = ckstrdup(name);
3251                 ap->val = ckstrdup(val);
3252                 /*ap->flag = 0; - ckzalloc did it */
3253                 /*ap->next = NULL;*/
3254                 *app = ap;
3255         }
3256         INT_ON;
3257 }
3258
3259 static int
3260 unalias(const char *name)
3261 {
3262         struct alias **app;
3263
3264         app = __lookupalias(name);
3265
3266         if (*app) {
3267                 INT_OFF;
3268                 *app = freealias(*app);
3269                 INT_ON;
3270                 return 0;
3271         }
3272
3273         return 1;
3274 }
3275
3276 static void
3277 rmaliases(void)
3278 {
3279         struct alias *ap, **app;
3280         int i;
3281
3282         INT_OFF;
3283         for (i = 0; i < ATABSIZE; i++) {
3284                 app = &atab[i];
3285                 for (ap = *app; ap; ap = *app) {
3286                         *app = freealias(*app);
3287                         if (ap == *app) {
3288                                 app = &ap->next;
3289                         }
3290                 }
3291         }
3292         INT_ON;
3293 }
3294
3295 static void
3296 printalias(const struct alias *ap)
3297 {
3298         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3299 }
3300
3301 /*
3302  * TODO - sort output
3303  */
3304 static int FAST_FUNC
3305 aliascmd(int argc UNUSED_PARAM, char **argv)
3306 {
3307         char *n, *v;
3308         int ret = 0;
3309         struct alias *ap;
3310
3311         if (!argv[1]) {
3312                 int i;
3313
3314                 for (i = 0; i < ATABSIZE; i++) {
3315                         for (ap = atab[i]; ap; ap = ap->next) {
3316                                 printalias(ap);
3317                         }
3318                 }
3319                 return 0;
3320         }
3321         while ((n = *++argv) != NULL) {
3322                 v = strchr(n+1, '=');
3323                 if (v == NULL) { /* n+1: funny ksh stuff */
3324                         ap = *__lookupalias(n);
3325                         if (ap == NULL) {
3326                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3327                                 ret = 1;
3328                         } else
3329                                 printalias(ap);
3330                 } else {
3331                         *v++ = '\0';
3332                         setalias(n, v);
3333                 }
3334         }
3335
3336         return ret;
3337 }
3338
3339 static int FAST_FUNC
3340 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3341 {
3342         int i;
3343
3344         while (nextopt("a") != '\0') {
3345                 rmaliases();
3346                 return 0;
3347         }
3348         for (i = 0; *argptr; argptr++) {
3349                 if (unalias(*argptr)) {
3350                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3351                         i = 1;
3352                 }
3353         }
3354
3355         return i;
3356 }
3357
3358 #endif /* ASH_ALIAS */
3359
3360
3361 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3362 #define FORK_FG    0
3363 #define FORK_BG    1
3364 #define FORK_NOJOB 2
3365
3366 /* mode flags for showjob(s) */
3367 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3368 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3369 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3370 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3371
3372 /*
3373  * A job structure contains information about a job.  A job is either a
3374  * single process or a set of processes contained in a pipeline.  In the
3375  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3376  * array of pids.
3377  */
3378 struct procstat {
3379         pid_t   ps_pid;         /* process id */
3380         int     ps_status;      /* last process status from wait() */
3381         char    *ps_cmd;        /* text of command being run */
3382 };
3383
3384 struct job {
3385         struct procstat ps0;    /* status of process */
3386         struct procstat *ps;    /* status or processes when more than one */
3387 #if JOBS
3388         int stopstatus;         /* status of a stopped job */
3389 #endif
3390         unsigned nprocs;        /* number of processes */
3391
3392 #define JOBRUNNING      0       /* at least one proc running */
3393 #define JOBSTOPPED      1       /* all procs are stopped */
3394 #define JOBDONE         2       /* all procs are completed */
3395         unsigned
3396                 state: 8,
3397 #if JOBS
3398                 sigint: 1,      /* job was killed by SIGINT */
3399                 jobctl: 1,      /* job running under job control */
3400 #endif
3401                 waited: 1,      /* true if this entry has been waited for */
3402                 used: 1,        /* true if this entry is in used */
3403                 changed: 1;     /* true if status has changed */
3404         struct job *prev_job;   /* previous job */
3405 };
3406
3407 static struct job *makejob(/*union node *,*/ int);
3408 static int forkshell(struct job *, union node *, int);
3409 static int waitforjob(struct job *);
3410
3411 #if !JOBS
3412 enum { doing_jobctl = 0 };
3413 #define setjobctl(on) do {} while (0)
3414 #else
3415 static smallint doing_jobctl; //references:8
3416 static void setjobctl(int);
3417 #endif
3418
3419 /*
3420  * Ignore a signal.
3421  */
3422 static void
3423 ignoresig(int signo)
3424 {
3425         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3426         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3427                 /* No, need to do it */
3428                 signal(signo, SIG_IGN);
3429         }
3430         sigmode[signo - 1] = S_HARD_IGN;
3431 }
3432
3433 /*
3434  * Only one usage site - in setsignal()
3435  */
3436 static void
3437 signal_handler(int signo)
3438 {
3439         if (signo == SIGCHLD) {
3440                 got_sigchld = 1;
3441                 if (!trap[SIGCHLD])
3442                         return;
3443         }
3444
3445         gotsig[signo - 1] = 1;
3446         pending_sig = signo;
3447
3448         if (signo == SIGINT && !trap[SIGINT]) {
3449                 if (!suppress_int) {
3450                         pending_sig = 0;
3451                         raise_interrupt(); /* does not return */
3452                 }
3453                 pending_int = 1;
3454         }
3455 }
3456
3457 /*
3458  * Set the signal handler for the specified signal.  The routine figures
3459  * out what it should be set to.
3460  */
3461 static void
3462 setsignal(int signo)
3463 {
3464         char *t;
3465         char cur_act, new_act;
3466         struct sigaction act;
3467
3468         t = trap[signo];
3469         new_act = S_DFL;
3470         if (t != NULL) { /* trap for this sig is set */
3471                 new_act = S_CATCH;
3472                 if (t[0] == '\0') /* trap is "": ignore this sig */
3473                         new_act = S_IGN;
3474         }
3475
3476         if (rootshell && new_act == S_DFL) {
3477                 switch (signo) {
3478                 case SIGINT:
3479                         if (iflag || minusc || sflag == 0)
3480                                 new_act = S_CATCH;
3481                         break;
3482                 case SIGQUIT:
3483 #if DEBUG
3484                         if (debug)
3485                                 break;
3486 #endif
3487                         /* man bash:
3488                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3489                          * commands run by bash have signal handlers
3490                          * set to the values inherited by the shell
3491                          * from its parent". */
3492                         new_act = S_IGN;
3493                         break;
3494                 case SIGTERM:
3495                         if (iflag)
3496                                 new_act = S_IGN;
3497                         break;
3498 #if JOBS
3499                 case SIGTSTP:
3500                 case SIGTTOU:
3501                         if (mflag)
3502                                 new_act = S_IGN;
3503                         break;
3504 #endif
3505                 }
3506         }
3507 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3508 //whereas we have to restore it to what shell got on entry
3509 //from the parent. See comment above
3510
3511         if (signo == SIGCHLD)
3512                 new_act = S_CATCH;
3513
3514         t = &sigmode[signo - 1];
3515         cur_act = *t;
3516         if (cur_act == 0) {
3517                 /* current setting is not yet known */
3518                 if (sigaction(signo, NULL, &act)) {
3519                         /* pretend it worked; maybe we should give a warning,
3520                          * but other shells don't. We don't alter sigmode,
3521                          * so we retry every time.
3522                          * btw, in Linux it never fails. --vda */
3523                         return;
3524                 }
3525                 if (act.sa_handler == SIG_IGN) {
3526                         cur_act = S_HARD_IGN;
3527                         if (mflag
3528                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3529                         ) {
3530                                 cur_act = S_IGN;   /* don't hard ignore these */
3531                         }
3532                 }
3533         }
3534         if (cur_act == S_HARD_IGN || cur_act == new_act)
3535                 return;
3536
3537         act.sa_handler = SIG_DFL;
3538         switch (new_act) {
3539         case S_CATCH:
3540                 act.sa_handler = signal_handler;
3541                 break;
3542         case S_IGN:
3543                 act.sa_handler = SIG_IGN;
3544                 break;
3545         }
3546
3547         /* flags and mask matter only if !DFL and !IGN, but we do it
3548          * for all cases for more deterministic behavior:
3549          */
3550         act.sa_flags = 0;
3551         sigfillset(&act.sa_mask);
3552
3553         sigaction_set(signo, &act);
3554
3555         *t = new_act;
3556 }
3557
3558 /* mode flags for set_curjob */
3559 #define CUR_DELETE 2
3560 #define CUR_RUNNING 1
3561 #define CUR_STOPPED 0
3562
3563 #if JOBS
3564 /* pgrp of shell on invocation */
3565 static int initialpgrp; //references:2
3566 static int ttyfd = -1; //5
3567 #endif
3568 /* array of jobs */
3569 static struct job *jobtab; //5
3570 /* size of array */
3571 static unsigned njobs; //4
3572 /* current job */
3573 static struct job *curjob; //lots
3574 /* number of presumed living untracked jobs */
3575 static int jobless; //4
3576
3577 #if 0
3578 /* Bash has a feature: it restores termios after a successful wait for
3579  * a foreground job which had at least one stopped or sigkilled member.
3580  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3581  * properly restoring tty state. Should we do this too?
3582  * A reproducer: ^Z an interactive python:
3583  *
3584  * # python
3585  * Python 2.7.12 (...)
3586  * >>> ^Z
3587  *      { python leaves tty in -icanon -echo state. We do survive that... }
3588  *  [1]+  Stopped                    python
3589  *      { ...however, next program (python #2) does not survive it well: }
3590  * # python
3591  * Python 2.7.12 (...)
3592  * >>> Traceback (most recent call last):
3593  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3594  *   File "<stdin>", line 1, in <module>
3595  * NameError: name 'qwerty' is not defined
3596  *
3597  * The implementation below is modeled on bash code and seems to work.
3598  * However, I'm not sure we should do this. For one: what if I'd fg
3599  * the stopped python instead? It'll be confused by "restored" tty state.
3600  */
3601 static struct termios shell_tty_info;
3602 static void
3603 get_tty_state(void)
3604 {
3605         if (rootshell && ttyfd >= 0)
3606                 tcgetattr(ttyfd, &shell_tty_info);
3607 }
3608 static void
3609 set_tty_state(void)
3610 {
3611         /* if (rootshell) - caller ensures this */
3612         if (ttyfd >= 0)
3613                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3614 }
3615 static int
3616 job_signal_status(struct job *jp)
3617 {
3618         int status;
3619         unsigned i;
3620         struct procstat *ps = jp->ps;
3621         for (i = 0; i < jp->nprocs; i++) {
3622                 status = ps[i].ps_status;
3623                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3624                         return status;
3625         }
3626         return 0;
3627 }
3628 static void
3629 restore_tty_if_stopped_or_signaled(struct job *jp)
3630 {
3631 //TODO: check what happens if we come from waitforjob() in expbackq()
3632         if (rootshell) {
3633                 int s = job_signal_status(jp);
3634                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3635                         set_tty_state();
3636         }
3637 }
3638 #else
3639 # define get_tty_state() ((void)0)
3640 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3641 #endif
3642
3643 static void
3644 set_curjob(struct job *jp, unsigned mode)
3645 {
3646         struct job *jp1;
3647         struct job **jpp, **curp;
3648
3649         /* first remove from list */
3650         jpp = curp = &curjob;
3651         while (1) {
3652                 jp1 = *jpp;
3653                 if (jp1 == jp)
3654                         break;
3655                 jpp = &jp1->prev_job;
3656         }
3657         *jpp = jp1->prev_job;
3658
3659         /* Then re-insert in correct position */
3660         jpp = curp;
3661         switch (mode) {
3662         default:
3663 #if DEBUG
3664                 abort();
3665 #endif
3666         case CUR_DELETE:
3667                 /* job being deleted */
3668                 break;
3669         case CUR_RUNNING:
3670                 /* newly created job or backgrounded job,
3671                  * put after all stopped jobs.
3672                  */
3673                 while (1) {
3674                         jp1 = *jpp;
3675 #if JOBS
3676                         if (!jp1 || jp1->state != JOBSTOPPED)
3677 #endif
3678                                 break;
3679                         jpp = &jp1->prev_job;
3680                 }
3681                 /* FALLTHROUGH */
3682 #if JOBS
3683         case CUR_STOPPED:
3684 #endif
3685                 /* newly stopped job - becomes curjob */
3686                 jp->prev_job = *jpp;
3687                 *jpp = jp;
3688                 break;
3689         }
3690 }
3691
3692 #if JOBS || DEBUG
3693 static int
3694 jobno(const struct job *jp)
3695 {
3696         return jp - jobtab + 1;
3697 }
3698 #endif
3699
3700 /*
3701  * Convert a job name to a job structure.
3702  */
3703 #if !JOBS
3704 #define getjob(name, getctl) getjob(name)
3705 #endif
3706 static struct job *
3707 getjob(const char *name, int getctl)
3708 {
3709         struct job *jp;
3710         struct job *found;
3711         const char *err_msg = "%s: no such job";
3712         unsigned num;
3713         int c;
3714         const char *p;
3715         char *(*match)(const char *, const char *);
3716
3717         jp = curjob;
3718         p = name;
3719         if (!p)
3720                 goto currentjob;
3721
3722         if (*p != '%')
3723                 goto err;
3724
3725         c = *++p;
3726         if (!c)
3727                 goto currentjob;
3728
3729         if (!p[1]) {
3730                 if (c == '+' || c == '%') {
3731  currentjob:
3732                         err_msg = "No current job";
3733                         goto check;
3734                 }
3735                 if (c == '-') {
3736                         if (jp)
3737                                 jp = jp->prev_job;
3738                         err_msg = "No previous job";
3739  check:
3740                         if (!jp)
3741                                 goto err;
3742                         goto gotit;
3743                 }
3744         }
3745
3746         if (is_number(p)) {
3747                 num = atoi(p);
3748                 if (num > 0 && num <= njobs) {
3749                         jp = jobtab + num - 1;
3750                         if (jp->used)
3751                                 goto gotit;
3752                         goto err;
3753                 }
3754         }
3755
3756         match = prefix;
3757         if (*p == '?') {
3758                 match = strstr;
3759                 p++;
3760         }
3761
3762         found = NULL;
3763         while (jp) {
3764                 if (match(jp->ps[0].ps_cmd, p)) {
3765                         if (found)
3766                                 goto err;
3767                         found = jp;
3768                         err_msg = "%s: ambiguous";
3769                 }
3770                 jp = jp->prev_job;
3771         }
3772         if (!found)
3773                 goto err;
3774         jp = found;
3775
3776  gotit:
3777 #if JOBS
3778         err_msg = "job %s not created under job control";
3779         if (getctl && jp->jobctl == 0)
3780                 goto err;
3781 #endif
3782         return jp;
3783  err:
3784         ash_msg_and_raise_error(err_msg, name);
3785 }
3786
3787 /*
3788  * Mark a job structure as unused.
3789  */
3790 static void
3791 freejob(struct job *jp)
3792 {
3793         struct procstat *ps;
3794         int i;
3795
3796         INT_OFF;
3797         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3798                 if (ps->ps_cmd != nullstr)
3799                         free(ps->ps_cmd);
3800         }
3801         if (jp->ps != &jp->ps0)
3802                 free(jp->ps);
3803         jp->used = 0;
3804         set_curjob(jp, CUR_DELETE);
3805         INT_ON;
3806 }
3807
3808 #if JOBS
3809 static void
3810 xtcsetpgrp(int fd, pid_t pgrp)
3811 {
3812         if (tcsetpgrp(fd, pgrp))
3813                 ash_msg_and_raise_error("can't set tty process group (%m)");
3814 }
3815
3816 /*
3817  * Turn job control on and off.
3818  *
3819  * Note:  This code assumes that the third arg to ioctl is a character
3820  * pointer, which is true on Berkeley systems but not System V.  Since
3821  * System V doesn't have job control yet, this isn't a problem now.
3822  *
3823  * Called with interrupts off.
3824  */
3825 static void
3826 setjobctl(int on)
3827 {
3828         int fd;
3829         int pgrp;
3830
3831         if (on == doing_jobctl || rootshell == 0)
3832                 return;
3833         if (on) {
3834                 int ofd;
3835                 ofd = fd = open(_PATH_TTY, O_RDWR);
3836                 if (fd < 0) {
3837         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3838          * That sometimes helps to acquire controlling tty.
3839          * Obviously, a workaround for bugs when someone
3840          * failed to provide a controlling tty to bash! :) */
3841                         fd = 2;
3842                         while (!isatty(fd))
3843                                 if (--fd < 0)
3844                                         goto out;
3845                 }
3846                 /* fd is a tty at this point */
3847                 fd = fcntl(fd, F_DUPFD, 10);
3848                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3849                         close(ofd);
3850                 if (fd < 0)
3851                         goto out; /* F_DUPFD failed */
3852                 close_on_exec_on(fd);
3853                 while (1) { /* while we are in the background */
3854                         pgrp = tcgetpgrp(fd);
3855                         if (pgrp < 0) {
3856  out:
3857                                 ash_msg("can't access tty; job control turned off");
3858                                 mflag = on = 0;
3859                                 goto close;
3860                         }
3861                         if (pgrp == getpgrp())
3862                                 break;
3863                         killpg(0, SIGTTIN);
3864                 }
3865                 initialpgrp = pgrp;
3866
3867                 setsignal(SIGTSTP);
3868                 setsignal(SIGTTOU);
3869                 setsignal(SIGTTIN);
3870                 pgrp = rootpid;
3871                 setpgid(0, pgrp);
3872                 xtcsetpgrp(fd, pgrp);
3873         } else {
3874                 /* turning job control off */
3875                 fd = ttyfd;
3876                 pgrp = initialpgrp;
3877                 /* was xtcsetpgrp, but this can make exiting ash
3878                  * loop forever if pty is already deleted */
3879                 tcsetpgrp(fd, pgrp);
3880                 setpgid(0, pgrp);
3881                 setsignal(SIGTSTP);
3882                 setsignal(SIGTTOU);
3883                 setsignal(SIGTTIN);
3884  close:
3885                 if (fd >= 0)
3886                         close(fd);
3887                 fd = -1;
3888         }
3889         ttyfd = fd;
3890         doing_jobctl = on;
3891 }
3892
3893 static int FAST_FUNC
3894 killcmd(int argc, char **argv)
3895 {
3896         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3897                 int i = 1;
3898                 do {
3899                         if (argv[i][0] == '%') {
3900                                 /*
3901                                  * "kill %N" - job kill
3902                                  * Converting to pgrp / pid kill
3903                                  */
3904                                 struct job *jp;
3905                                 char *dst;
3906                                 int j, n;
3907
3908                                 jp = getjob(argv[i], 0);
3909                                 /*
3910                                  * In jobs started under job control, we signal
3911                                  * entire process group by kill -PGRP_ID.
3912                                  * This happens, f.e., in interactive shell.
3913                                  *
3914                                  * Otherwise, we signal each child via
3915                                  * kill PID1 PID2 PID3.
3916                                  * Testcases:
3917                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3918                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3919                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3920                                  */
3921                                 n = jp->nprocs; /* can't be 0 (I hope) */
3922                                 if (jp->jobctl)
3923                                         n = 1;
3924                                 dst = alloca(n * sizeof(int)*4);
3925                                 argv[i] = dst;
3926                                 for (j = 0; j < n; j++) {
3927                                         struct procstat *ps = &jp->ps[j];
3928                                         /* Skip non-running and not-stopped members
3929                                          * (i.e. dead members) of the job
3930                                          */
3931                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3932                                                 continue;
3933                                         /*
3934                                          * kill_main has matching code to expect
3935                                          * leading space. Needed to not confuse
3936                                          * negative pids with "kill -SIGNAL_NO" syntax
3937                                          */
3938                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3939                                 }
3940                                 *dst = '\0';
3941                         }
3942                 } while (argv[++i]);
3943         }
3944         return kill_main(argc, argv);
3945 }
3946
3947 static void
3948 showpipe(struct job *jp /*, FILE *out*/)
3949 {
3950         struct procstat *ps;
3951         struct procstat *psend;
3952
3953         psend = jp->ps + jp->nprocs;
3954         for (ps = jp->ps + 1; ps < psend; ps++)
3955                 printf(" | %s", ps->ps_cmd);
3956         newline_and_flush(stdout);
3957         flush_stdout_stderr();
3958 }
3959
3960
3961 static int
3962 restartjob(struct job *jp, int mode)
3963 {
3964         struct procstat *ps;
3965         int i;
3966         int status;
3967         pid_t pgid;
3968
3969         INT_OFF;
3970         if (jp->state == JOBDONE)
3971                 goto out;
3972         jp->state = JOBRUNNING;
3973         pgid = jp->ps[0].ps_pid;
3974         if (mode == FORK_FG) {
3975                 get_tty_state();
3976                 xtcsetpgrp(ttyfd, pgid);
3977         }
3978         killpg(pgid, SIGCONT);
3979         ps = jp->ps;
3980         i = jp->nprocs;
3981         do {
3982                 if (WIFSTOPPED(ps->ps_status)) {
3983                         ps->ps_status = -1;
3984                 }
3985                 ps++;
3986         } while (--i);
3987  out:
3988         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3989         INT_ON;
3990         return status;
3991 }
3992
3993 static int FAST_FUNC
3994 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3995 {
3996         struct job *jp;
3997         int mode;
3998         int retval;
3999
4000         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4001         nextopt(nullstr);
4002         argv = argptr;
4003         do {
4004                 jp = getjob(*argv, 1);
4005                 if (mode == FORK_BG) {
4006                         set_curjob(jp, CUR_RUNNING);
4007                         printf("[%d] ", jobno(jp));
4008                 }
4009                 out1str(jp->ps[0].ps_cmd);
4010                 showpipe(jp /*, stdout*/);
4011                 retval = restartjob(jp, mode);
4012         } while (*argv && *++argv);
4013         return retval;
4014 }
4015 #endif
4016
4017 static int
4018 sprint_status48(char *s, int status, int sigonly)
4019 {
4020         int col;
4021         int st;
4022
4023         col = 0;
4024         if (!WIFEXITED(status)) {
4025 #if JOBS
4026                 if (WIFSTOPPED(status))
4027                         st = WSTOPSIG(status);
4028                 else
4029 #endif
4030                         st = WTERMSIG(status);
4031                 if (sigonly) {
4032                         if (st == SIGINT || st == SIGPIPE)
4033                                 goto out;
4034 #if JOBS
4035                         if (WIFSTOPPED(status))
4036                                 goto out;
4037 #endif
4038                 }
4039                 st &= 0x7f;
4040 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4041                 col = fmtstr(s, 32, strsignal(st));
4042                 if (WCOREDUMP(status)) {
4043                         strcpy(s + col, " (core dumped)");
4044                         col += sizeof(" (core dumped)")-1;
4045                 }
4046         } else if (!sigonly) {
4047                 st = WEXITSTATUS(status);
4048                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4049         }
4050  out:
4051         return col;
4052 }
4053
4054 static int
4055 wait_block_or_sig(int *status)
4056 {
4057         int pid;
4058
4059         do {
4060                 sigset_t mask;
4061
4062                 /* Poll all children for changes in their state */
4063                 got_sigchld = 0;
4064                 /* if job control is active, accept stopped processes too */
4065                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4066                 if (pid != 0)
4067                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4068
4069                 /* Children exist, but none are ready. Sleep until interesting signal */
4070 #if 1
4071                 sigfillset(&mask);
4072                 sigprocmask(SIG_SETMASK, &mask, &mask);
4073                 while (!got_sigchld && !pending_sig)
4074                         sigsuspend(&mask);
4075                 sigprocmask(SIG_SETMASK, &mask, NULL);
4076 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4077                 while (!got_sigchld && !pending_sig)
4078                         pause();
4079 #endif
4080
4081                 /* If it was SIGCHLD, poll children again */
4082         } while (got_sigchld);
4083
4084         return pid;
4085 }
4086
4087 #define DOWAIT_NONBLOCK 0
4088 #define DOWAIT_BLOCK    1
4089 #define DOWAIT_BLOCK_OR_SIG 2
4090
4091 static int
4092 dowait(int block, struct job *job)
4093 {
4094         int pid;
4095         int status;
4096         struct job *jp;
4097         struct job *thisjob = NULL;
4098
4099         TRACE(("dowait(0x%x) called\n", block));
4100
4101         /* It's wrong to call waitpid() outside of INT_OFF region:
4102          * signal can arrive just after syscall return and handler can
4103          * longjmp away, losing stop/exit notification processing.
4104          * Thus, for "jobs" builtin, and for waiting for a fg job,
4105          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4106          *
4107          * However, for "wait" builtin it is wrong to simply call waitpid()
4108          * in INT_OFF region: "wait" needs to wait for any running job
4109          * to change state, but should exit on any trap too.
4110          * In INT_OFF region, a signal just before syscall entry can set
4111          * pending_sig variables, but we can't check them, and we would
4112          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4113          *
4114          * Because of this, we run inside INT_OFF, but use a special routine
4115          * which combines waitpid() and sigsuspend().
4116          * This is the reason why we need to have a handler for SIGCHLD:
4117          * SIG_DFL handler does not wake sigsuspend().
4118          */
4119         INT_OFF;
4120         if (block == DOWAIT_BLOCK_OR_SIG) {
4121                 pid = wait_block_or_sig(&status);
4122         } else {
4123                 int wait_flags = 0;
4124                 if (block == DOWAIT_NONBLOCK)
4125                         wait_flags = WNOHANG;
4126                 /* if job control is active, accept stopped processes too */
4127                 if (doing_jobctl)
4128                         wait_flags |= WUNTRACED;
4129                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4130                 pid = waitpid(-1, &status, wait_flags);
4131         }
4132         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4133                                 pid, status, errno, strerror(errno)));
4134         if (pid <= 0)
4135                 goto out;
4136
4137         thisjob = NULL;
4138         for (jp = curjob; jp; jp = jp->prev_job) {
4139                 int jobstate;
4140                 struct procstat *ps;
4141                 struct procstat *psend;
4142                 if (jp->state == JOBDONE)
4143                         continue;
4144                 jobstate = JOBDONE;
4145                 ps = jp->ps;
4146                 psend = ps + jp->nprocs;
4147                 do {
4148                         if (ps->ps_pid == pid) {
4149                                 TRACE(("Job %d: changing status of proc %d "
4150                                         "from 0x%x to 0x%x\n",
4151                                         jobno(jp), pid, ps->ps_status, status));
4152                                 ps->ps_status = status;
4153                                 thisjob = jp;
4154                         }
4155                         if (ps->ps_status == -1)
4156                                 jobstate = JOBRUNNING;
4157 #if JOBS
4158                         if (jobstate == JOBRUNNING)
4159                                 continue;
4160                         if (WIFSTOPPED(ps->ps_status)) {
4161                                 jp->stopstatus = ps->ps_status;
4162                                 jobstate = JOBSTOPPED;
4163                         }
4164 #endif
4165                 } while (++ps < psend);
4166                 if (!thisjob)
4167                         continue;
4168
4169                 /* Found the job where one of its processes changed its state.
4170                  * Is there at least one live and running process in this job? */
4171                 if (jobstate != JOBRUNNING) {
4172                         /* No. All live processes in the job are stopped
4173                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4174                          */
4175                         thisjob->changed = 1;
4176                         if (thisjob->state != jobstate) {
4177                                 TRACE(("Job %d: changing state from %d to %d\n",
4178                                         jobno(thisjob), thisjob->state, jobstate));
4179                                 thisjob->state = jobstate;
4180 #if JOBS
4181                                 if (jobstate == JOBSTOPPED)
4182                                         set_curjob(thisjob, CUR_STOPPED);
4183 #endif
4184                         }
4185                 }
4186                 goto out;
4187         }
4188         /* The process wasn't found in job list */
4189 #if JOBS
4190         if (!WIFSTOPPED(status))
4191                 jobless--;
4192 #endif
4193  out:
4194         INT_ON;
4195
4196         if (thisjob && thisjob == job) {
4197                 char s[48 + 1];
4198                 int len;
4199
4200                 len = sprint_status48(s, status, 1);
4201                 if (len) {
4202                         s[len] = '\n';
4203                         s[len + 1] = '\0';
4204                         out2str(s);
4205                 }
4206         }
4207         return pid;
4208 }
4209
4210 #if JOBS
4211 static void
4212 showjob(struct job *jp, int mode)
4213 {
4214         struct procstat *ps;
4215         struct procstat *psend;
4216         int col;
4217         int indent_col;
4218         char s[16 + 16 + 48];
4219         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4220
4221         ps = jp->ps;
4222
4223         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4224                 /* just output process (group) id of pipeline */
4225                 fprintf(out, "%d\n", ps->ps_pid);
4226                 return;
4227         }
4228
4229         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4230         indent_col = col;
4231
4232         if (jp == curjob)
4233                 s[col - 3] = '+';
4234         else if (curjob && jp == curjob->prev_job)
4235                 s[col - 3] = '-';
4236
4237         if (mode & SHOW_PIDS)
4238                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4239
4240         psend = ps + jp->nprocs;
4241
4242         if (jp->state == JOBRUNNING) {
4243                 strcpy(s + col, "Running");
4244                 col += sizeof("Running") - 1;
4245         } else {
4246                 int status = psend[-1].ps_status;
4247                 if (jp->state == JOBSTOPPED)
4248                         status = jp->stopstatus;
4249                 col += sprint_status48(s + col, status, 0);
4250         }
4251         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4252
4253         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4254          * or prints several "PID             | <cmdN>" lines,
4255          * depending on SHOW_PIDS bit.
4256          * We do not print status of individual processes
4257          * between PID and <cmdN>. bash does it, but not very well:
4258          * first line shows overall job status, not process status,
4259          * making it impossible to know 1st process status.
4260          */
4261         goto start;
4262         do {
4263                 /* for each process */
4264                 s[0] = '\0';
4265                 col = 33;
4266                 if (mode & SHOW_PIDS)
4267                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4268  start:
4269                 fprintf(out, "%s%*c%s%s",
4270                                 s,
4271                                 33 - col >= 0 ? 33 - col : 0, ' ',
4272                                 ps == jp->ps ? "" : "| ",
4273                                 ps->ps_cmd
4274                 );
4275         } while (++ps != psend);
4276         newline_and_flush(out);
4277
4278         jp->changed = 0;
4279
4280         if (jp->state == JOBDONE) {
4281                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4282                 freejob(jp);
4283         }
4284 }
4285
4286 /*
4287  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4288  * statuses have changed since the last call to showjobs.
4289  */
4290 static void
4291 showjobs(int mode)
4292 {
4293         struct job *jp;
4294
4295         TRACE(("showjobs(0x%x) called\n", mode));
4296
4297         /* Handle all finished jobs */
4298         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4299                 continue;
4300
4301         for (jp = curjob; jp; jp = jp->prev_job) {
4302                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4303                         showjob(jp, mode);
4304                 }
4305         }
4306 }
4307
4308 static int FAST_FUNC
4309 jobscmd(int argc UNUSED_PARAM, char **argv)
4310 {
4311         int mode, m;
4312
4313         mode = 0;
4314         while ((m = nextopt("lp")) != '\0') {
4315                 if (m == 'l')
4316                         mode |= SHOW_PIDS;
4317                 else
4318                         mode |= SHOW_ONLY_PGID;
4319         }
4320
4321         argv = argptr;
4322         if (*argv) {
4323                 do
4324                         showjob(getjob(*argv, 0), mode);
4325                 while (*++argv);
4326         } else {
4327                 showjobs(mode);
4328         }
4329
4330         return 0;
4331 }
4332 #endif /* JOBS */
4333
4334 /* Called only on finished or stopped jobs (no members are running) */
4335 static int
4336 getstatus(struct job *job)
4337 {
4338         int status;
4339         int retval;
4340         struct procstat *ps;
4341
4342         /* Fetch last member's status */
4343         ps = job->ps + job->nprocs - 1;
4344         status = ps->ps_status;
4345         if (pipefail) {
4346                 /* "set -o pipefail" mode: use last _nonzero_ status */
4347                 while (status == 0 && --ps >= job->ps)
4348                         status = ps->ps_status;
4349         }
4350
4351         retval = WEXITSTATUS(status);
4352         if (!WIFEXITED(status)) {
4353 #if JOBS
4354                 retval = WSTOPSIG(status);
4355                 if (!WIFSTOPPED(status))
4356 #endif
4357                 {
4358                         /* XXX: limits number of signals */
4359                         retval = WTERMSIG(status);
4360 #if JOBS
4361                         if (retval == SIGINT)
4362                                 job->sigint = 1;
4363 #endif
4364                 }
4365                 retval += 128;
4366         }
4367         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4368                 jobno(job), job->nprocs, status, retval));
4369         return retval;
4370 }
4371
4372 static int FAST_FUNC
4373 waitcmd(int argc UNUSED_PARAM, char **argv)
4374 {
4375         struct job *job;
4376         int retval;
4377         struct job *jp;
4378
4379         nextopt(nullstr);
4380         retval = 0;
4381
4382         argv = argptr;
4383         if (!*argv) {
4384                 /* wait for all jobs */
4385                 for (;;) {
4386                         jp = curjob;
4387                         while (1) {
4388                                 if (!jp) /* no running procs */
4389                                         goto ret;
4390                                 if (jp->state == JOBRUNNING)
4391                                         break;
4392                                 jp->waited = 1;
4393                                 jp = jp->prev_job;
4394                         }
4395         /* man bash:
4396          * "When bash is waiting for an asynchronous command via
4397          * the wait builtin, the reception of a signal for which a trap
4398          * has been set will cause the wait builtin to return immediately
4399          * with an exit status greater than 128, immediately after which
4400          * the trap is executed."
4401          */
4402                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4403         /* if child sends us a signal *and immediately exits*,
4404          * dowait() returns pid > 0. Check this case,
4405          * not "if (dowait() < 0)"!
4406          */
4407                         if (pending_sig)
4408                                 goto sigout;
4409                 }
4410         }
4411
4412         retval = 127;
4413         do {
4414                 if (**argv != '%') {
4415                         pid_t pid = number(*argv);
4416                         job = curjob;
4417                         while (1) {
4418                                 if (!job)
4419                                         goto repeat;
4420                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4421                                         break;
4422                                 job = job->prev_job;
4423                         }
4424                 } else {
4425                         job = getjob(*argv, 0);
4426                 }
4427                 /* loop until process terminated or stopped */
4428                 while (job->state == JOBRUNNING) {
4429                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4430                         if (pending_sig)
4431                                 goto sigout;
4432                 }
4433                 job->waited = 1;
4434                 retval = getstatus(job);
4435  repeat: ;
4436         } while (*++argv);
4437
4438  ret:
4439         return retval;
4440  sigout:
4441         retval = 128 + pending_sig;
4442         return retval;
4443 }
4444
4445 static struct job *
4446 growjobtab(void)
4447 {
4448         size_t len;
4449         ptrdiff_t offset;
4450         struct job *jp, *jq;
4451
4452         len = njobs * sizeof(*jp);
4453         jq = jobtab;
4454         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4455
4456         offset = (char *)jp - (char *)jq;
4457         if (offset) {
4458                 /* Relocate pointers */
4459                 size_t l = len;
4460
4461                 jq = (struct job *)((char *)jq + l);
4462                 while (l) {
4463                         l -= sizeof(*jp);
4464                         jq--;
4465 #define joff(p) ((struct job *)((char *)(p) + l))
4466 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4467                         if (joff(jp)->ps == &jq->ps0)
4468                                 jmove(joff(jp)->ps);
4469                         if (joff(jp)->prev_job)
4470                                 jmove(joff(jp)->prev_job);
4471                 }
4472                 if (curjob)
4473                         jmove(curjob);
4474 #undef joff
4475 #undef jmove
4476         }
4477
4478         njobs += 4;
4479         jobtab = jp;
4480         jp = (struct job *)((char *)jp + len);
4481         jq = jp + 3;
4482         do {
4483                 jq->used = 0;
4484         } while (--jq >= jp);
4485         return jp;
4486 }
4487
4488 /*
4489  * Return a new job structure.
4490  * Called with interrupts off.
4491  */
4492 static struct job *
4493 makejob(/*union node *node,*/ int nprocs)
4494 {
4495         int i;
4496         struct job *jp;
4497
4498         for (i = njobs, jp = jobtab; ; jp++) {
4499                 if (--i < 0) {
4500                         jp = growjobtab();
4501                         break;
4502                 }
4503                 if (jp->used == 0)
4504                         break;
4505                 if (jp->state != JOBDONE || !jp->waited)
4506                         continue;
4507 #if JOBS
4508                 if (doing_jobctl)
4509                         continue;
4510 #endif
4511                 freejob(jp);
4512                 break;
4513         }
4514         memset(jp, 0, sizeof(*jp));
4515 #if JOBS
4516         /* jp->jobctl is a bitfield.
4517          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4518         if (doing_jobctl)
4519                 jp->jobctl = 1;
4520 #endif
4521         jp->prev_job = curjob;
4522         curjob = jp;
4523         jp->used = 1;
4524         jp->ps = &jp->ps0;
4525         if (nprocs > 1) {
4526                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4527         }
4528         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4529                                 jobno(jp)));
4530         return jp;
4531 }
4532
4533 #if JOBS
4534 /*
4535  * Return a string identifying a command (to be printed by the
4536  * jobs command).
4537  */
4538 static char *cmdnextc;
4539
4540 static void
4541 cmdputs(const char *s)
4542 {
4543         static const char vstype[VSTYPE + 1][3] = {
4544                 "", "}", "-", "+", "?", "=",
4545                 "%", "%%", "#", "##"
4546                 IF_BASH_SUBSTR(, ":")
4547                 IF_BASH_PATTERN_SUBST(, "/", "//")
4548         };
4549
4550         const char *p, *str;
4551         char cc[2];
4552         char *nextc;
4553         unsigned char c;
4554         unsigned char subtype = 0;
4555         int quoted = 0;
4556
4557         cc[1] = '\0';
4558         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4559         p = s;
4560         while ((c = *p++) != '\0') {
4561                 str = NULL;
4562                 switch (c) {
4563                 case CTLESC:
4564                         c = *p++;
4565                         break;
4566                 case CTLVAR:
4567                         subtype = *p++;
4568                         if ((subtype & VSTYPE) == VSLENGTH)
4569                                 str = "${#";
4570                         else
4571                                 str = "${";
4572                         goto dostr;
4573                 case CTLENDVAR:
4574                         str = "\"}" + !(quoted & 1);
4575                         quoted >>= 1;
4576                         subtype = 0;
4577                         goto dostr;
4578                 case CTLBACKQ:
4579                         str = "$(...)";
4580                         goto dostr;
4581 #if ENABLE_FEATURE_SH_MATH
4582                 case CTLARI:
4583                         str = "$((";
4584                         goto dostr;
4585                 case CTLENDARI:
4586                         str = "))";
4587                         goto dostr;
4588 #endif
4589                 case CTLQUOTEMARK:
4590                         quoted ^= 1;
4591                         c = '"';
4592                         break;
4593                 case '=':
4594                         if (subtype == 0)
4595                                 break;
4596                         if ((subtype & VSTYPE) != VSNORMAL)
4597                                 quoted <<= 1;
4598                         str = vstype[subtype & VSTYPE];
4599                         if (subtype & VSNUL)
4600                                 c = ':';
4601                         else
4602                                 goto checkstr;
4603                         break;
4604                 case '\'':
4605                 case '\\':
4606                 case '"':
4607                 case '$':
4608                         /* These can only happen inside quotes */
4609                         cc[0] = c;
4610                         str = cc;
4611                         c = '\\';
4612                         break;
4613                 default:
4614                         break;
4615                 }
4616                 USTPUTC(c, nextc);
4617  checkstr:
4618                 if (!str)
4619                         continue;
4620  dostr:
4621                 while ((c = *str++) != '\0') {
4622                         USTPUTC(c, nextc);
4623                 }
4624         } /* while *p++ not NUL */
4625
4626         if (quoted & 1) {
4627                 USTPUTC('"', nextc);
4628         }
4629         *nextc = 0;
4630         cmdnextc = nextc;
4631 }
4632
4633 /* cmdtxt() and cmdlist() call each other */
4634 static void cmdtxt(union node *n);
4635
4636 static void
4637 cmdlist(union node *np, int sep)
4638 {
4639         for (; np; np = np->narg.next) {
4640                 if (!sep)
4641                         cmdputs(" ");
4642                 cmdtxt(np);
4643                 if (sep && np->narg.next)
4644                         cmdputs(" ");
4645         }
4646 }
4647
4648 static void
4649 cmdtxt(union node *n)
4650 {
4651         union node *np;
4652         struct nodelist *lp;
4653         const char *p;
4654
4655         if (!n)
4656                 return;
4657         switch (n->type) {
4658         default:
4659 #if DEBUG
4660                 abort();
4661 #endif
4662         case NPIPE:
4663                 lp = n->npipe.cmdlist;
4664                 for (;;) {
4665                         cmdtxt(lp->n);
4666                         lp = lp->next;
4667                         if (!lp)
4668                                 break;
4669                         cmdputs(" | ");
4670                 }
4671                 break;
4672         case NSEMI:
4673                 p = "; ";
4674                 goto binop;
4675         case NAND:
4676                 p = " && ";
4677                 goto binop;
4678         case NOR:
4679                 p = " || ";
4680  binop:
4681                 cmdtxt(n->nbinary.ch1);
4682                 cmdputs(p);
4683                 n = n->nbinary.ch2;
4684                 goto donode;
4685         case NREDIR:
4686         case NBACKGND:
4687                 n = n->nredir.n;
4688                 goto donode;
4689         case NNOT:
4690                 cmdputs("!");
4691                 n = n->nnot.com;
4692  donode:
4693                 cmdtxt(n);
4694                 break;
4695         case NIF:
4696                 cmdputs("if ");
4697                 cmdtxt(n->nif.test);
4698                 cmdputs("; then ");
4699                 if (n->nif.elsepart) {
4700                         cmdtxt(n->nif.ifpart);
4701                         cmdputs("; else ");
4702                         n = n->nif.elsepart;
4703                 } else {
4704                         n = n->nif.ifpart;
4705                 }
4706                 p = "; fi";
4707                 goto dotail;
4708         case NSUBSHELL:
4709                 cmdputs("(");
4710                 n = n->nredir.n;
4711                 p = ")";
4712                 goto dotail;
4713         case NWHILE:
4714                 p = "while ";
4715                 goto until;
4716         case NUNTIL:
4717                 p = "until ";
4718  until:
4719                 cmdputs(p);
4720                 cmdtxt(n->nbinary.ch1);
4721                 n = n->nbinary.ch2;
4722                 p = "; done";
4723  dodo:
4724                 cmdputs("; do ");
4725  dotail:
4726                 cmdtxt(n);
4727                 goto dotail2;
4728         case NFOR:
4729                 cmdputs("for ");
4730                 cmdputs(n->nfor.var);
4731                 cmdputs(" in ");
4732                 cmdlist(n->nfor.args, 1);
4733                 n = n->nfor.body;
4734                 p = "; done";
4735                 goto dodo;
4736         case NDEFUN:
4737                 cmdputs(n->narg.text);
4738                 p = "() { ... }";
4739                 goto dotail2;
4740         case NCMD:
4741                 cmdlist(n->ncmd.args, 1);
4742                 cmdlist(n->ncmd.redirect, 0);
4743                 break;
4744         case NARG:
4745                 p = n->narg.text;
4746  dotail2:
4747                 cmdputs(p);
4748                 break;
4749         case NHERE:
4750         case NXHERE:
4751                 p = "<<...";
4752                 goto dotail2;
4753         case NCASE:
4754                 cmdputs("case ");
4755                 cmdputs(n->ncase.expr->narg.text);
4756                 cmdputs(" in ");
4757                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4758                         cmdtxt(np->nclist.pattern);
4759                         cmdputs(") ");
4760                         cmdtxt(np->nclist.body);
4761                         cmdputs(";; ");
4762                 }
4763                 p = "esac";
4764                 goto dotail2;
4765         case NTO:
4766                 p = ">";
4767                 goto redir;
4768         case NCLOBBER:
4769                 p = ">|";
4770                 goto redir;
4771         case NAPPEND:
4772                 p = ">>";
4773                 goto redir;
4774 #if BASH_REDIR_OUTPUT
4775         case NTO2:
4776 #endif
4777         case NTOFD:
4778                 p = ">&";
4779                 goto redir;
4780         case NFROM:
4781                 p = "<";
4782                 goto redir;
4783         case NFROMFD:
4784                 p = "<&";
4785                 goto redir;
4786         case NFROMTO:
4787                 p = "<>";
4788  redir:
4789                 cmdputs(utoa(n->nfile.fd));
4790                 cmdputs(p);
4791                 if (n->type == NTOFD || n->type == NFROMFD) {
4792                         cmdputs(utoa(n->ndup.dupfd));
4793                         break;
4794                 }
4795                 n = n->nfile.fname;
4796                 goto donode;
4797         }
4798 }
4799
4800 static char *
4801 commandtext(union node *n)
4802 {
4803         char *name;
4804
4805         STARTSTACKSTR(cmdnextc);
4806         cmdtxt(n);
4807         name = stackblock();
4808         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4809         return ckstrdup(name);
4810 }
4811 #endif /* JOBS */
4812
4813 /*
4814  * Fork off a subshell.  If we are doing job control, give the subshell its
4815  * own process group.  Jp is a job structure that the job is to be added to.
4816  * N is the command that will be evaluated by the child.  Both jp and n may
4817  * be NULL.  The mode parameter can be one of the following:
4818  *      FORK_FG - Fork off a foreground process.
4819  *      FORK_BG - Fork off a background process.
4820  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4821  *                   process group even if job control is on.
4822  *
4823  * When job control is turned off, background processes have their standard
4824  * input redirected to /dev/null (except for the second and later processes
4825  * in a pipeline).
4826  *
4827  * Called with interrupts off.
4828  */
4829 /*
4830  * Clear traps on a fork.
4831  */
4832 static void
4833 clear_traps(void)
4834 {
4835         char **tp;
4836
4837         INT_OFF;
4838         for (tp = trap; tp < &trap[NSIG]; tp++) {
4839                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4840                         if (trap_ptr == trap)
4841                                 free(*tp);
4842                         /* else: it "belongs" to trap_ptr vector, don't free */
4843                         *tp = NULL;
4844                         if ((tp - trap) != 0)
4845                                 setsignal(tp - trap);
4846                 }
4847         }
4848         may_have_traps = 0;
4849         INT_ON;
4850 }
4851
4852 /* Lives far away from here, needed for forkchild */
4853 static void closescript(void);
4854
4855 /* Called after fork(), in child */
4856 /* jp and n are NULL when called by openhere() for heredoc support */
4857 static NOINLINE void
4858 forkchild(struct job *jp, union node *n, int mode)
4859 {
4860         int oldlvl;
4861
4862         TRACE(("Child shell %d\n", getpid()));
4863         oldlvl = shlvl;
4864         shlvl++;
4865
4866         /* man bash: "Non-builtin commands run by bash have signal handlers
4867          * set to the values inherited by the shell from its parent".
4868          * Do we do it correctly? */
4869
4870         closescript();
4871
4872         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4873          && n && n->type == NCMD        /* is it single cmd? */
4874         /* && n->ncmd.args->type == NARG - always true? */
4875          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4876          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4877         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4878         ) {
4879                 TRACE(("Trap hack\n"));
4880                 /* Awful hack for `trap` or $(trap).
4881                  *
4882                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4883                  * contains an example where "trap" is executed in a subshell:
4884                  *
4885                  * save_traps=$(trap)
4886                  * ...
4887                  * eval "$save_traps"
4888                  *
4889                  * Standard does not say that "trap" in subshell shall print
4890                  * parent shell's traps. It only says that its output
4891                  * must have suitable form, but then, in the above example
4892                  * (which is not supposed to be normative), it implies that.
4893                  *
4894                  * bash (and probably other shell) does implement it
4895                  * (traps are reset to defaults, but "trap" still shows them),
4896                  * but as a result, "trap" logic is hopelessly messed up:
4897                  *
4898                  * # trap
4899                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4900                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4901                  * # true | trap   <--- trap is in subshell - no output (ditto)
4902                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4903                  * trap -- 'echo Ho' SIGWINCH
4904                  * # echo `(trap)`         <--- in subshell in subshell - output
4905                  * trap -- 'echo Ho' SIGWINCH
4906                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4907                  * trap -- 'echo Ho' SIGWINCH
4908                  *
4909                  * The rules when to forget and when to not forget traps
4910                  * get really complex and nonsensical.
4911                  *
4912                  * Our solution: ONLY bare $(trap) or `trap` is special.
4913                  */
4914                 /* Save trap handler strings for trap builtin to print */
4915                 trap_ptr = xmemdup(trap, sizeof(trap));
4916                 /* Fall through into clearing traps */
4917         }
4918         clear_traps();
4919 #if JOBS
4920         /* do job control only in root shell */
4921         doing_jobctl = 0;
4922         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4923                 pid_t pgrp;
4924
4925                 if (jp->nprocs == 0)
4926                         pgrp = getpid();
4927                 else
4928                         pgrp = jp->ps[0].ps_pid;
4929                 /* this can fail because we are doing it in the parent also */
4930                 setpgid(0, pgrp);
4931                 if (mode == FORK_FG)
4932                         xtcsetpgrp(ttyfd, pgrp);
4933                 setsignal(SIGTSTP);
4934                 setsignal(SIGTTOU);
4935         } else
4936 #endif
4937         if (mode == FORK_BG) {
4938                 /* man bash: "When job control is not in effect,
4939                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4940                 ignoresig(SIGINT);
4941                 ignoresig(SIGQUIT);
4942                 if (jp->nprocs == 0) {
4943                         close(0);
4944                         if (open(bb_dev_null, O_RDONLY) != 0)
4945                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4946                 }
4947         }
4948         if (oldlvl == 0) {
4949                 if (iflag) { /* why if iflag only? */
4950                         setsignal(SIGINT);
4951                         setsignal(SIGTERM);
4952                 }
4953                 /* man bash:
4954                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4955                  * commands run by bash have signal handlers
4956                  * set to the values inherited by the shell
4957                  * from its parent".
4958                  * Take care of the second rule: */
4959                 setsignal(SIGQUIT);
4960         }
4961 #if JOBS
4962         if (n && n->type == NCMD
4963          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4964         ) {
4965                 TRACE(("Job hack\n"));
4966                 /* "jobs": we do not want to clear job list for it,
4967                  * instead we remove only _its_ own_ job from job list.
4968                  * This makes "jobs .... | cat" more useful.
4969                  */
4970                 freejob(curjob);
4971                 return;
4972         }
4973 #endif
4974         for (jp = curjob; jp; jp = jp->prev_job)
4975                 freejob(jp);
4976         jobless = 0;
4977 }
4978
4979 /* Called after fork(), in parent */
4980 #if !JOBS
4981 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4982 #endif
4983 static void
4984 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4985 {
4986         TRACE(("In parent shell: child = %d\n", pid));
4987         if (!jp) {
4988                 /* jp is NULL when called by openhere() for heredoc support */
4989                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4990                         continue;
4991                 jobless++;
4992                 return;
4993         }
4994 #if JOBS
4995         if (mode != FORK_NOJOB && jp->jobctl) {
4996                 int pgrp;
4997
4998                 if (jp->nprocs == 0)
4999                         pgrp = pid;
5000                 else
5001                         pgrp = jp->ps[0].ps_pid;
5002                 /* This can fail because we are doing it in the child also */
5003                 setpgid(pid, pgrp);
5004         }
5005 #endif
5006         if (mode == FORK_BG) {
5007                 backgndpid = pid;               /* set $! */
5008                 set_curjob(jp, CUR_RUNNING);
5009         }
5010         if (jp) {
5011                 struct procstat *ps = &jp->ps[jp->nprocs++];
5012                 ps->ps_pid = pid;
5013                 ps->ps_status = -1;
5014                 ps->ps_cmd = nullstr;
5015 #if JOBS
5016                 if (doing_jobctl && n)
5017                         ps->ps_cmd = commandtext(n);
5018 #endif
5019         }
5020 }
5021
5022 /* jp and n are NULL when called by openhere() for heredoc support */
5023 static int
5024 forkshell(struct job *jp, union node *n, int mode)
5025 {
5026         int pid;
5027
5028         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5029         pid = fork();
5030         if (pid < 0) {
5031                 TRACE(("Fork failed, errno=%d", errno));
5032                 if (jp)
5033                         freejob(jp);
5034                 ash_msg_and_raise_error("can't fork");
5035         }
5036         if (pid == 0) {
5037                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5038                 forkchild(jp, n, mode);
5039         } else {
5040                 forkparent(jp, n, mode, pid);
5041         }
5042         return pid;
5043 }
5044
5045 /*
5046  * Wait for job to finish.
5047  *
5048  * Under job control we have the problem that while a child process
5049  * is running interrupts generated by the user are sent to the child
5050  * but not to the shell.  This means that an infinite loop started by
5051  * an interactive user may be hard to kill.  With job control turned off,
5052  * an interactive user may place an interactive program inside a loop.
5053  * If the interactive program catches interrupts, the user doesn't want
5054  * these interrupts to also abort the loop.  The approach we take here
5055  * is to have the shell ignore interrupt signals while waiting for a
5056  * foreground process to terminate, and then send itself an interrupt
5057  * signal if the child process was terminated by an interrupt signal.
5058  * Unfortunately, some programs want to do a bit of cleanup and then
5059  * exit on interrupt; unless these processes terminate themselves by
5060  * sending a signal to themselves (instead of calling exit) they will
5061  * confuse this approach.
5062  *
5063  * Called with interrupts off.
5064  */
5065 static int
5066 waitforjob(struct job *jp)
5067 {
5068         int st;
5069
5070         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5071
5072         INT_OFF;
5073         while (jp->state == JOBRUNNING) {
5074                 /* In non-interactive shells, we _can_ get
5075                  * a keyboard signal here and be EINTRed,
5076                  * but we just loop back, waiting for command to complete.
5077                  *
5078                  * man bash:
5079                  * "If bash is waiting for a command to complete and receives
5080                  * a signal for which a trap has been set, the trap
5081                  * will not be executed until the command completes."
5082                  *
5083                  * Reality is that even if trap is not set, bash
5084                  * will not act on the signal until command completes.
5085                  * Try this. sleep5intoff.c:
5086                  * #include <signal.h>
5087                  * #include <unistd.h>
5088                  * int main() {
5089                  *         sigset_t set;
5090                  *         sigemptyset(&set);
5091                  *         sigaddset(&set, SIGINT);
5092                  *         sigaddset(&set, SIGQUIT);
5093                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5094                  *         sleep(5);
5095                  *         return 0;
5096                  * }
5097                  * $ bash -c './sleep5intoff; echo hi'
5098                  * ^C^C^C^C <--- pressing ^C once a second
5099                  * $ _
5100                  * $ bash -c './sleep5intoff; echo hi'
5101                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5102                  * $ _
5103                  */
5104                 dowait(DOWAIT_BLOCK, jp);
5105         }
5106         INT_ON;
5107
5108         st = getstatus(jp);
5109 #if JOBS
5110         if (jp->jobctl) {
5111                 xtcsetpgrp(ttyfd, rootpid);
5112                 restore_tty_if_stopped_or_signaled(jp);
5113
5114                 /*
5115                  * This is truly gross.
5116                  * If we're doing job control, then we did a TIOCSPGRP which
5117                  * caused us (the shell) to no longer be in the controlling
5118                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5119                  * intuit from the subprocess exit status whether a SIGINT
5120                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5121                  */
5122                 if (jp->sigint) /* TODO: do the same with all signals */
5123                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5124         }
5125         if (jp->state == JOBDONE)
5126 #endif
5127                 freejob(jp);
5128         return st;
5129 }
5130
5131 /*
5132  * return 1 if there are stopped jobs, otherwise 0
5133  */
5134 static int
5135 stoppedjobs(void)
5136 {
5137         struct job *jp;
5138         int retval;
5139
5140         retval = 0;
5141         if (job_warning)
5142                 goto out;
5143         jp = curjob;
5144         if (jp && jp->state == JOBSTOPPED) {
5145                 out2str("You have stopped jobs.\n");
5146                 job_warning = 2;
5147                 retval++;
5148         }
5149  out:
5150         return retval;
5151 }
5152
5153
5154 /*
5155  * Code for dealing with input/output redirection.
5156  */
5157
5158 #undef EMPTY
5159 #undef CLOSED
5160 #define EMPTY -2                /* marks an unused slot in redirtab */
5161 #define CLOSED -3               /* marks a slot of previously-closed fd */
5162
5163 /*
5164  * Open a file in noclobber mode.
5165  * The code was copied from bash.
5166  */
5167 static int
5168 noclobberopen(const char *fname)
5169 {
5170         int r, fd;
5171         struct stat finfo, finfo2;
5172
5173         /*
5174          * If the file exists and is a regular file, return an error
5175          * immediately.
5176          */
5177         r = stat(fname, &finfo);
5178         if (r == 0 && S_ISREG(finfo.st_mode)) {
5179                 errno = EEXIST;
5180                 return -1;
5181         }
5182
5183         /*
5184          * If the file was not present (r != 0), make sure we open it
5185          * exclusively so that if it is created before we open it, our open
5186          * will fail.  Make sure that we do not truncate an existing file.
5187          * Note that we don't turn on O_EXCL unless the stat failed -- if the
5188          * file was not a regular file, we leave O_EXCL off.
5189          */
5190         if (r != 0)
5191                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5192         fd = open(fname, O_WRONLY|O_CREAT, 0666);
5193
5194         /* If the open failed, return the file descriptor right away. */
5195         if (fd < 0)
5196                 return fd;
5197
5198         /*
5199          * OK, the open succeeded, but the file may have been changed from a
5200          * non-regular file to a regular file between the stat and the open.
5201          * We are assuming that the O_EXCL open handles the case where FILENAME
5202          * did not exist and is symlinked to an existing file between the stat
5203          * and open.
5204          */
5205
5206         /*
5207          * If we can open it and fstat the file descriptor, and neither check
5208          * revealed that it was a regular file, and the file has not been
5209          * replaced, return the file descriptor.
5210          */
5211         if (fstat(fd, &finfo2) == 0
5212          && !S_ISREG(finfo2.st_mode)
5213          && finfo.st_dev == finfo2.st_dev
5214          && finfo.st_ino == finfo2.st_ino
5215         ) {
5216                 return fd;
5217         }
5218
5219         /* The file has been replaced.  badness. */
5220         close(fd);
5221         errno = EEXIST;
5222         return -1;
5223 }
5224
5225 /*
5226  * Handle here documents.  Normally we fork off a process to write the
5227  * data to a pipe.  If the document is short, we can stuff the data in
5228  * the pipe without forking.
5229  */
5230 /* openhere needs this forward reference */
5231 static void expandhere(union node *arg, int fd);
5232 static int
5233 openhere(union node *redir)
5234 {
5235         int pip[2];
5236         size_t len = 0;
5237
5238         if (pipe(pip) < 0)
5239                 ash_msg_and_raise_error("pipe call failed");
5240         if (redir->type == NHERE) {
5241                 len = strlen(redir->nhere.doc->narg.text);
5242                 if (len <= PIPE_BUF) {
5243                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5244                         goto out;
5245                 }
5246         }
5247         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5248                 /* child */
5249                 close(pip[0]);
5250                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5251                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5252                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5253                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5254                 signal(SIGPIPE, SIG_DFL);
5255                 if (redir->type == NHERE)
5256                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5257                 else /* NXHERE */
5258                         expandhere(redir->nhere.doc, pip[1]);
5259                 _exit(EXIT_SUCCESS);
5260         }
5261  out:
5262         close(pip[1]);
5263         return pip[0];
5264 }
5265
5266 static int
5267 openredirect(union node *redir)
5268 {
5269         char *fname;
5270         int f;
5271
5272         switch (redir->nfile.type) {
5273 /* Can't happen, our single caller does this itself */
5274 //      case NTOFD:
5275 //      case NFROMFD:
5276 //              return -1;
5277         case NHERE:
5278         case NXHERE:
5279                 return openhere(redir);
5280         }
5281
5282         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5283          * allocated space. Do it only when we know it is safe.
5284          */
5285         fname = redir->nfile.expfname;
5286
5287         switch (redir->nfile.type) {
5288         default:
5289 #if DEBUG
5290                 abort();
5291 #endif
5292         case NFROM:
5293                 f = open(fname, O_RDONLY);
5294                 if (f < 0)
5295                         goto eopen;
5296                 break;
5297         case NFROMTO:
5298                 f = open(fname, O_RDWR|O_CREAT, 0666);
5299                 if (f < 0)
5300                         goto ecreate;
5301                 break;
5302         case NTO:
5303 #if BASH_REDIR_OUTPUT
5304         case NTO2:
5305 #endif
5306                 /* Take care of noclobber mode. */
5307                 if (Cflag) {
5308                         f = noclobberopen(fname);
5309                         if (f < 0)
5310                                 goto ecreate;
5311                         break;
5312                 }
5313                 /* FALLTHROUGH */
5314         case NCLOBBER:
5315                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5316                 if (f < 0)
5317                         goto ecreate;
5318                 break;
5319         case NAPPEND:
5320                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5321                 if (f < 0)
5322                         goto ecreate;
5323                 break;
5324         }
5325
5326         return f;
5327  ecreate:
5328         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5329  eopen:
5330         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5331 }
5332
5333 /*
5334  * Copy a file descriptor to be >= 10. Throws exception on error.
5335  */
5336 static int
5337 savefd(int from)
5338 {
5339         int newfd;
5340         int err;
5341
5342         newfd = fcntl(from, F_DUPFD, 10);
5343         err = newfd < 0 ? errno : 0;
5344         if (err != EBADF) {
5345                 if (err)
5346                         ash_msg_and_raise_error("%d: %m", from);
5347                 close(from);
5348                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5349         }
5350
5351         return newfd;
5352 }
5353 static int
5354 dup2_or_raise(int from, int to)
5355 {
5356         int newfd;
5357
5358         newfd = (from != to) ? dup2(from, to) : to;
5359         if (newfd < 0) {
5360                 /* Happens when source fd is not open: try "echo >&99" */
5361                 ash_msg_and_raise_error("%d: %m", from);
5362         }
5363         return newfd;
5364 }
5365
5366 /* Struct def and variable are moved down to the first usage site */
5367 struct two_fd_t {
5368         int orig, copy;
5369 };
5370 struct redirtab {
5371         struct redirtab *next;
5372         int pair_count;
5373         struct two_fd_t two_fd[];
5374 };
5375 #define redirlist (G_var.redirlist)
5376 enum {
5377         COPYFD_RESTORE = (int)~(INT_MAX),
5378 };
5379
5380 static int
5381 need_to_remember(struct redirtab *rp, int fd)
5382 {
5383         int i;
5384
5385         if (!rp) /* remembering was not requested */
5386                 return 0;
5387
5388         for (i = 0; i < rp->pair_count; i++) {
5389                 if (rp->two_fd[i].orig == fd) {
5390                         /* already remembered */
5391                         return 0;
5392                 }
5393         }
5394         return 1;
5395 }
5396
5397 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5398 static int
5399 is_hidden_fd(struct redirtab *rp, int fd)
5400 {
5401         int i;
5402         struct parsefile *pf;
5403
5404         if (fd == -1)
5405                 return 0;
5406         /* Check open scripts' fds */
5407         pf = g_parsefile;
5408         while (pf) {
5409                 /* We skip pf_fd == 0 case because of the following case:
5410                  * $ ash  # running ash interactively
5411                  * $ . ./script.sh
5412                  * and in script.sh: "exec 9>&0".
5413                  * Even though top-level pf_fd _is_ 0,
5414                  * it's still ok to use it: "read" builtin uses it,
5415                  * why should we cripple "exec" builtin?
5416                  */
5417                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5418                         return 1;
5419                 }
5420                 pf = pf->prev;
5421         }
5422
5423         if (!rp)
5424                 return 0;
5425         /* Check saved fds of redirects */
5426         fd |= COPYFD_RESTORE;
5427         for (i = 0; i < rp->pair_count; i++) {
5428                 if (rp->two_fd[i].copy == fd) {
5429                         return 1;
5430                 }
5431         }
5432         return 0;
5433 }
5434
5435 /*
5436  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5437  * old file descriptors are stashed away so that the redirection can be
5438  * undone by calling popredir.
5439  */
5440 /* flags passed to redirect */
5441 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5442 #define REDIR_SAVEFD2 03        /* set preverrout */
5443 static void
5444 redirect(union node *redir, int flags)
5445 {
5446         struct redirtab *sv;
5447         int sv_pos;
5448         int i;
5449         int fd;
5450         int newfd;
5451         int copied_fd2 = -1;
5452
5453         if (!redir) {
5454                 return;
5455         }
5456
5457         sv = NULL;
5458         sv_pos = 0;
5459         INT_OFF;
5460         if (flags & REDIR_PUSH) {
5461                 union node *tmp = redir;
5462                 do {
5463                         sv_pos++;
5464 #if BASH_REDIR_OUTPUT
5465                         if (tmp->nfile.type == NTO2)
5466                                 sv_pos++;
5467 #endif
5468                         tmp = tmp->nfile.next;
5469                 } while (tmp);
5470                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5471                 sv->next = redirlist;
5472                 sv->pair_count = sv_pos;
5473                 redirlist = sv;
5474                 while (sv_pos > 0) {
5475                         sv_pos--;
5476                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5477                 }
5478         }
5479
5480         do {
5481                 int right_fd = -1;
5482                 fd = redir->nfile.fd;
5483                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5484                         right_fd = redir->ndup.dupfd;
5485                         //bb_error_msg("doing %d > %d", fd, right_fd);
5486                         /* redirect from/to same file descriptor? */
5487                         if (right_fd == fd)
5488                                 continue;
5489                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5490                         if (is_hidden_fd(sv, right_fd)) {
5491                                 errno = EBADF; /* as if it is closed */
5492                                 ash_msg_and_raise_error("%d: %m", right_fd);
5493                         }
5494                         newfd = -1;
5495                 } else {
5496                         newfd = openredirect(redir); /* always >= 0 */
5497                         if (fd == newfd) {
5498                                 /* Descriptor wasn't open before redirect.
5499                                  * Mark it for close in the future */
5500                                 if (need_to_remember(sv, fd)) {
5501                                         goto remember_to_close;
5502                                 }
5503                                 continue;
5504                         }
5505                 }
5506 #if BASH_REDIR_OUTPUT
5507  redirect_more:
5508 #endif
5509                 if (need_to_remember(sv, fd)) {
5510                         /* Copy old descriptor */
5511                         /* Careful to not accidentally "save"
5512                          * to the same fd as right side fd in N>&M */
5513                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5514 #if defined(F_DUPFD_CLOEXEC)
5515                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5516 #else
5517                         i = fcntl(fd, F_DUPFD, minfd);
5518 #endif
5519                         if (i == -1) {
5520                                 i = errno;
5521                                 if (i != EBADF) {
5522                                         /* Strange error (e.g. "too many files" EMFILE?) */
5523                                         if (newfd >= 0)
5524                                                 close(newfd);
5525                                         errno = i;
5526                                         ash_msg_and_raise_error("%d: %m", fd);
5527                                         /* NOTREACHED */
5528                                 }
5529                                 /* EBADF: it is not open - good, remember to close it */
5530  remember_to_close:
5531                                 i = CLOSED;
5532                         } else { /* fd is open, save its copy */
5533 #if !defined(F_DUPFD_CLOEXEC)
5534                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5535 #endif
5536                                 /* "exec fd>&-" should not close fds
5537                                  * which point to script file(s).
5538                                  * Force them to be restored afterwards */
5539                                 if (is_hidden_fd(sv, fd))
5540                                         i |= COPYFD_RESTORE;
5541                         }
5542                         if (fd == 2)
5543                                 copied_fd2 = i;
5544                         sv->two_fd[sv_pos].orig = fd;
5545                         sv->two_fd[sv_pos].copy = i;
5546                         sv_pos++;
5547                 }
5548                 if (newfd < 0) {
5549                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5550                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5551                                 /* Don't want to trigger debugging */
5552                                 if (fd != -1)
5553                                         close(fd);
5554                         } else {
5555                                 dup2_or_raise(redir->ndup.dupfd, fd);
5556                         }
5557                 } else if (fd != newfd) { /* move newfd to fd */
5558                         dup2_or_raise(newfd, fd);
5559 #if BASH_REDIR_OUTPUT
5560                         if (!(redir->nfile.type == NTO2 && fd == 2))
5561 #endif
5562                                 close(newfd);
5563                 }
5564 #if BASH_REDIR_OUTPUT
5565                 if (redir->nfile.type == NTO2 && fd == 1) {
5566                         /* We already redirected it to fd 1, now copy it to 2 */
5567                         newfd = 1;
5568                         fd = 2;
5569                         goto redirect_more;
5570                 }
5571 #endif
5572         } while ((redir = redir->nfile.next) != NULL);
5573
5574         INT_ON;
5575         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5576                 preverrout_fd = copied_fd2;
5577 }
5578
5579 /*
5580  * Undo the effects of the last redirection.
5581  */
5582 static void
5583 popredir(int drop, int restore)
5584 {
5585         struct redirtab *rp;
5586         int i;
5587
5588         if (redirlist == NULL)
5589                 return;
5590         INT_OFF;
5591         rp = redirlist;
5592         for (i = 0; i < rp->pair_count; i++) {
5593                 int fd = rp->two_fd[i].orig;
5594                 int copy = rp->two_fd[i].copy;
5595                 if (copy == CLOSED) {
5596                         if (!drop)
5597                                 close(fd);
5598                         continue;
5599                 }
5600                 if (copy != EMPTY) {
5601                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5602                                 copy &= ~COPYFD_RESTORE;
5603                                 /*close(fd);*/
5604                                 dup2_or_raise(copy, fd);
5605                         }
5606                         close(copy & ~COPYFD_RESTORE);
5607                 }
5608         }
5609         redirlist = rp->next;
5610         free(rp);
5611         INT_ON;
5612 }
5613
5614 /*
5615  * Undo all redirections.  Called on error or interrupt.
5616  */
5617
5618 static int
5619 redirectsafe(union node *redir, int flags)
5620 {
5621         int err;
5622         volatile int saveint;
5623         struct jmploc *volatile savehandler = exception_handler;
5624         struct jmploc jmploc;
5625
5626         SAVE_INT(saveint);
5627         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5628         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5629         if (!err) {
5630                 exception_handler = &jmploc;
5631                 redirect(redir, flags);
5632         }
5633         exception_handler = savehandler;
5634         if (err && exception_type != EXERROR)
5635                 longjmp(exception_handler->loc, 1);
5636         RESTORE_INT(saveint);
5637         return err;
5638 }
5639
5640
5641 /* ============ Routines to expand arguments to commands
5642  *
5643  * We have to deal with backquotes, shell variables, and file metacharacters.
5644  */
5645
5646 #if ENABLE_FEATURE_SH_MATH
5647 static arith_t
5648 ash_arith(const char *s)
5649 {
5650         arith_state_t math_state;
5651         arith_t result;
5652
5653         math_state.lookupvar = lookupvar;
5654         math_state.setvar    = setvar0;
5655         //math_state.endofname = endofname;
5656
5657         INT_OFF;
5658         result = arith(&math_state, s);
5659         if (math_state.errmsg)
5660                 ash_msg_and_raise_error(math_state.errmsg);
5661         INT_ON;
5662
5663         return result;
5664 }
5665 #endif
5666
5667 /*
5668  * expandarg flags
5669  */
5670 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5671 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5672 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5673 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5674 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5675  * POSIX says for this case:
5676  *  Pathname expansion shall not be performed on the word by a
5677  *  non-interactive shell; an interactive shell may perform it, but shall
5678  *  do so only when the expansion would result in one word.
5679  * Currently, our code complies to the above rule by never globbing
5680  * redirection filenames.
5681  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5682  * (this means that on a typical Linux distro, bash almost always
5683  * performs globbing, and thus diverges from what we do).
5684  */
5685 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5686 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5687 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5688 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5689 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5690 /*
5691  * rmescape() flags
5692  */
5693 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5694 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5695 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5696 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5697 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5698
5699 /* Add CTLESC when necessary. */
5700 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR)
5701 /* Do not skip NUL characters. */
5702 #define QUOTES_KEEPNUL EXP_TILDE
5703
5704 /*
5705  * Structure specifying which parts of the string should be searched
5706  * for IFS characters.
5707  */
5708 struct ifsregion {
5709         struct ifsregion *next; /* next region in list */
5710         int begoff;             /* offset of start of region */
5711         int endoff;             /* offset of end of region */
5712         int nulonly;            /* search for nul bytes only */
5713 };
5714
5715 struct arglist {
5716         struct strlist *list;
5717         struct strlist **lastp;
5718 };
5719
5720 /* output of current string */
5721 static char *expdest;
5722 /* list of back quote expressions */
5723 static struct nodelist *argbackq;
5724 /* first struct in list of ifs regions */
5725 static struct ifsregion ifsfirst;
5726 /* last struct in list */
5727 static struct ifsregion *ifslastp;
5728 /* holds expanded arg list */
5729 static struct arglist exparg;
5730
5731 /*
5732  * Our own itoa().
5733  */
5734 #if !ENABLE_FEATURE_SH_MATH
5735 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5736 typedef long arith_t;
5737 # define ARITH_FMT "%ld"
5738 #endif
5739 static int
5740 cvtnum(arith_t num)
5741 {
5742         int len;
5743
5744         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5745         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5746         STADJUST(len, expdest);
5747         return len;
5748 }
5749
5750 /*
5751  * Break the argument string into pieces based upon IFS and add the
5752  * strings to the argument list.  The regions of the string to be
5753  * searched for IFS characters have been stored by recordregion.
5754  */
5755 static void
5756 ifsbreakup(char *string, struct arglist *arglist)
5757 {
5758         struct ifsregion *ifsp;
5759         struct strlist *sp;
5760         char *start;
5761         char *p;
5762         char *q;
5763         const char *ifs, *realifs;
5764         int ifsspc;
5765         int nulonly;
5766
5767         start = string;
5768         if (ifslastp != NULL) {
5769                 ifsspc = 0;
5770                 nulonly = 0;
5771                 realifs = ifsset() ? ifsval() : defifs;
5772                 ifsp = &ifsfirst;
5773                 do {
5774                         p = string + ifsp->begoff;
5775                         nulonly = ifsp->nulonly;
5776                         ifs = nulonly ? nullstr : realifs;
5777                         ifsspc = 0;
5778                         while (p < string + ifsp->endoff) {
5779                                 q = p;
5780                                 if ((unsigned char)*p == CTLESC)
5781                                         p++;
5782                                 if (!strchr(ifs, *p)) {
5783                                         p++;
5784                                         continue;
5785                                 }
5786                                 if (!nulonly)
5787                                         ifsspc = (strchr(defifs, *p) != NULL);
5788                                 /* Ignore IFS whitespace at start */
5789                                 if (q == start && ifsspc) {
5790                                         p++;
5791                                         start = p;
5792                                         continue;
5793                                 }
5794                                 *q = '\0';
5795                                 sp = stzalloc(sizeof(*sp));
5796                                 sp->text = start;
5797                                 *arglist->lastp = sp;
5798                                 arglist->lastp = &sp->next;
5799                                 p++;
5800                                 if (!nulonly) {
5801                                         for (;;) {
5802                                                 if (p >= string + ifsp->endoff) {
5803                                                         break;
5804                                                 }
5805                                                 q = p;
5806                                                 if ((unsigned char)*p == CTLESC)
5807                                                         p++;
5808                                                 if (strchr(ifs, *p) == NULL) {
5809                                                         p = q;
5810                                                         break;
5811                                                 }
5812                                                 if (strchr(defifs, *p) == NULL) {
5813                                                         if (ifsspc) {
5814                                                                 p++;
5815                                                                 ifsspc = 0;
5816                                                         } else {
5817                                                                 p = q;
5818                                                                 break;
5819                                                         }
5820                                                 } else
5821                                                         p++;
5822                                         }
5823                                 }
5824                                 start = p;
5825                         } /* while */
5826                         ifsp = ifsp->next;
5827                 } while (ifsp != NULL);
5828                 if (nulonly)
5829                         goto add;
5830         }
5831
5832         if (!*start)
5833                 return;
5834
5835  add:
5836         sp = stzalloc(sizeof(*sp));
5837         sp->text = start;
5838         *arglist->lastp = sp;
5839         arglist->lastp = &sp->next;
5840 }
5841
5842 static void
5843 ifsfree(void)
5844 {
5845         struct ifsregion *p = ifsfirst.next;
5846
5847         if (!p)
5848                 goto out;
5849
5850         INT_OFF;
5851         do {
5852                 struct ifsregion *ifsp;
5853                 ifsp = p->next;
5854                 free(p);
5855                 p = ifsp;
5856         } while (p);
5857         ifsfirst.next = NULL;
5858         INT_ON;
5859  out:
5860         ifslastp = NULL;
5861 }
5862
5863 static size_t
5864 esclen(const char *start, const char *p)
5865 {
5866         size_t esc = 0;
5867
5868         while (p > start && (unsigned char)*--p == CTLESC) {
5869                 esc++;
5870         }
5871         return esc;
5872 }
5873
5874 /*
5875  * Remove any CTLESC characters from a string.
5876  */
5877 static char *
5878 rmescapes(char *str, int flag)
5879 {
5880         static const char qchars[] ALIGN1 = {
5881                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5882
5883         char *p, *q, *r;
5884         unsigned inquotes;
5885         unsigned protect_against_glob;
5886         unsigned globbing;
5887         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5888
5889         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5890         if (!p)
5891                 return str;
5892
5893         q = p;
5894         r = str;
5895         if (flag & RMESCAPE_ALLOC) {
5896                 size_t len = p - str;
5897                 size_t fulllen = len + strlen(p) + 1;
5898
5899                 if (flag & RMESCAPE_GROW) {
5900                         int strloc = str - (char *)stackblock();
5901                         r = makestrspace(fulllen, expdest);
5902                         /* p and str may be invalidated by makestrspace */
5903                         str = (char *)stackblock() + strloc;
5904                         p = str + len;
5905                 } else if (flag & RMESCAPE_HEAP) {
5906                         r = ckmalloc(fulllen);
5907                 } else {
5908                         r = stalloc(fulllen);
5909                 }
5910                 q = r;
5911                 if (len > 0) {
5912                         q = (char *)memcpy(q, str, len) + len;
5913                 }
5914         }
5915
5916         inquotes = 0;
5917         globbing = flag & RMESCAPE_GLOB;
5918         protect_against_glob = globbing;
5919         while (*p) {
5920                 if ((unsigned char)*p == CTLQUOTEMARK) {
5921 // Note: both inquotes and protect_against_glob only affect whether
5922 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5923                         inquotes = ~inquotes;
5924                         p++;
5925                         protect_against_glob = globbing;
5926                         continue;
5927                 }
5928                 if ((unsigned char)*p == CTLESC) {
5929                         p++;
5930 #if DEBUG
5931                         if (*p == '\0')
5932                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5933 #endif
5934                         if (protect_against_glob) {
5935                                 /*
5936                                  * We used to trust glob() and fnmatch() to eat
5937                                  * superfluous escapes (\z where z has no
5938                                  * special meaning anyway). But this causes
5939                                  * bugs such as string of one greek letter rho
5940                                  * (unicode-encoded as two bytes "cf,81")
5941                                  * getting encoded as "cf,CTLESC,81"
5942                                  * and here, converted to "cf,\,81" -
5943                                  * which does not go well with some flavors
5944                                  * of fnmatch() in unicode locales
5945                                  * (for example, glibc <= 2.22).
5946                                  *
5947                                  * Lets add "\" only on the chars which need it.
5948                                  * Testcases for less obvious chars are shown.
5949                                  */
5950                                 if (*p == '*'
5951                                  || *p == '?'
5952                                  || *p == '['
5953                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5954                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5955                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5956                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5957                                 /* Some libc support [^negate], that's why "^" also needs love */
5958                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5959                                 ) {
5960                                         *q++ = '\\';
5961                                 }
5962                         }
5963                 } else if (*p == '\\' && !inquotes) {
5964                         /* naked back slash */
5965                         protect_against_glob = 0;
5966                         goto copy;
5967                 }
5968 #if BASH_PATTERN_SUBST
5969                 else if (*p == '/' && slash) {
5970                         /* stop handling globbing and mark location of slash */
5971                         globbing = slash = 0;
5972                         *p = CTLESC;
5973                 }
5974 #endif
5975                 protect_against_glob = globbing;
5976  copy:
5977                 *q++ = *p++;
5978         }
5979         *q = '\0';
5980         if (flag & RMESCAPE_GROW) {
5981                 expdest = r;
5982                 STADJUST(q - r + 1, expdest);
5983         }
5984         return r;
5985 }
5986 #define pmatch(a, b) !fnmatch((a), (b), 0)
5987
5988 /*
5989  * Prepare a pattern for a expmeta (internal glob(3)) call.
5990  *
5991  * Returns an stalloced string.
5992  */
5993 static char *
5994 preglob(const char *pattern, int flag)
5995 {
5996         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5997 }
5998
5999 /*
6000  * Put a string on the stack.
6001  */
6002 static void
6003 memtodest(const char *p, size_t len, int syntax, int quotes)
6004 {
6005         char *q;
6006
6007         if (!len)
6008                 return;
6009
6010         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6011
6012         do {
6013                 unsigned char c = *p++;
6014                 if (c) {
6015                         if (quotes & QUOTES_ESC) {
6016                                 int n = SIT(c, syntax);
6017                                 if (n == CCTL
6018                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6019                                      && n == CBACK
6020                                     )
6021                                 ) {
6022                                         USTPUTC(CTLESC, q);
6023                                 }
6024                         }
6025                 } else if (!(quotes & QUOTES_KEEPNUL))
6026                         continue;
6027                 USTPUTC(c, q);
6028         } while (--len);
6029
6030         expdest = q;
6031 }
6032
6033 static size_t
6034 strtodest(const char *p, int syntax, int quotes)
6035 {
6036         size_t len = strlen(p);
6037         memtodest(p, len, syntax, quotes);
6038         return len;
6039 }
6040
6041 /*
6042  * Record the fact that we have to scan this region of the
6043  * string for IFS characters.
6044  */
6045 static void
6046 recordregion(int start, int end, int nulonly)
6047 {
6048         struct ifsregion *ifsp;
6049
6050         if (ifslastp == NULL) {
6051                 ifsp = &ifsfirst;
6052         } else {
6053                 INT_OFF;
6054                 ifsp = ckzalloc(sizeof(*ifsp));
6055                 /*ifsp->next = NULL; - ckzalloc did it */
6056                 ifslastp->next = ifsp;
6057                 INT_ON;
6058         }
6059         ifslastp = ifsp;
6060         ifslastp->begoff = start;
6061         ifslastp->endoff = end;
6062         ifslastp->nulonly = nulonly;
6063 }
6064
6065 static void
6066 removerecordregions(int endoff)
6067 {
6068         if (ifslastp == NULL)
6069                 return;
6070
6071         if (ifsfirst.endoff > endoff) {
6072                 while (ifsfirst.next) {
6073                         struct ifsregion *ifsp;
6074                         INT_OFF;
6075                         ifsp = ifsfirst.next->next;
6076                         free(ifsfirst.next);
6077                         ifsfirst.next = ifsp;
6078                         INT_ON;
6079                 }
6080                 if (ifsfirst.begoff > endoff) {
6081                         ifslastp = NULL;
6082                 } else {
6083                         ifslastp = &ifsfirst;
6084                         ifsfirst.endoff = endoff;
6085                 }
6086                 return;
6087         }
6088
6089         ifslastp = &ifsfirst;
6090         while (ifslastp->next && ifslastp->next->begoff < endoff)
6091                 ifslastp = ifslastp->next;
6092         while (ifslastp->next) {
6093                 struct ifsregion *ifsp;
6094                 INT_OFF;
6095                 ifsp = ifslastp->next->next;
6096                 free(ifslastp->next);
6097                 ifslastp->next = ifsp;
6098                 INT_ON;
6099         }
6100         if (ifslastp->endoff > endoff)
6101                 ifslastp->endoff = endoff;
6102 }
6103
6104 static char *
6105 exptilde(char *startp, char *p, int flags)
6106 {
6107         unsigned char c;
6108         char *name;
6109         struct passwd *pw;
6110         const char *home;
6111         int quotes = flags & QUOTES_ESC;
6112
6113         name = p + 1;
6114
6115         while ((c = *++p) != '\0') {
6116                 switch (c) {
6117                 case CTLESC:
6118                         return startp;
6119                 case CTLQUOTEMARK:
6120                         return startp;
6121                 case ':':
6122                         if (flags & EXP_VARTILDE)
6123                                 goto done;
6124                         break;
6125                 case '/':
6126                 case CTLENDVAR:
6127                         goto done;
6128                 }
6129         }
6130  done:
6131         *p = '\0';
6132         if (*name == '\0') {
6133                 home = lookupvar("HOME");
6134         } else {
6135                 pw = getpwnam(name);
6136                 if (pw == NULL)
6137                         goto lose;
6138                 home = pw->pw_dir;
6139         }
6140         if (!home || !*home)
6141                 goto lose;
6142         *p = c;
6143         strtodest(home, SQSYNTAX, quotes);
6144         return p;
6145  lose:
6146         *p = c;
6147         return startp;
6148 }
6149
6150 /*
6151  * Execute a command inside back quotes.  If it's a builtin command, we
6152  * want to save its output in a block obtained from malloc.  Otherwise
6153  * we fork off a subprocess and get the output of the command via a pipe.
6154  * Should be called with interrupts off.
6155  */
6156 struct backcmd {                /* result of evalbackcmd */
6157         int fd;                 /* file descriptor to read from */
6158         int nleft;              /* number of chars in buffer */
6159         char *buf;              /* buffer */
6160         struct job *jp;         /* job structure for command */
6161 };
6162
6163 /* These forward decls are needed to use "eval" code for backticks handling: */
6164 #define EV_EXIT 01              /* exit after evaluating tree */
6165 static int evaltree(union node *, int);
6166
6167 static void FAST_FUNC
6168 evalbackcmd(union node *n, struct backcmd *result)
6169 {
6170         int pip[2];
6171         struct job *jp;
6172
6173         result->fd = -1;
6174         result->buf = NULL;
6175         result->nleft = 0;
6176         result->jp = NULL;
6177         if (n == NULL) {
6178                 goto out;
6179         }
6180
6181         if (pipe(pip) < 0)
6182                 ash_msg_and_raise_error("pipe call failed");
6183         jp = makejob(/*n,*/ 1);
6184         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6185                 /* child */
6186                 FORCE_INT_ON;
6187                 close(pip[0]);
6188                 if (pip[1] != 1) {
6189                         /*close(1);*/
6190                         dup2_or_raise(pip[1], 1);
6191                         close(pip[1]);
6192                 }
6193 /* TODO: eflag clearing makes the following not abort:
6194  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6195  * which is what bash does (unless it is in POSIX mode).
6196  * dash deleted "eflag = 0" line in the commit
6197  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6198  *  [EVAL] Don't clear eflag in evalbackcmd
6199  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6200  */
6201                 eflag = 0;
6202                 ifsfree();
6203                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6204                 /* NOTREACHED */
6205         }
6206         /* parent */
6207         close(pip[1]);
6208         result->fd = pip[0];
6209         result->jp = jp;
6210
6211  out:
6212         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6213                 result->fd, result->buf, result->nleft, result->jp));
6214 }
6215
6216 /*
6217  * Expand stuff in backwards quotes.
6218  */
6219 static void
6220 expbackq(union node *cmd, int flag)
6221 {
6222         struct backcmd in;
6223         int i;
6224         char buf[128];
6225         char *p;
6226         char *dest;
6227         int startloc;
6228         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6229         struct stackmark smark;
6230
6231         INT_OFF;
6232         startloc = expdest - (char *)stackblock();
6233         pushstackmark(&smark, startloc);
6234         evalbackcmd(cmd, &in);
6235         popstackmark(&smark);
6236
6237         p = in.buf;
6238         i = in.nleft;
6239         if (i == 0)
6240                 goto read;
6241         for (;;) {
6242                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6243  read:
6244                 if (in.fd < 0)
6245                         break;
6246                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6247                 TRACE(("expbackq: read returns %d\n", i));
6248                 if (i <= 0)
6249                         break;
6250                 p = buf;
6251         }
6252
6253         free(in.buf);
6254         if (in.fd >= 0) {
6255                 close(in.fd);
6256                 back_exitstatus = waitforjob(in.jp);
6257         }
6258         INT_ON;
6259
6260         /* Eat all trailing newlines */
6261         dest = expdest;
6262         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6263                 STUNPUTC(dest);
6264         expdest = dest;
6265
6266         if (!(flag & EXP_QUOTED))
6267                 recordregion(startloc, dest - (char *)stackblock(), 0);
6268         TRACE(("evalbackq: size:%d:'%.*s'\n",
6269                 (int)((dest - (char *)stackblock()) - startloc),
6270                 (int)((dest - (char *)stackblock()) - startloc),
6271                 stackblock() + startloc));
6272 }
6273
6274 #if ENABLE_FEATURE_SH_MATH
6275 /*
6276  * Expand arithmetic expression.  Backup to start of expression,
6277  * evaluate, place result in (backed up) result, adjust string position.
6278  */
6279 static void
6280 expari(int flag)
6281 {
6282         char *p, *start;
6283         int begoff;
6284         int len;
6285
6286         /* ifsfree(); */
6287
6288         /*
6289          * This routine is slightly over-complicated for
6290          * efficiency.  Next we scan backwards looking for the
6291          * start of arithmetic.
6292          */
6293         start = stackblock();
6294         p = expdest - 1;
6295         *p = '\0';
6296         p--;
6297         while (1) {
6298                 int esc;
6299
6300                 while ((unsigned char)*p != CTLARI) {
6301                         p--;
6302 #if DEBUG
6303                         if (p < start) {
6304                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6305                         }
6306 #endif
6307                 }
6308
6309                 esc = esclen(start, p);
6310                 if (!(esc % 2)) {
6311                         break;
6312                 }
6313
6314                 p -= esc + 1;
6315         }
6316
6317         begoff = p - start;
6318
6319         removerecordregions(begoff);
6320
6321         expdest = p;
6322
6323         if (flag & QUOTES_ESC)
6324                 rmescapes(p + 1, 0);
6325
6326         len = cvtnum(ash_arith(p + 1));
6327
6328         if (!(flag & EXP_QUOTED))
6329                 recordregion(begoff, begoff + len, 0);
6330 }
6331 #endif
6332
6333 /* argstr needs it */
6334 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6335
6336 /*
6337  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6338  * characters to allow for further processing.  Otherwise treat
6339  * $@ like $* since no splitting will be performed.
6340  *
6341  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6342  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6343  * for correct expansion of "B=$A" word.
6344  */
6345 static void
6346 argstr(char *p, int flags, struct strlist *var_str_list)
6347 {
6348         static const char spclchars[] ALIGN1 = {
6349                 '=',
6350                 ':',
6351                 CTLQUOTEMARK,
6352                 CTLENDVAR,
6353                 CTLESC,
6354                 CTLVAR,
6355                 CTLBACKQ,
6356 #if ENABLE_FEATURE_SH_MATH
6357                 CTLENDARI,
6358 #endif
6359                 '\0'
6360         };
6361         const char *reject = spclchars;
6362         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6363         int inquotes;
6364         size_t length;
6365         int startloc;
6366
6367         if (!(flags & EXP_VARTILDE)) {
6368                 reject += 2;
6369         } else if (flags & EXP_VARTILDE2) {
6370                 reject++;
6371         }
6372         inquotes = 0;
6373         length = 0;
6374         if (flags & EXP_TILDE) {
6375                 char *q;
6376
6377                 flags &= ~EXP_TILDE;
6378  tilde:
6379                 q = p;
6380                 if (*q == '~')
6381                         p = exptilde(p, q, flags);
6382         }
6383  start:
6384         startloc = expdest - (char *)stackblock();
6385         for (;;) {
6386                 unsigned char c;
6387
6388                 length += strcspn(p + length, reject);
6389                 c = p[length];
6390                 if (c) {
6391                         if (!(c & 0x80)
6392                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6393                         ) {
6394                                 /* c == '=' || c == ':' || c == CTLENDARI */
6395                                 length++;
6396                         }
6397                 }
6398                 if (length > 0) {
6399                         int newloc;
6400                         expdest = stack_nputstr(p, length, expdest);
6401                         newloc = expdest - (char *)stackblock();
6402                         if (breakall && !inquotes && newloc > startloc) {
6403                                 recordregion(startloc, newloc, 0);
6404                         }
6405                         startloc = newloc;
6406                 }
6407                 p += length + 1;
6408                 length = 0;
6409
6410                 switch (c) {
6411                 case '\0':
6412                         goto breakloop;
6413                 case '=':
6414                         if (flags & EXP_VARTILDE2) {
6415                                 p--;
6416                                 continue;
6417                         }
6418                         flags |= EXP_VARTILDE2;
6419                         reject++;
6420                         /* fall through */
6421                 case ':':
6422                         /*
6423                          * sort of a hack - expand tildes in variable
6424                          * assignments (after the first '=' and after ':'s).
6425                          */
6426                         if (*--p == '~') {
6427                                 goto tilde;
6428                         }
6429                         continue;
6430                 }
6431
6432                 switch (c) {
6433                 case CTLENDVAR: /* ??? */
6434                         goto breakloop;
6435                 case CTLQUOTEMARK:
6436                         inquotes ^= EXP_QUOTED;
6437                         /* "$@" syntax adherence hack */
6438                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6439                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6440                                 goto start;
6441                         }
6442  addquote:
6443                         if (flags & QUOTES_ESC) {
6444                                 p--;
6445                                 length++;
6446                                 startloc++;
6447                         }
6448                         break;
6449                 case CTLESC:
6450                         startloc++;
6451                         length++;
6452
6453                         /*
6454                          * Quoted parameter expansion pattern: remove quote
6455                          * unless inside inner quotes or we have a literal
6456                          * backslash.
6457                          */
6458                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6459                             EXP_QPAT && *p != '\\')
6460                                 break;
6461
6462                         goto addquote;
6463                 case CTLVAR:
6464                         TRACE(("argstr: evalvar('%s')\n", p));
6465                         p = evalvar(p, flags | inquotes, var_str_list);
6466                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6467                         goto start;
6468                 case CTLBACKQ:
6469                         expbackq(argbackq->n, flags | inquotes);
6470                         argbackq = argbackq->next;
6471                         goto start;
6472 #if ENABLE_FEATURE_SH_MATH
6473                 case CTLENDARI:
6474                         p--;
6475                         expari(flags | inquotes);
6476                         goto start;
6477 #endif
6478                 }
6479         }
6480  breakloop: ;
6481 }
6482
6483 static char *
6484 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6485                 char *pattern, int quotes, int zero)
6486 {
6487         char *loc, *loc2;
6488         char c;
6489
6490         loc = startp;
6491         loc2 = rmesc;
6492         do {
6493                 int match;
6494                 const char *s = loc2;
6495
6496                 c = *loc2;
6497                 if (zero) {
6498                         *loc2 = '\0';
6499                         s = rmesc;
6500                 }
6501                 match = pmatch(pattern, s);
6502
6503                 *loc2 = c;
6504                 if (match)
6505                         return loc;
6506                 if (quotes && (unsigned char)*loc == CTLESC)
6507                         loc++;
6508                 loc++;
6509                 loc2++;
6510         } while (c);
6511         return NULL;
6512 }
6513
6514 static char *
6515 scanright(char *startp, char *rmesc, char *rmescend,
6516                 char *pattern, int quotes, int match_at_start)
6517 {
6518 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6519         int try2optimize = match_at_start;
6520 #endif
6521         int esc = 0;
6522         char *loc;
6523         char *loc2;
6524
6525         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6526          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6527          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6528          * Logic:
6529          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6530          * and on each iteration they go back two/one char until they reach the beginning.
6531          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6532          */
6533         /* TODO: document in what other circumstances we are called. */
6534
6535         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6536                 int match;
6537                 char c = *loc2;
6538                 const char *s = loc2;
6539                 if (match_at_start) {
6540                         *loc2 = '\0';
6541                         s = rmesc;
6542                 }
6543                 match = pmatch(pattern, s);
6544                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6545                 *loc2 = c;
6546                 if (match)
6547                         return loc;
6548 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6549                 if (try2optimize) {
6550                         /* Maybe we can optimize this:
6551                          * if pattern ends with unescaped *, we can avoid checking
6552                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6553                          * it won't match truncated "raw_value_of_" strings too.
6554                          */
6555                         unsigned plen = strlen(pattern);
6556                         /* Does it end with "*"? */
6557                         if (plen != 0 && pattern[--plen] == '*') {
6558                                 /* "xxxx*" is not escaped */
6559                                 /* "xxx\*" is escaped */
6560                                 /* "xx\\*" is not escaped */
6561                                 /* "x\\\*" is escaped */
6562                                 int slashes = 0;
6563                                 while (plen != 0 && pattern[--plen] == '\\')
6564                                         slashes++;
6565                                 if (!(slashes & 1))
6566                                         break; /* ends with unescaped "*" */
6567                         }
6568                         try2optimize = 0;
6569                 }
6570 #endif
6571                 loc--;
6572                 if (quotes) {
6573                         if (--esc < 0) {
6574                                 esc = esclen(startp, loc);
6575                         }
6576                         if (esc % 2) {
6577                                 esc--;
6578                                 loc--;
6579                         }
6580                 }
6581         }
6582         return NULL;
6583 }
6584
6585 static void varunset(const char *, const char *, const char *, int) NORETURN;
6586 static void
6587 varunset(const char *end, const char *var, const char *umsg, int varflags)
6588 {
6589         const char *msg;
6590         const char *tail;
6591
6592         tail = nullstr;
6593         msg = "parameter not set";
6594         if (umsg) {
6595                 if ((unsigned char)*end == CTLENDVAR) {
6596                         if (varflags & VSNUL)
6597                                 tail = " or null";
6598                 } else {
6599                         msg = umsg;
6600                 }
6601         }
6602         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6603 }
6604
6605 static const char *
6606 subevalvar(char *p, char *varname, int strloc, int subtype,
6607                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6608 {
6609         struct nodelist *saveargbackq = argbackq;
6610         int quotes = flag & QUOTES_ESC;
6611         char *startp;
6612         char *loc;
6613         char *rmesc, *rmescend;
6614         char *str;
6615         int amount, resetloc;
6616         IF_BASH_PATTERN_SUBST(int workloc;)
6617         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6618         int zero;
6619         char *(*scan)(char*, char*, char*, char*, int, int);
6620
6621         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6622         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6623
6624         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6625                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6626                         var_str_list);
6627         STPUTC('\0', expdest);
6628         argbackq = saveargbackq;
6629         startp = (char *)stackblock() + startloc;
6630
6631         switch (subtype) {
6632         case VSASSIGN:
6633                 setvar0(varname, startp);
6634                 amount = startp - expdest;
6635                 STADJUST(amount, expdest);
6636                 return startp;
6637
6638         case VSQUESTION:
6639                 varunset(p, varname, startp, varflags);
6640                 /* NOTREACHED */
6641
6642 #if BASH_SUBSTR
6643         case VSSUBSTR: {
6644                 int pos, len, orig_len;
6645                 char *colon;
6646
6647                 loc = str = stackblock() + strloc;
6648
6649 # if !ENABLE_FEATURE_SH_MATH
6650 #  define ash_arith number
6651 # endif
6652                 /* Read POS in ${var:POS:LEN} */
6653                 colon = strchr(loc, ':');
6654                 if (colon) *colon = '\0';
6655                 pos = ash_arith(loc);
6656                 if (colon) *colon = ':';
6657
6658                 /* Read LEN in ${var:POS:LEN} */
6659                 len = str - startp - 1;
6660                 /* *loc != '\0', guaranteed by parser */
6661                 if (quotes) {
6662                         char *ptr;
6663
6664                         /* Adjust the length by the number of escapes */
6665                         for (ptr = startp; ptr < (str - 1); ptr++) {
6666                                 if ((unsigned char)*ptr == CTLESC) {
6667                                         len--;
6668                                         ptr++;
6669                                 }
6670                         }
6671                 }
6672                 orig_len = len;
6673                 if (*loc++ == ':') {
6674                         /* ${var::LEN} */
6675                         len = ash_arith(loc);
6676                 } else {
6677                         /* Skip POS in ${var:POS:LEN} */
6678                         len = orig_len;
6679                         while (*loc && *loc != ':') {
6680                                 loc++;
6681                         }
6682                         if (*loc++ == ':') {
6683                                 len = ash_arith(loc);
6684                         }
6685                 }
6686 #  undef ash_arith
6687
6688                 if (pos < 0) {
6689                         /* ${VAR:$((-n)):l} starts n chars from the end */
6690                         pos = orig_len + pos;
6691                 }
6692                 if ((unsigned)pos >= orig_len) {
6693                         /* apart from obvious ${VAR:999999:l},
6694                          * covers ${VAR:$((-9999999)):l} - result is ""
6695                          * (bash compat)
6696                          */
6697                         pos = 0;
6698                         len = 0;
6699                 }
6700                 if (len < 0) {
6701                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6702                         len = (orig_len - pos) + len;
6703                 }
6704                 if ((unsigned)len > (orig_len - pos))
6705                         len = orig_len - pos;
6706
6707                 for (str = startp; pos; str++, pos--) {
6708                         if (quotes && (unsigned char)*str == CTLESC)
6709                                 str++;
6710                 }
6711                 for (loc = startp; len; len--) {
6712                         if (quotes && (unsigned char)*str == CTLESC)
6713                                 *loc++ = *str++;
6714                         *loc++ = *str++;
6715                 }
6716                 *loc = '\0';
6717                 amount = loc - expdest;
6718                 STADJUST(amount, expdest);
6719                 return loc;
6720         }
6721 #endif /* BASH_SUBSTR */
6722         }
6723
6724         resetloc = expdest - (char *)stackblock();
6725
6726 #if BASH_PATTERN_SUBST
6727         /* We'll comeback here if we grow the stack while handling
6728          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6729          * stack will need rebasing, and we'll need to remove our work
6730          * areas each time
6731          */
6732  restart:
6733 #endif
6734
6735         amount = expdest - ((char *)stackblock() + resetloc);
6736         STADJUST(-amount, expdest);
6737         startp = (char *)stackblock() + startloc;
6738
6739         rmesc = startp;
6740         rmescend = (char *)stackblock() + strloc;
6741         if (quotes) {
6742                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6743                 if (rmesc != startp) {
6744                         rmescend = expdest;
6745                         startp = (char *)stackblock() + startloc;
6746                 }
6747         }
6748         rmescend--;
6749         str = (char *)stackblock() + strloc;
6750         /*
6751          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6752          * The result is a_\_z_c (not a\_\_z_c)!
6753          *
6754          * The search pattern and replace string treat backslashes differently!
6755          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6756          * and string.  It's only used on the first call.
6757          */
6758         preglob(str, IF_BASH_PATTERN_SUBST(
6759                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6760                         RMESCAPE_SLASH : ) 0);
6761
6762 #if BASH_PATTERN_SUBST
6763         workloc = expdest - (char *)stackblock();
6764         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6765                 int len;
6766                 char *idx, *end;
6767
6768                 if (!repl) {
6769                         repl = strchr(str, CTLESC);
6770                         if (repl)
6771                                 *repl++ = '\0';
6772                         else
6773                                 repl = nullstr;
6774                 }
6775                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6776
6777                 /* If there's no pattern to match, return the expansion unmolested */
6778                 if (str[0] == '\0')
6779                         return NULL;
6780
6781                 len = 0;
6782                 idx = startp;
6783                 end = str - 1;
6784                 while (idx < end) {
6785  try_to_match:
6786                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6787                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6788                         if (!loc) {
6789                                 /* No match, advance */
6790                                 char *restart_detect = stackblock();
6791  skip_matching:
6792                                 STPUTC(*idx, expdest);
6793                                 if (quotes && (unsigned char)*idx == CTLESC) {
6794                                         idx++;
6795                                         len++;
6796                                         STPUTC(*idx, expdest);
6797                                 }
6798                                 if (stackblock() != restart_detect)
6799                                         goto restart;
6800                                 idx++;
6801                                 len++;
6802                                 rmesc++;
6803                                 /* continue; - prone to quadratic behavior, smarter code: */
6804                                 if (idx >= end)
6805                                         break;
6806                                 if (str[0] == '*') {
6807                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6808                                          * it would never match "ong_string" etc, no point in trying.
6809                                          */
6810                                         goto skip_matching;
6811                                 }
6812                                 goto try_to_match;
6813                         }
6814
6815                         if (subtype == VSREPLACEALL) {
6816                                 while (idx < loc) {
6817                                         if (quotes && (unsigned char)*idx == CTLESC)
6818                                                 idx++;
6819                                         idx++;
6820                                         rmesc++;
6821                                 }
6822                         } else {
6823                                 idx = loc;
6824                         }
6825
6826                         //bb_error_msg("repl:'%s'", repl);
6827                         for (loc = (char*)repl; *loc; loc++) {
6828                                 char *restart_detect = stackblock();
6829                                 if (quotes && *loc == '\\') {
6830                                         STPUTC(CTLESC, expdest);
6831                                         len++;
6832                                 }
6833                                 STPUTC(*loc, expdest);
6834                                 if (stackblock() != restart_detect)
6835                                         goto restart;
6836                                 len++;
6837                         }
6838
6839                         if (subtype == VSREPLACE) {
6840                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6841                                 while (*idx) {
6842                                         char *restart_detect = stackblock();
6843                                         STPUTC(*idx, expdest);
6844                                         if (stackblock() != restart_detect)
6845                                                 goto restart;
6846                                         len++;
6847                                         idx++;
6848                                 }
6849                                 break;
6850                         }
6851                 }
6852
6853                 /* We've put the replaced text into a buffer at workloc, now
6854                  * move it to the right place and adjust the stack.
6855                  */
6856                 STPUTC('\0', expdest);
6857                 startp = (char *)stackblock() + startloc;
6858                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6859                 //bb_error_msg("startp:'%s'", startp);
6860                 amount = expdest - (startp + len);
6861                 STADJUST(-amount, expdest);
6862                 return startp;
6863         }
6864 #endif /* BASH_PATTERN_SUBST */
6865
6866         subtype -= VSTRIMRIGHT;
6867 #if DEBUG
6868         if (subtype < 0 || subtype > 7)
6869                 abort();
6870 #endif
6871         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6872         zero = subtype >> 1;
6873         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6874         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6875
6876         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6877         if (loc) {
6878                 if (zero) {
6879                         memmove(startp, loc, str - loc);
6880                         loc = startp + (str - loc) - 1;
6881                 }
6882                 *loc = '\0';
6883                 amount = loc - expdest;
6884                 STADJUST(amount, expdest);
6885         }
6886         return loc;
6887 }
6888
6889 /*
6890  * Add the value of a specialized variable to the stack string.
6891  * name parameter (examples):
6892  * ash -c 'echo $1'      name:'1='
6893  * ash -c 'echo $qwe'    name:'qwe='
6894  * ash -c 'echo $$'      name:'$='
6895  * ash -c 'echo ${$}'    name:'$='
6896  * ash -c 'echo ${$##q}' name:'$=q'
6897  * ash -c 'echo ${#$}'   name:'$='
6898  * note: examples with bad shell syntax:
6899  * ash -c 'echo ${#$1}'  name:'$=1'
6900  * ash -c 'echo ${#1#}'  name:'1=#'
6901  */
6902 static NOINLINE ssize_t
6903 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6904 {
6905         const char *p;
6906         int num;
6907         int i;
6908         ssize_t len = 0;
6909         int sep;
6910         int quoted = *quotedp;
6911         int subtype = varflags & VSTYPE;
6912         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6913         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6914         int syntax;
6915
6916         sep = (flags & EXP_FULL) << CHAR_BIT;
6917         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6918
6919         switch (*name) {
6920         case '$':
6921                 num = rootpid;
6922                 goto numvar;
6923         case '?':
6924                 num = exitstatus;
6925                 goto numvar;
6926         case '#':
6927                 num = shellparam.nparam;
6928                 goto numvar;
6929         case '!':
6930                 num = backgndpid;
6931                 if (num == 0)
6932                         return -1;
6933  numvar:
6934                 len = cvtnum(num);
6935                 goto check_1char_name;
6936         case '-':
6937                 expdest = makestrspace(NOPTS, expdest);
6938                 for (i = NOPTS - 1; i >= 0; i--) {
6939                         if (optlist[i]) {
6940                                 USTPUTC(optletters(i), expdest);
6941                                 len++;
6942                         }
6943                 }
6944  check_1char_name:
6945 #if 0
6946                 /* handles cases similar to ${#$1} */
6947                 if (name[2] != '\0')
6948                         raise_error_syntax("bad substitution");
6949 #endif
6950                 break;
6951         case '@':
6952                 if (quoted && sep)
6953                         goto param;
6954                 /* fall through */
6955         case '*': {
6956                 char **ap;
6957                 char sepc;
6958
6959                 if (quoted)
6960                         sep = 0;
6961                 sep |= ifsset() ? ifsval()[0] : ' ';
6962  param:
6963                 sepc = sep;
6964                 *quotedp = !sepc;
6965                 ap = shellparam.p;
6966                 if (!ap)
6967                         return -1;
6968                 while ((p = *ap++) != NULL) {
6969                         len += strtodest(p, syntax, quotes);
6970
6971                         if (*ap && sep) {
6972                                 len++;
6973                                 memtodest(&sepc, 1, syntax, quotes);
6974                         }
6975                 }
6976                 break;
6977         } /* case '*' */
6978         case '0':
6979         case '1':
6980         case '2':
6981         case '3':
6982         case '4':
6983         case '5':
6984         case '6':
6985         case '7':
6986         case '8':
6987         case '9':
6988                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6989                 if (num < 0 || num > shellparam.nparam)
6990                         return -1;
6991                 p = num ? shellparam.p[num - 1] : arg0;
6992                 goto value;
6993         default:
6994                 /* NB: name has form "VAR=..." */
6995
6996                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6997                  * which should be considered before we check variables. */
6998                 if (var_str_list) {
6999                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
7000                         p = NULL;
7001                         do {
7002                                 char *str, *eq;
7003                                 str = var_str_list->text;
7004                                 eq = strchr(str, '=');
7005                                 if (!eq) /* stop at first non-assignment */
7006                                         break;
7007                                 eq++;
7008                                 if (name_len == (unsigned)(eq - str)
7009                                  && strncmp(str, name, name_len) == 0
7010                                 ) {
7011                                         p = eq;
7012                                         /* goto value; - WRONG! */
7013                                         /* think "A=1 A=2 B=$A" */
7014                                 }
7015                                 var_str_list = var_str_list->next;
7016                         } while (var_str_list);
7017                         if (p)
7018                                 goto value;
7019                 }
7020                 p = lookupvar(name);
7021  value:
7022                 if (!p)
7023                         return -1;
7024
7025                 len = strtodest(p, syntax, quotes);
7026 #if ENABLE_UNICODE_SUPPORT
7027                 if (subtype == VSLENGTH && len > 0) {
7028                         reinit_unicode_for_ash();
7029                         if (unicode_status == UNICODE_ON) {
7030                                 STADJUST(-len, expdest);
7031                                 discard = 0;
7032                                 len = unicode_strlen(p);
7033                         }
7034                 }
7035 #endif
7036                 break;
7037         }
7038
7039         if (discard)
7040                 STADJUST(-len, expdest);
7041         return len;
7042 }
7043
7044 /*
7045  * Expand a variable, and return a pointer to the next character in the
7046  * input string.
7047  */
7048 static char *
7049 evalvar(char *p, int flag, struct strlist *var_str_list)
7050 {
7051         char varflags;
7052         char subtype;
7053         int quoted;
7054         char easy;
7055         char *var;
7056         int patloc;
7057         int startloc;
7058         ssize_t varlen;
7059
7060         varflags = (unsigned char) *p++;
7061         subtype = varflags & VSTYPE;
7062
7063         if (!subtype)
7064                 raise_error_syntax("bad substitution");
7065
7066         quoted = flag & EXP_QUOTED;
7067         var = p;
7068         easy = (!quoted || (*var == '@' && shellparam.nparam));
7069         startloc = expdest - (char *)stackblock();
7070         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7071
7072  again:
7073         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7074         if (varflags & VSNUL)
7075                 varlen--;
7076
7077         if (subtype == VSPLUS) {
7078                 varlen = -1 - varlen;
7079                 goto vsplus;
7080         }
7081
7082         if (subtype == VSMINUS) {
7083  vsplus:
7084                 if (varlen < 0) {
7085                         argstr(
7086                                 p,
7087                                 flag | EXP_TILDE | EXP_WORD,
7088                                 var_str_list
7089                         );
7090                         goto end;
7091                 }
7092                 goto record;
7093         }
7094
7095         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7096                 if (varlen >= 0)
7097                         goto record;
7098
7099                 subevalvar(p, var, 0, subtype, startloc, varflags,
7100                            flag & ~QUOTES_ESC, var_str_list);
7101                 varflags &= ~VSNUL;
7102                 /*
7103                  * Remove any recorded regions beyond
7104                  * start of variable
7105                  */
7106                 removerecordregions(startloc);
7107                 goto again;
7108         }
7109
7110         if (varlen < 0 && uflag)
7111                 varunset(p, var, 0, 0);
7112
7113         if (subtype == VSLENGTH) {
7114                 cvtnum(varlen > 0 ? varlen : 0);
7115                 goto record;
7116         }
7117
7118         if (subtype == VSNORMAL) {
7119  record:
7120                 if (!easy)
7121                         goto end;
7122                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7123                 goto end;
7124         }
7125
7126 #if DEBUG
7127         switch (subtype) {
7128         case VSTRIMLEFT:
7129         case VSTRIMLEFTMAX:
7130         case VSTRIMRIGHT:
7131         case VSTRIMRIGHTMAX:
7132 #if BASH_SUBSTR
7133         case VSSUBSTR:
7134 #endif
7135 #if BASH_PATTERN_SUBST
7136         case VSREPLACE:
7137         case VSREPLACEALL:
7138 #endif
7139                 break;
7140         default:
7141                 abort();
7142         }
7143 #endif
7144
7145         if (varlen >= 0) {
7146                 /*
7147                  * Terminate the string and start recording the pattern
7148                  * right after it
7149                  */
7150                 STPUTC('\0', expdest);
7151                 patloc = expdest - (char *)stackblock();
7152                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7153                                 startloc, varflags, flag, var_str_list)) {
7154                         int amount = expdest - (
7155                                 (char *)stackblock() + patloc - 1
7156                         );
7157                         STADJUST(-amount, expdest);
7158                 }
7159                 /* Remove any recorded regions beyond start of variable */
7160                 removerecordregions(startloc);
7161                 goto record;
7162         }
7163
7164  end:
7165         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7166                 int nesting = 1;
7167                 for (;;) {
7168                         unsigned char c = *p++;
7169                         if (c == CTLESC)
7170                                 p++;
7171                         else if (c == CTLBACKQ) {
7172                                 if (varlen >= 0)
7173                                         argbackq = argbackq->next;
7174                         } else if (c == CTLVAR) {
7175                                 if ((*p++ & VSTYPE) != VSNORMAL)
7176                                         nesting++;
7177                         } else if (c == CTLENDVAR) {
7178                                 if (--nesting == 0)
7179                                         break;
7180                         }
7181                 }
7182         }
7183         return p;
7184 }
7185
7186 /*
7187  * Add a file name to the list.
7188  */
7189 static void
7190 addfname(const char *name)
7191 {
7192         struct strlist *sp;
7193
7194         sp = stzalloc(sizeof(*sp));
7195         sp->text = sstrdup(name);
7196         *exparg.lastp = sp;
7197         exparg.lastp = &sp->next;
7198 }
7199
7200 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7201 static int
7202 hasmeta(const char *p)
7203 {
7204         static const char chars[] ALIGN1 = {
7205                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7206         };
7207
7208         for (;;) {
7209                 p = strpbrk(p, chars);
7210                 if (!p)
7211                         break;
7212                 switch ((unsigned char) *p) {
7213                 case CTLQUOTEMARK:
7214                         for (;;) {
7215                                 p++;
7216                                 if (*p == CTLQUOTEMARK)
7217                                         break;
7218                                 if (*p == CTLESC)
7219                                         p++;
7220                                 if (*p == '\0') /* huh? */
7221                                         return 0;
7222                         }
7223                         break;
7224                 case '\\':
7225                 case CTLESC:
7226                         p++;
7227                         if (*p == '\0')
7228                                 return 0;
7229                         break;
7230                 case '[':
7231                         if (!strchr(p + 1, ']')) {
7232                                 /* It's not a properly closed [] pattern,
7233                                  * but other metas may follow. Continue checking.
7234                                  * my[file* _is_ globbed by bash
7235                                  * and matches filenames like "my[file1".
7236                                  */
7237                                 break;
7238                         }
7239                         /* fallthrough */
7240                 default:
7241                 /* case '*': */
7242                 /* case '?': */
7243                         return 1;
7244                 }
7245                 p++;
7246         }
7247
7248         return 0;
7249 }
7250
7251 /* If we want to use glob() from libc... */
7252 #if !ENABLE_ASH_INTERNAL_GLOB
7253
7254 /* Add the result of glob() to the list */
7255 static void
7256 addglob(const glob_t *pglob)
7257 {
7258         char **p = pglob->gl_pathv;
7259
7260         do {
7261                 addfname(*p);
7262         } while (*++p);
7263 }
7264 static void
7265 expandmeta(struct strlist *str /*, int flag*/)
7266 {
7267         /* TODO - EXP_REDIR */
7268
7269         while (str) {
7270                 char *p;
7271                 glob_t pglob;
7272                 int i;
7273
7274                 if (fflag)
7275                         goto nometa;
7276
7277                 if (!hasmeta(str->text))
7278                         goto nometa;
7279
7280                 INT_OFF;
7281                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7282 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7283 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7284 //
7285 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7286 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7287 // Which means you need to unescape the string, right? Not so fast:
7288 // if there _is_ a file named "file\?" (with backslash), it is returned
7289 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7290 // You DON'T KNOW by looking at the result whether you need to unescape it.
7291 //
7292 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7293 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7294 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7295 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7296 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7297 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7298                 i = glob(p, 0, NULL, &pglob);
7299                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7300                 if (p != str->text)
7301                         free(p);
7302                 switch (i) {
7303                 case 0:
7304 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7305                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7306                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7307                                 goto nometa2;
7308 #endif
7309                         addglob(&pglob);
7310                         globfree(&pglob);
7311                         INT_ON;
7312                         break;
7313                 case GLOB_NOMATCH:
7314  //nometa2:
7315                         globfree(&pglob);
7316                         INT_ON;
7317  nometa:
7318                         *exparg.lastp = str;
7319                         rmescapes(str->text, 0);
7320                         exparg.lastp = &str->next;
7321                         break;
7322                 default:        /* GLOB_NOSPACE */
7323                         globfree(&pglob);
7324                         INT_ON;
7325                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7326                 }
7327                 str = str->next;
7328         }
7329 }
7330
7331 #else
7332 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7333
7334 /*
7335  * Do metacharacter (i.e. *, ?, [...]) expansion.
7336  */
7337 static void
7338 expmeta(char *expdir, char *enddir, char *name)
7339 {
7340         char *p;
7341         const char *cp;
7342         char *start;
7343         char *endname;
7344         int metaflag;
7345         struct stat statb;
7346         DIR *dirp;
7347         struct dirent *dp;
7348         int atend;
7349         int matchdot;
7350         int esc;
7351
7352         metaflag = 0;
7353         start = name;
7354         for (p = name; esc = 0, *p; p += esc + 1) {
7355                 if (*p == '*' || *p == '?')
7356                         metaflag = 1;
7357                 else if (*p == '[') {
7358                         char *q = p + 1;
7359                         if (*q == '!')
7360                                 q++;
7361                         for (;;) {
7362                                 if (*q == '\\')
7363                                         q++;
7364                                 if (*q == '/' || *q == '\0')
7365                                         break;
7366                                 if (*++q == ']') {
7367                                         metaflag = 1;
7368                                         break;
7369                                 }
7370                         }
7371                 } else {
7372                         if (*p == '\\')
7373                                 esc++;
7374                         if (p[esc] == '/') {
7375                                 if (metaflag)
7376                                         break;
7377                                 start = p + esc + 1;
7378                         }
7379                 }
7380         }
7381         if (metaflag == 0) {    /* we've reached the end of the file name */
7382                 if (enddir != expdir)
7383                         metaflag++;
7384                 p = name;
7385                 do {
7386                         if (*p == '\\')
7387                                 p++;
7388                         *enddir++ = *p;
7389                 } while (*p++);
7390                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7391                         addfname(expdir);
7392                 return;
7393         }
7394         endname = p;
7395         if (name < start) {
7396                 p = name;
7397                 do {
7398                         if (*p == '\\')
7399                                 p++;
7400                         *enddir++ = *p++;
7401                 } while (p < start);
7402         }
7403         if (enddir == expdir) {
7404                 cp = ".";
7405         } else if (enddir == expdir + 1 && *expdir == '/') {
7406                 cp = "/";
7407         } else {
7408                 cp = expdir;
7409                 enddir[-1] = '\0';
7410         }
7411         dirp = opendir(cp);
7412         if (dirp == NULL)
7413                 return;
7414         if (enddir != expdir)
7415                 enddir[-1] = '/';
7416         if (*endname == 0) {
7417                 atend = 1;
7418         } else {
7419                 atend = 0;
7420                 *endname = '\0';
7421                 endname += esc + 1;
7422         }
7423         matchdot = 0;
7424         p = start;
7425         if (*p == '\\')
7426                 p++;
7427         if (*p == '.')
7428                 matchdot++;
7429         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7430                 if (dp->d_name[0] == '.' && !matchdot)
7431                         continue;
7432                 if (pmatch(start, dp->d_name)) {
7433                         if (atend) {
7434                                 strcpy(enddir, dp->d_name);
7435                                 addfname(expdir);
7436                         } else {
7437                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7438                                         continue;
7439                                 p[-1] = '/';
7440                                 expmeta(expdir, p, endname);
7441                         }
7442                 }
7443         }
7444         closedir(dirp);
7445         if (!atend)
7446                 endname[-esc - 1] = esc ? '\\' : '/';
7447 }
7448
7449 static struct strlist *
7450 msort(struct strlist *list, int len)
7451 {
7452         struct strlist *p, *q = NULL;
7453         struct strlist **lpp;
7454         int half;
7455         int n;
7456
7457         if (len <= 1)
7458                 return list;
7459         half = len >> 1;
7460         p = list;
7461         for (n = half; --n >= 0;) {
7462                 q = p;
7463                 p = p->next;
7464         }
7465         q->next = NULL;                 /* terminate first half of list */
7466         q = msort(list, half);          /* sort first half of list */
7467         p = msort(p, len - half);               /* sort second half */
7468         lpp = &list;
7469         for (;;) {
7470 #if ENABLE_LOCALE_SUPPORT
7471                 if (strcoll(p->text, q->text) < 0)
7472 #else
7473                 if (strcmp(p->text, q->text) < 0)
7474 #endif
7475                                                 {
7476                         *lpp = p;
7477                         lpp = &p->next;
7478                         p = *lpp;
7479                         if (p == NULL) {
7480                                 *lpp = q;
7481                                 break;
7482                         }
7483                 } else {
7484                         *lpp = q;
7485                         lpp = &q->next;
7486                         q = *lpp;
7487                         if (q == NULL) {
7488                                 *lpp = p;
7489                                 break;
7490                         }
7491                 }
7492         }
7493         return list;
7494 }
7495
7496 /*
7497  * Sort the results of file name expansion.  It calculates the number of
7498  * strings to sort and then calls msort (short for merge sort) to do the
7499  * work.
7500  */
7501 static struct strlist *
7502 expsort(struct strlist *str)
7503 {
7504         int len;
7505         struct strlist *sp;
7506
7507         len = 0;
7508         for (sp = str; sp; sp = sp->next)
7509                 len++;
7510         return msort(str, len);
7511 }
7512
7513 static void
7514 expandmeta(struct strlist *str /*, int flag*/)
7515 {
7516         /* TODO - EXP_REDIR */
7517
7518         while (str) {
7519                 char *expdir;
7520                 struct strlist **savelastp;
7521                 struct strlist *sp;
7522                 char *p;
7523
7524                 if (fflag)
7525                         goto nometa;
7526                 if (!hasmeta(str->text))
7527                         goto nometa;
7528                 savelastp = exparg.lastp;
7529
7530                 INT_OFF;
7531                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7532                 {
7533                         int i = strlen(str->text);
7534 //BUGGY estimation of how long expanded name can be
7535                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7536                 }
7537                 expmeta(expdir, expdir, p);
7538                 free(expdir);
7539                 if (p != str->text)
7540                         free(p);
7541                 INT_ON;
7542                 if (exparg.lastp == savelastp) {
7543                         /*
7544                          * no matches
7545                          */
7546  nometa:
7547                         *exparg.lastp = str;
7548                         rmescapes(str->text, 0);
7549                         exparg.lastp = &str->next;
7550                 } else {
7551                         *exparg.lastp = NULL;
7552                         *savelastp = sp = expsort(*savelastp);
7553                         while (sp->next != NULL)
7554                                 sp = sp->next;
7555                         exparg.lastp = &sp->next;
7556                 }
7557                 str = str->next;
7558         }
7559 }
7560 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7561
7562 /*
7563  * Perform variable substitution and command substitution on an argument,
7564  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7565  * perform splitting and file name expansion.  When arglist is NULL, perform
7566  * here document expansion.
7567  */
7568 static void
7569 expandarg(union node *arg, struct arglist *arglist, int flag)
7570 {
7571         struct strlist *sp;
7572         char *p;
7573
7574         argbackq = arg->narg.backquote;
7575         STARTSTACKSTR(expdest);
7576         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7577         argstr(arg->narg.text, flag,
7578                         /* var_str_list: */ arglist ? arglist->list : NULL);
7579         p = _STPUTC('\0', expdest);
7580         expdest = p - 1;
7581         if (arglist == NULL) {
7582                 /* here document expanded */
7583                 goto out;
7584         }
7585         p = grabstackstr(p);
7586         TRACE(("expandarg: p:'%s'\n", p));
7587         exparg.lastp = &exparg.list;
7588         /*
7589          * TODO - EXP_REDIR
7590          */
7591         if (flag & EXP_FULL) {
7592                 ifsbreakup(p, &exparg);
7593                 *exparg.lastp = NULL;
7594                 exparg.lastp = &exparg.list;
7595                 expandmeta(exparg.list /*, flag*/);
7596         } else {
7597                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7598                         rmescapes(p, 0);
7599                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7600                 }
7601                 sp = stzalloc(sizeof(*sp));
7602                 sp->text = p;
7603                 *exparg.lastp = sp;
7604                 exparg.lastp = &sp->next;
7605         }
7606         *exparg.lastp = NULL;
7607         if (exparg.list) {
7608                 *arglist->lastp = exparg.list;
7609                 arglist->lastp = exparg.lastp;
7610         }
7611
7612  out:
7613         ifsfree();
7614 }
7615
7616 /*
7617  * Expand shell variables and backquotes inside a here document.
7618  */
7619 static void
7620 expandhere(union node *arg, int fd)
7621 {
7622         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7623         full_write(fd, stackblock(), expdest - (char *)stackblock());
7624 }
7625
7626 /*
7627  * Returns true if the pattern matches the string.
7628  */
7629 static int
7630 patmatch(char *pattern, const char *string)
7631 {
7632         char *p = preglob(pattern, 0);
7633         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7634         return pmatch(p, string);
7635 }
7636
7637 /*
7638  * See if a pattern matches in a case statement.
7639  */
7640 static int
7641 casematch(union node *pattern, char *val)
7642 {
7643         struct stackmark smark;
7644         int result;
7645
7646         setstackmark(&smark);
7647         argbackq = pattern->narg.backquote;
7648         STARTSTACKSTR(expdest);
7649         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7650                         /* var_str_list: */ NULL);
7651         STACKSTRNUL(expdest);
7652         ifsfree();
7653         result = patmatch(stackblock(), val);
7654         popstackmark(&smark);
7655         return result;
7656 }
7657
7658
7659 /* ============ find_command */
7660
7661 struct builtincmd {
7662         const char *name;
7663         int (*builtin)(int, char **) FAST_FUNC;
7664         /* unsigned flags; */
7665 };
7666 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7667 /* "regular" builtins always take precedence over commands,
7668  * regardless of PATH=....%builtin... position */
7669 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7670 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7671
7672 struct cmdentry {
7673         smallint cmdtype;       /* CMDxxx */
7674         union param {
7675                 int index;
7676                 /* index >= 0 for commands without path (slashes) */
7677                 /* (TODO: what exactly does the value mean? PATH position?) */
7678                 /* index == -1 for commands with slashes */
7679                 /* index == (-2 - applet_no) for NOFORK applets */
7680                 const struct builtincmd *cmd;
7681                 struct funcnode *func;
7682         } u;
7683 };
7684 /* values of cmdtype */
7685 #define CMDUNKNOWN      -1      /* no entry in table for command */
7686 #define CMDNORMAL       0       /* command is an executable program */
7687 #define CMDFUNCTION     1       /* command is a shell function */
7688 #define CMDBUILTIN      2       /* command is a shell builtin */
7689
7690 /* action to find_command() */
7691 #define DO_ERR          0x01    /* prints errors */
7692 #define DO_ABS          0x02    /* checks absolute paths */
7693 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7694 #define DO_ALTPATH      0x08    /* using alternate path */
7695 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7696
7697 static void find_command(char *, struct cmdentry *, int, const char *);
7698
7699
7700 /* ============ Hashing commands */
7701
7702 /*
7703  * When commands are first encountered, they are entered in a hash table.
7704  * This ensures that a full path search will not have to be done for them
7705  * on each invocation.
7706  *
7707  * We should investigate converting to a linear search, even though that
7708  * would make the command name "hash" a misnomer.
7709  */
7710
7711 struct tblentry {
7712         struct tblentry *next;  /* next entry in hash chain */
7713         union param param;      /* definition of builtin function */
7714         smallint cmdtype;       /* CMDxxx */
7715         char rehash;            /* if set, cd done since entry created */
7716         char cmdname[1];        /* name of command */
7717 };
7718
7719 static struct tblentry **cmdtable;
7720 #define INIT_G_cmdtable() do { \
7721         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7722 } while (0)
7723
7724 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7725
7726
7727 static void
7728 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7729 {
7730 #if ENABLE_FEATURE_SH_STANDALONE
7731         if (applet_no >= 0) {
7732                 if (APPLET_IS_NOEXEC(applet_no)) {
7733                         clearenv();
7734                         while (*envp)
7735                                 putenv(*envp++);
7736                         run_applet_no_and_exit(applet_no, cmd, argv);
7737                 }
7738                 /* re-exec ourselves with the new arguments */
7739                 execve(bb_busybox_exec_path, argv, envp);
7740                 /* If they called chroot or otherwise made the binary no longer
7741                  * executable, fall through */
7742         }
7743 #endif
7744
7745  repeat:
7746 #ifdef SYSV
7747         do {
7748                 execve(cmd, argv, envp);
7749         } while (errno == EINTR);
7750 #else
7751         execve(cmd, argv, envp);
7752 #endif
7753         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7754                 /* Run "cmd" as a shell script:
7755                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7756                  * "If the execve() function fails with ENOEXEC, the shell
7757                  * shall execute a command equivalent to having a shell invoked
7758                  * with the command name as its first operand,
7759                  * with any remaining arguments passed to the new shell"
7760                  *
7761                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7762                  * just call ourselves.
7763                  *
7764                  * Note that bash reads ~80 chars of the file, and if it sees
7765                  * a zero byte before it sees newline, it doesn't try to
7766                  * interpret it, but fails with "cannot execute binary file"
7767                  * message and exit code 126. For one, this prevents attempts
7768                  * to interpret foreign ELF binaries as shell scripts.
7769                  */
7770                 argv[0] = cmd;
7771                 cmd = (char*) bb_busybox_exec_path;
7772                 /* NB: this is only possible because all callers of shellexec()
7773                  * ensure that the argv[-1] slot exists!
7774                  */
7775                 argv--;
7776                 argv[0] = (char*) "ash";
7777                 goto repeat;
7778         }
7779 }
7780
7781 /*
7782  * Exec a program.  Never returns.  If you change this routine, you may
7783  * have to change the find_command routine as well.
7784  * argv[-1] must exist and be writable! See tryexec() for why.
7785  */
7786 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7787 static void shellexec(char *prog, char **argv, const char *path, int idx)
7788 {
7789         char *cmdname;
7790         int e;
7791         char **envp;
7792         int exerrno;
7793         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7794
7795         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7796         if (strchr(prog, '/') != NULL
7797 #if ENABLE_FEATURE_SH_STANDALONE
7798          || (applet_no = find_applet_by_name(prog)) >= 0
7799 #endif
7800         ) {
7801                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7802                 if (applet_no >= 0) {
7803                         /* We tried execing ourself, but it didn't work.
7804                          * Maybe /proc/self/exe doesn't exist?
7805                          * Try $PATH search.
7806                          */
7807                         goto try_PATH;
7808                 }
7809                 e = errno;
7810         } else {
7811  try_PATH:
7812                 e = ENOENT;
7813                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7814                         if (--idx < 0 && pathopt == NULL) {
7815                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7816                                 if (errno != ENOENT && errno != ENOTDIR)
7817                                         e = errno;
7818                         }
7819                         stunalloc(cmdname);
7820                 }
7821         }
7822
7823         /* Map to POSIX errors */
7824         switch (e) {
7825         case EACCES:
7826                 exerrno = 126;
7827                 break;
7828         case ENOENT:
7829                 exerrno = 127;
7830                 break;
7831         default:
7832                 exerrno = 2;
7833                 break;
7834         }
7835         exitstatus = exerrno;
7836         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7837                 prog, e, suppress_int));
7838         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7839         /* NOTREACHED */
7840 }
7841
7842 static void
7843 printentry(struct tblentry *cmdp)
7844 {
7845         int idx;
7846         const char *path;
7847         char *name;
7848
7849         idx = cmdp->param.index;
7850         path = pathval();
7851         do {
7852                 name = path_advance(&path, cmdp->cmdname);
7853                 stunalloc(name);
7854         } while (--idx >= 0);
7855         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7856 }
7857
7858 /*
7859  * Clear out command entries.  The argument specifies the first entry in
7860  * PATH which has changed.
7861  */
7862 static void
7863 clearcmdentry(int firstchange)
7864 {
7865         struct tblentry **tblp;
7866         struct tblentry **pp;
7867         struct tblentry *cmdp;
7868
7869         INT_OFF;
7870         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7871                 pp = tblp;
7872                 while ((cmdp = *pp) != NULL) {
7873                         if ((cmdp->cmdtype == CMDNORMAL &&
7874                              cmdp->param.index >= firstchange)
7875                          || (cmdp->cmdtype == CMDBUILTIN &&
7876                              builtinloc >= firstchange)
7877                         ) {
7878                                 *pp = cmdp->next;
7879                                 free(cmdp);
7880                         } else {
7881                                 pp = &cmdp->next;
7882                         }
7883                 }
7884         }
7885         INT_ON;
7886 }
7887
7888 /*
7889  * Locate a command in the command hash table.  If "add" is nonzero,
7890  * add the command to the table if it is not already present.  The
7891  * variable "lastcmdentry" is set to point to the address of the link
7892  * pointing to the entry, so that delete_cmd_entry can delete the
7893  * entry.
7894  *
7895  * Interrupts must be off if called with add != 0.
7896  */
7897 static struct tblentry **lastcmdentry;
7898
7899 static struct tblentry *
7900 cmdlookup(const char *name, int add)
7901 {
7902         unsigned int hashval;
7903         const char *p;
7904         struct tblentry *cmdp;
7905         struct tblentry **pp;
7906
7907         p = name;
7908         hashval = (unsigned char)*p << 4;
7909         while (*p)
7910                 hashval += (unsigned char)*p++;
7911         hashval &= 0x7FFF;
7912         pp = &cmdtable[hashval % CMDTABLESIZE];
7913         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7914                 if (strcmp(cmdp->cmdname, name) == 0)
7915                         break;
7916                 pp = &cmdp->next;
7917         }
7918         if (add && cmdp == NULL) {
7919                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7920                                 + strlen(name)
7921                                 /* + 1 - already done because
7922                                  * tblentry::cmdname is char[1] */);
7923                 /*cmdp->next = NULL; - ckzalloc did it */
7924                 cmdp->cmdtype = CMDUNKNOWN;
7925                 strcpy(cmdp->cmdname, name);
7926         }
7927         lastcmdentry = pp;
7928         return cmdp;
7929 }
7930
7931 /*
7932  * Delete the command entry returned on the last lookup.
7933  */
7934 static void
7935 delete_cmd_entry(void)
7936 {
7937         struct tblentry *cmdp;
7938
7939         INT_OFF;
7940         cmdp = *lastcmdentry;
7941         *lastcmdentry = cmdp->next;
7942         if (cmdp->cmdtype == CMDFUNCTION)
7943                 freefunc(cmdp->param.func);
7944         free(cmdp);
7945         INT_ON;
7946 }
7947
7948 /*
7949  * Add a new command entry, replacing any existing command entry for
7950  * the same name - except special builtins.
7951  */
7952 static void
7953 addcmdentry(char *name, struct cmdentry *entry)
7954 {
7955         struct tblentry *cmdp;
7956
7957         cmdp = cmdlookup(name, 1);
7958         if (cmdp->cmdtype == CMDFUNCTION) {
7959                 freefunc(cmdp->param.func);
7960         }
7961         cmdp->cmdtype = entry->cmdtype;
7962         cmdp->param = entry->u;
7963         cmdp->rehash = 0;
7964 }
7965
7966 static int FAST_FUNC
7967 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7968 {
7969         struct tblentry **pp;
7970         struct tblentry *cmdp;
7971         int c;
7972         struct cmdentry entry;
7973         char *name;
7974
7975         if (nextopt("r") != '\0') {
7976                 clearcmdentry(0);
7977                 return 0;
7978         }
7979
7980         if (*argptr == NULL) {
7981                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7982                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7983                                 if (cmdp->cmdtype == CMDNORMAL)
7984                                         printentry(cmdp);
7985                         }
7986                 }
7987                 return 0;
7988         }
7989
7990         c = 0;
7991         while ((name = *argptr) != NULL) {
7992                 cmdp = cmdlookup(name, 0);
7993                 if (cmdp != NULL
7994                  && (cmdp->cmdtype == CMDNORMAL
7995                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7996                 ) {
7997                         delete_cmd_entry();
7998                 }
7999                 find_command(name, &entry, DO_ERR, pathval());
8000                 if (entry.cmdtype == CMDUNKNOWN)
8001                         c = 1;
8002                 argptr++;
8003         }
8004         return c;
8005 }
8006
8007 /*
8008  * Called when a cd is done.  Marks all commands so the next time they
8009  * are executed they will be rehashed.
8010  */
8011 static void
8012 hashcd(void)
8013 {
8014         struct tblentry **pp;
8015         struct tblentry *cmdp;
8016
8017         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8018                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8019                         if (cmdp->cmdtype == CMDNORMAL
8020                          || (cmdp->cmdtype == CMDBUILTIN
8021                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8022                              && builtinloc > 0)
8023                         ) {
8024                                 cmdp->rehash = 1;
8025                         }
8026                 }
8027         }
8028 }
8029
8030 /*
8031  * Fix command hash table when PATH changed.
8032  * Called before PATH is changed.  The argument is the new value of PATH;
8033  * pathval() still returns the old value at this point.
8034  * Called with interrupts off.
8035  */
8036 static void FAST_FUNC
8037 changepath(const char *new)
8038 {
8039         const char *old;
8040         int firstchange;
8041         int idx;
8042         int idx_bltin;
8043
8044         old = pathval();
8045         firstchange = 9999;     /* assume no change */
8046         idx = 0;
8047         idx_bltin = -1;
8048         for (;;) {
8049                 if (*old != *new) {
8050                         firstchange = idx;
8051                         if ((*old == '\0' && *new == ':')
8052                          || (*old == ':' && *new == '\0')
8053                         ) {
8054                                 firstchange++;
8055                         }
8056                         old = new;      /* ignore subsequent differences */
8057                 }
8058                 if (*new == '\0')
8059                         break;
8060                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8061                         idx_bltin = idx;
8062                 if (*new == ':')
8063                         idx++;
8064                 new++;
8065                 old++;
8066         }
8067         if (builtinloc < 0 && idx_bltin >= 0)
8068                 builtinloc = idx_bltin;             /* zap builtins */
8069         if (builtinloc >= 0 && idx_bltin < 0)
8070                 firstchange = 0;
8071         clearcmdentry(firstchange);
8072         builtinloc = idx_bltin;
8073 }
8074 enum {
8075         TEOF,
8076         TNL,
8077         TREDIR,
8078         TWORD,
8079         TSEMI,
8080         TBACKGND,
8081         TAND,
8082         TOR,
8083         TPIPE,
8084         TLP,
8085         TRP,
8086         TENDCASE,
8087         TENDBQUOTE,
8088         TNOT,
8089         TCASE,
8090         TDO,
8091         TDONE,
8092         TELIF,
8093         TELSE,
8094         TESAC,
8095         TFI,
8096         TFOR,
8097 #if BASH_FUNCTION
8098         TFUNCTION,
8099 #endif
8100         TIF,
8101         TIN,
8102         TTHEN,
8103         TUNTIL,
8104         TWHILE,
8105         TBEGIN,
8106         TEND
8107 };
8108 typedef smallint token_id_t;
8109
8110 /* Nth bit indicates if token marks the end of a list */
8111 enum {
8112         tokendlist = 0
8113         /*  0 */ | (1u << TEOF)
8114         /*  1 */ | (0u << TNL)
8115         /*  2 */ | (0u << TREDIR)
8116         /*  3 */ | (0u << TWORD)
8117         /*  4 */ | (0u << TSEMI)
8118         /*  5 */ | (0u << TBACKGND)
8119         /*  6 */ | (0u << TAND)
8120         /*  7 */ | (0u << TOR)
8121         /*  8 */ | (0u << TPIPE)
8122         /*  9 */ | (0u << TLP)
8123         /* 10 */ | (1u << TRP)
8124         /* 11 */ | (1u << TENDCASE)
8125         /* 12 */ | (1u << TENDBQUOTE)
8126         /* 13 */ | (0u << TNOT)
8127         /* 14 */ | (0u << TCASE)
8128         /* 15 */ | (1u << TDO)
8129         /* 16 */ | (1u << TDONE)
8130         /* 17 */ | (1u << TELIF)
8131         /* 18 */ | (1u << TELSE)
8132         /* 19 */ | (1u << TESAC)
8133         /* 20 */ | (1u << TFI)
8134         /* 21 */ | (0u << TFOR)
8135 #if BASH_FUNCTION
8136         /* 22 */ | (0u << TFUNCTION)
8137 #endif
8138         /* 23 */ | (0u << TIF)
8139         /* 24 */ | (0u << TIN)
8140         /* 25 */ | (1u << TTHEN)
8141         /* 26 */ | (0u << TUNTIL)
8142         /* 27 */ | (0u << TWHILE)
8143         /* 28 */ | (0u << TBEGIN)
8144         /* 29 */ | (1u << TEND)
8145         , /* thus far 29 bits used */
8146 };
8147
8148 static const char *const tokname_array[] = {
8149         "end of file",
8150         "newline",
8151         "redirection",
8152         "word",
8153         ";",
8154         "&",
8155         "&&",
8156         "||",
8157         "|",
8158         "(",
8159         ")",
8160         ";;",
8161         "`",
8162 #define KWDOFFSET 13
8163         /* the following are keywords */
8164         "!",
8165         "case",
8166         "do",
8167         "done",
8168         "elif",
8169         "else",
8170         "esac",
8171         "fi",
8172         "for",
8173 #if BASH_FUNCTION
8174         "function",
8175 #endif
8176         "if",
8177         "in",
8178         "then",
8179         "until",
8180         "while",
8181         "{",
8182         "}",
8183 };
8184
8185 /* Wrapper around strcmp for qsort/bsearch/... */
8186 static int
8187 pstrcmp(const void *a, const void *b)
8188 {
8189         return strcmp((char*)a, *(char**)b);
8190 }
8191
8192 static const char *const *
8193 findkwd(const char *s)
8194 {
8195         return bsearch(s, tokname_array + KWDOFFSET,
8196                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8197                         sizeof(tokname_array[0]), pstrcmp);
8198 }
8199
8200 /*
8201  * Locate and print what a word is...
8202  */
8203 static int
8204 describe_command(char *command, const char *path, int describe_command_verbose)
8205 {
8206         struct cmdentry entry;
8207 #if ENABLE_ASH_ALIAS
8208         const struct alias *ap;
8209 #endif
8210
8211         path = path ? path : pathval();
8212
8213         if (describe_command_verbose) {
8214                 out1str(command);
8215         }
8216
8217         /* First look at the keywords */
8218         if (findkwd(command)) {
8219                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8220                 goto out;
8221         }
8222
8223 #if ENABLE_ASH_ALIAS
8224         /* Then look at the aliases */
8225         ap = lookupalias(command, 0);
8226         if (ap != NULL) {
8227                 if (!describe_command_verbose) {
8228                         out1str("alias ");
8229                         printalias(ap);
8230                         return 0;
8231                 }
8232                 out1fmt(" is an alias for %s", ap->val);
8233                 goto out;
8234         }
8235 #endif
8236         /* Brute force */
8237         find_command(command, &entry, DO_ABS, path);
8238
8239         switch (entry.cmdtype) {
8240         case CMDNORMAL: {
8241                 int j = entry.u.index;
8242                 char *p;
8243                 if (j < 0) {
8244                         p = command;
8245                 } else {
8246                         do {
8247                                 p = path_advance(&path, command);
8248                                 stunalloc(p);
8249                         } while (--j >= 0);
8250                 }
8251                 if (describe_command_verbose) {
8252                         out1fmt(" is %s", p);
8253                 } else {
8254                         out1str(p);
8255                 }
8256                 break;
8257         }
8258
8259         case CMDFUNCTION:
8260                 if (describe_command_verbose) {
8261                         out1str(" is a shell function");
8262                 } else {
8263                         out1str(command);
8264                 }
8265                 break;
8266
8267         case CMDBUILTIN:
8268                 if (describe_command_verbose) {
8269                         out1fmt(" is a %sshell builtin",
8270                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8271                                         "special " : nullstr
8272                         );
8273                 } else {
8274                         out1str(command);
8275                 }
8276                 break;
8277
8278         default:
8279                 if (describe_command_verbose) {
8280                         out1str(": not found\n");
8281                 }
8282                 return 127;
8283         }
8284  out:
8285         out1str("\n");
8286         return 0;
8287 }
8288
8289 static int FAST_FUNC
8290 typecmd(int argc UNUSED_PARAM, char **argv)
8291 {
8292         int i = 1;
8293         int err = 0;
8294         int verbose = 1;
8295
8296         /* type -p ... ? (we don't bother checking for 'p') */
8297         if (argv[1] && argv[1][0] == '-') {
8298                 i++;
8299                 verbose = 0;
8300         }
8301         while (argv[i]) {
8302                 err |= describe_command(argv[i++], NULL, verbose);
8303         }
8304         return err;
8305 }
8306
8307 #if ENABLE_ASH_CMDCMD
8308 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8309 static char **
8310 parse_command_args(char **argv, const char **path)
8311 {
8312         char *cp, c;
8313
8314         for (;;) {
8315                 cp = *++argv;
8316                 if (!cp)
8317                         return NULL;
8318                 if (*cp++ != '-')
8319                         break;
8320                 c = *cp++;
8321                 if (!c)
8322                         break;
8323                 if (c == '-' && !*cp) {
8324                         if (!*++argv)
8325                                 return NULL;
8326                         break;
8327                 }
8328                 do {
8329                         switch (c) {
8330                         case 'p':
8331                                 *path = bb_default_path;
8332                                 break;
8333                         default:
8334                                 /* run 'typecmd' for other options */
8335                                 return NULL;
8336                         }
8337                         c = *cp++;
8338                 } while (c);
8339         }
8340         return argv;
8341 }
8342
8343 static int FAST_FUNC
8344 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8345 {
8346         char *cmd;
8347         int c;
8348         enum {
8349                 VERIFY_BRIEF = 1,
8350                 VERIFY_VERBOSE = 2,
8351         } verify = 0;
8352         const char *path = NULL;
8353
8354         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8355          * never reaches this function.
8356          */
8357
8358         while ((c = nextopt("pvV")) != '\0')
8359                 if (c == 'V')
8360                         verify |= VERIFY_VERBOSE;
8361                 else if (c == 'v')
8362                         /*verify |= VERIFY_BRIEF*/;
8363 #if DEBUG
8364                 else if (c != 'p')
8365                         abort();
8366 #endif
8367                 else
8368                         path = bb_default_path;
8369
8370         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8371         cmd = *argptr;
8372         if (/*verify && */ cmd)
8373                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8374
8375         return 0;
8376 }
8377 #endif
8378
8379
8380 /*static int funcblocksize;     // size of structures in function */
8381 /*static int funcstringsize;    // size of strings in node */
8382 static void *funcblock;         /* block to allocate function from */
8383 static char *funcstring_end;    /* end of block to allocate strings from */
8384
8385 /* flags in argument to evaltree */
8386 #define EV_EXIT    01           /* exit after evaluating tree */
8387 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8388
8389 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8390         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8391         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8392         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8393         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8394         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8395         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8396         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8397         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8398         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8399         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8400         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8401         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8402         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8403         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8404         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8405         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8406         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8407 #if BASH_REDIR_OUTPUT
8408         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8409 #endif
8410         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8411         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8412         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8413         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8414         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8415         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8416         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8417         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8418         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8419 };
8420
8421 static int calcsize(int funcblocksize, union node *n);
8422
8423 static int
8424 sizenodelist(int funcblocksize, struct nodelist *lp)
8425 {
8426         while (lp) {
8427                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8428                 funcblocksize = calcsize(funcblocksize, lp->n);
8429                 lp = lp->next;
8430         }
8431         return funcblocksize;
8432 }
8433
8434 static int
8435 calcsize(int funcblocksize, union node *n)
8436 {
8437         if (n == NULL)
8438                 return funcblocksize;
8439         funcblocksize += nodesize[n->type];
8440         switch (n->type) {
8441         case NCMD:
8442                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8443                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8444                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8445                 break;
8446         case NPIPE:
8447                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8448                 break;
8449         case NREDIR:
8450         case NBACKGND:
8451         case NSUBSHELL:
8452                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8453                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8454                 break;
8455         case NAND:
8456         case NOR:
8457         case NSEMI:
8458         case NWHILE:
8459         case NUNTIL:
8460                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8461                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8462                 break;
8463         case NIF:
8464                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8465                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8466                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8467                 break;
8468         case NFOR:
8469                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8470                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8471                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8472                 break;
8473         case NCASE:
8474                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8475                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8476                 break;
8477         case NCLIST:
8478                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8479                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8480                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8481                 break;
8482         case NDEFUN:
8483         case NARG:
8484                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8485                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8486                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8487                 break;
8488         case NTO:
8489 #if BASH_REDIR_OUTPUT
8490         case NTO2:
8491 #endif
8492         case NCLOBBER:
8493         case NFROM:
8494         case NFROMTO:
8495         case NAPPEND:
8496                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8497                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8498                 break;
8499         case NTOFD:
8500         case NFROMFD:
8501                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8502                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8503         break;
8504         case NHERE:
8505         case NXHERE:
8506                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8507                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8508                 break;
8509         case NNOT:
8510                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8511                 break;
8512         };
8513         return funcblocksize;
8514 }
8515
8516 static char *
8517 nodeckstrdup(char *s)
8518 {
8519         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8520         return strcpy(funcstring_end, s);
8521 }
8522
8523 static union node *copynode(union node *);
8524
8525 static struct nodelist *
8526 copynodelist(struct nodelist *lp)
8527 {
8528         struct nodelist *start;
8529         struct nodelist **lpp;
8530
8531         lpp = &start;
8532         while (lp) {
8533                 *lpp = funcblock;
8534                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8535                 (*lpp)->n = copynode(lp->n);
8536                 lp = lp->next;
8537                 lpp = &(*lpp)->next;
8538         }
8539         *lpp = NULL;
8540         return start;
8541 }
8542
8543 static union node *
8544 copynode(union node *n)
8545 {
8546         union node *new;
8547
8548         if (n == NULL)
8549                 return NULL;
8550         new = funcblock;
8551         funcblock = (char *) funcblock + nodesize[n->type];
8552
8553         switch (n->type) {
8554         case NCMD:
8555                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8556                 new->ncmd.args = copynode(n->ncmd.args);
8557                 new->ncmd.assign = copynode(n->ncmd.assign);
8558                 break;
8559         case NPIPE:
8560                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8561                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8562                 break;
8563         case NREDIR:
8564         case NBACKGND:
8565         case NSUBSHELL:
8566                 new->nredir.redirect = copynode(n->nredir.redirect);
8567                 new->nredir.n = copynode(n->nredir.n);
8568                 break;
8569         case NAND:
8570         case NOR:
8571         case NSEMI:
8572         case NWHILE:
8573         case NUNTIL:
8574                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8575                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8576                 break;
8577         case NIF:
8578                 new->nif.elsepart = copynode(n->nif.elsepart);
8579                 new->nif.ifpart = copynode(n->nif.ifpart);
8580                 new->nif.test = copynode(n->nif.test);
8581                 break;
8582         case NFOR:
8583                 new->nfor.var = nodeckstrdup(n->nfor.var);
8584                 new->nfor.body = copynode(n->nfor.body);
8585                 new->nfor.args = copynode(n->nfor.args);
8586                 break;
8587         case NCASE:
8588                 new->ncase.cases = copynode(n->ncase.cases);
8589                 new->ncase.expr = copynode(n->ncase.expr);
8590                 break;
8591         case NCLIST:
8592                 new->nclist.body = copynode(n->nclist.body);
8593                 new->nclist.pattern = copynode(n->nclist.pattern);
8594                 new->nclist.next = copynode(n->nclist.next);
8595                 break;
8596         case NDEFUN:
8597         case NARG:
8598                 new->narg.backquote = copynodelist(n->narg.backquote);
8599                 new->narg.text = nodeckstrdup(n->narg.text);
8600                 new->narg.next = copynode(n->narg.next);
8601                 break;
8602         case NTO:
8603 #if BASH_REDIR_OUTPUT
8604         case NTO2:
8605 #endif
8606         case NCLOBBER:
8607         case NFROM:
8608         case NFROMTO:
8609         case NAPPEND:
8610                 new->nfile.fname = copynode(n->nfile.fname);
8611                 new->nfile.fd = n->nfile.fd;
8612                 new->nfile.next = copynode(n->nfile.next);
8613                 break;
8614         case NTOFD:
8615         case NFROMFD:
8616                 new->ndup.vname = copynode(n->ndup.vname);
8617                 new->ndup.dupfd = n->ndup.dupfd;
8618                 new->ndup.fd = n->ndup.fd;
8619                 new->ndup.next = copynode(n->ndup.next);
8620                 break;
8621         case NHERE:
8622         case NXHERE:
8623                 new->nhere.doc = copynode(n->nhere.doc);
8624                 new->nhere.fd = n->nhere.fd;
8625                 new->nhere.next = copynode(n->nhere.next);
8626                 break;
8627         case NNOT:
8628                 new->nnot.com = copynode(n->nnot.com);
8629                 break;
8630         };
8631         new->type = n->type;
8632         return new;
8633 }
8634
8635 /*
8636  * Make a copy of a parse tree.
8637  */
8638 static struct funcnode *
8639 copyfunc(union node *n)
8640 {
8641         struct funcnode *f;
8642         size_t blocksize;
8643
8644         /*funcstringsize = 0;*/
8645         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8646         f = ckzalloc(blocksize /* + funcstringsize */);
8647         funcblock = (char *) f + offsetof(struct funcnode, n);
8648         funcstring_end = (char *) f + blocksize;
8649         copynode(n);
8650         /* f->count = 0; - ckzalloc did it */
8651         return f;
8652 }
8653
8654 /*
8655  * Define a shell function.
8656  */
8657 static void
8658 defun(union node *func)
8659 {
8660         struct cmdentry entry;
8661
8662         INT_OFF;
8663         entry.cmdtype = CMDFUNCTION;
8664         entry.u.func = copyfunc(func);
8665         addcmdentry(func->narg.text, &entry);
8666         INT_ON;
8667 }
8668
8669 /* Reasons for skipping commands (see comment on breakcmd routine) */
8670 #define SKIPBREAK      (1 << 0)
8671 #define SKIPCONT       (1 << 1)
8672 #define SKIPFUNC       (1 << 2)
8673 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8674 static int skipcount;           /* number of levels to skip */
8675 static int funcnest;            /* depth of function calls */
8676 static int loopnest;            /* current loop nesting level */
8677
8678 /* Forward decl way out to parsing code - dotrap needs it */
8679 static int evalstring(char *s, int flags);
8680
8681 /* Called to execute a trap.
8682  * Single callsite - at the end of evaltree().
8683  * If we return non-zero, evaltree raises EXEXIT exception.
8684  *
8685  * Perhaps we should avoid entering new trap handlers
8686  * while we are executing a trap handler. [is it a TODO?]
8687  */
8688 static void
8689 dotrap(void)
8690 {
8691         uint8_t *g;
8692         int sig;
8693         uint8_t last_status;
8694
8695         if (!pending_sig)
8696                 return;
8697
8698         last_status = exitstatus;
8699         pending_sig = 0;
8700         barrier();
8701
8702         TRACE(("dotrap entered\n"));
8703         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8704                 char *p;
8705
8706                 if (!*g)
8707                         continue;
8708
8709                 if (evalskip) {
8710                         pending_sig = sig;
8711                         break;
8712                 }
8713
8714                 p = trap[sig];
8715                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8716                  * don't upset it by resetting gotsig[SIGINT-1] */
8717                 if (sig == SIGINT && !p)
8718                         continue;
8719
8720                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8721                 *g = 0;
8722                 if (!p)
8723                         continue;
8724                 evalstring(p, 0);
8725         }
8726         exitstatus = last_status;
8727         TRACE(("dotrap returns\n"));
8728 }
8729
8730 /* forward declarations - evaluation is fairly recursive business... */
8731 static int evalloop(union node *, int);
8732 static int evalfor(union node *, int);
8733 static int evalcase(union node *, int);
8734 static int evalsubshell(union node *, int);
8735 static void expredir(union node *);
8736 static int evalpipe(union node *, int);
8737 static int evalcommand(union node *, int);
8738 static int evalbltin(const struct builtincmd *, int, char **, int);
8739 static void prehash(union node *);
8740
8741 /*
8742  * Evaluate a parse tree.  The value is left in the global variable
8743  * exitstatus.
8744  */
8745 static int
8746 evaltree(union node *n, int flags)
8747 {
8748         int checkexit = 0;
8749         int (*evalfn)(union node *, int);
8750         int status = 0;
8751
8752         if (n == NULL) {
8753                 TRACE(("evaltree(NULL) called\n"));
8754                 goto out;
8755         }
8756         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8757
8758         dotrap();
8759
8760         switch (n->type) {
8761         default:
8762 #if DEBUG
8763                 out1fmt("Node type = %d\n", n->type);
8764                 fflush_all();
8765                 break;
8766 #endif
8767         case NNOT:
8768                 status = !evaltree(n->nnot.com, EV_TESTED);
8769                 goto setstatus;
8770         case NREDIR:
8771                 expredir(n->nredir.redirect);
8772                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8773                 if (!status) {
8774                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8775                 }
8776                 if (n->nredir.redirect)
8777                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8778                 goto setstatus;
8779         case NCMD:
8780                 evalfn = evalcommand;
8781  checkexit:
8782                 if (eflag && !(flags & EV_TESTED))
8783                         checkexit = ~0;
8784                 goto calleval;
8785         case NFOR:
8786                 evalfn = evalfor;
8787                 goto calleval;
8788         case NWHILE:
8789         case NUNTIL:
8790                 evalfn = evalloop;
8791                 goto calleval;
8792         case NSUBSHELL:
8793         case NBACKGND:
8794                 evalfn = evalsubshell;
8795                 goto checkexit;
8796         case NPIPE:
8797                 evalfn = evalpipe;
8798                 goto checkexit;
8799         case NCASE:
8800                 evalfn = evalcase;
8801                 goto calleval;
8802         case NAND:
8803         case NOR:
8804         case NSEMI: {
8805
8806 #if NAND + 1 != NOR
8807 #error NAND + 1 != NOR
8808 #endif
8809 #if NOR + 1 != NSEMI
8810 #error NOR + 1 != NSEMI
8811 #endif
8812                 unsigned is_or = n->type - NAND;
8813                 status = evaltree(
8814                         n->nbinary.ch1,
8815                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8816                 );
8817                 if ((!status) == is_or || evalskip)
8818                         break;
8819                 n = n->nbinary.ch2;
8820  evaln:
8821                 evalfn = evaltree;
8822  calleval:
8823                 status = evalfn(n, flags);
8824                 goto setstatus;
8825         }
8826         case NIF:
8827                 status = evaltree(n->nif.test, EV_TESTED);
8828                 if (evalskip)
8829                         break;
8830                 if (!status) {
8831                         n = n->nif.ifpart;
8832                         goto evaln;
8833                 }
8834                 if (n->nif.elsepart) {
8835                         n = n->nif.elsepart;
8836                         goto evaln;
8837                 }
8838                 status = 0;
8839                 goto setstatus;
8840         case NDEFUN:
8841                 defun(n);
8842                 /* Not necessary. To test it:
8843                  * "false; f() { qwerty; }; echo $?" should print 0.
8844                  */
8845                 /* status = 0; */
8846  setstatus:
8847                 exitstatus = status;
8848                 break;
8849         }
8850  out:
8851         /* Order of checks below is important:
8852          * signal handlers trigger before exit caused by "set -e".
8853          */
8854         dotrap();
8855
8856         if (checkexit & status)
8857                 raise_exception(EXEXIT);
8858         if (flags & EV_EXIT)
8859                 raise_exception(EXEXIT);
8860
8861         TRACE(("leaving evaltree (no interrupts)\n"));
8862         return exitstatus;
8863 }
8864
8865 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8866 static
8867 #endif
8868 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8869
8870 static int
8871 skiploop(void)
8872 {
8873         int skip = evalskip;
8874
8875         switch (skip) {
8876         case 0:
8877                 break;
8878         case SKIPBREAK:
8879         case SKIPCONT:
8880                 if (--skipcount <= 0) {
8881                         evalskip = 0;
8882                         break;
8883                 }
8884                 skip = SKIPBREAK;
8885                 break;
8886         }
8887         return skip;
8888 }
8889
8890 static int
8891 evalloop(union node *n, int flags)
8892 {
8893         int skip;
8894         int status;
8895
8896         loopnest++;
8897         status = 0;
8898         flags &= EV_TESTED;
8899         do {
8900                 int i;
8901
8902                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8903                 skip = skiploop();
8904                 if (skip == SKIPFUNC)
8905                         status = i;
8906                 if (skip)
8907                         continue;
8908                 if (n->type != NWHILE)
8909                         i = !i;
8910                 if (i != 0)
8911                         break;
8912                 status = evaltree(n->nbinary.ch2, flags);
8913                 skip = skiploop();
8914         } while (!(skip & ~SKIPCONT));
8915         loopnest--;
8916
8917         return status;
8918 }
8919
8920 static int
8921 evalfor(union node *n, int flags)
8922 {
8923         struct arglist arglist;
8924         union node *argp;
8925         struct strlist *sp;
8926         struct stackmark smark;
8927         int status = 0;
8928
8929         setstackmark(&smark);
8930         arglist.list = NULL;
8931         arglist.lastp = &arglist.list;
8932         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8933                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8934         }
8935         *arglist.lastp = NULL;
8936
8937         loopnest++;
8938         flags &= EV_TESTED;
8939         for (sp = arglist.list; sp; sp = sp->next) {
8940                 setvar0(n->nfor.var, sp->text);
8941                 status = evaltree(n->nfor.body, flags);
8942                 if (skiploop() & ~SKIPCONT)
8943                         break;
8944         }
8945         loopnest--;
8946         popstackmark(&smark);
8947
8948         return status;
8949 }
8950
8951 static int
8952 evalcase(union node *n, int flags)
8953 {
8954         union node *cp;
8955         union node *patp;
8956         struct arglist arglist;
8957         struct stackmark smark;
8958         int status = 0;
8959
8960         setstackmark(&smark);
8961         arglist.list = NULL;
8962         arglist.lastp = &arglist.list;
8963         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8964         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8965                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8966                         if (casematch(patp, arglist.list->text)) {
8967                                 /* Ensure body is non-empty as otherwise
8968                                  * EV_EXIT may prevent us from setting the
8969                                  * exit status.
8970                                  */
8971                                 if (evalskip == 0 && cp->nclist.body) {
8972                                         status = evaltree(cp->nclist.body, flags);
8973                                 }
8974                                 goto out;
8975                         }
8976                 }
8977         }
8978  out:
8979         popstackmark(&smark);
8980
8981         return status;
8982 }
8983
8984 /*
8985  * Kick off a subshell to evaluate a tree.
8986  */
8987 static int
8988 evalsubshell(union node *n, int flags)
8989 {
8990         struct job *jp;
8991         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8992         int status;
8993
8994         expredir(n->nredir.redirect);
8995         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8996                 goto nofork;
8997         INT_OFF;
8998         if (backgnd == FORK_FG)
8999                 get_tty_state();
9000         jp = makejob(/*n,*/ 1);
9001         if (forkshell(jp, n, backgnd) == 0) {
9002                 /* child */
9003                 INT_ON;
9004                 flags |= EV_EXIT;
9005                 if (backgnd)
9006                         flags &= ~EV_TESTED;
9007  nofork:
9008                 redirect(n->nredir.redirect, 0);
9009                 evaltreenr(n->nredir.n, flags);
9010                 /* never returns */
9011         }
9012         /* parent */
9013         status = 0;
9014         if (backgnd == FORK_FG)
9015                 status = waitforjob(jp);
9016         INT_ON;
9017         return status;
9018 }
9019
9020 /*
9021  * Compute the names of the files in a redirection list.
9022  */
9023 static void fixredir(union node *, const char *, int);
9024 static void
9025 expredir(union node *n)
9026 {
9027         union node *redir;
9028
9029         for (redir = n; redir; redir = redir->nfile.next) {
9030                 struct arglist fn;
9031
9032                 fn.list = NULL;
9033                 fn.lastp = &fn.list;
9034                 switch (redir->type) {
9035                 case NFROMTO:
9036                 case NFROM:
9037                 case NTO:
9038 #if BASH_REDIR_OUTPUT
9039                 case NTO2:
9040 #endif
9041                 case NCLOBBER:
9042                 case NAPPEND:
9043                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9044                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9045 #if BASH_REDIR_OUTPUT
9046  store_expfname:
9047 #endif
9048 #if 0
9049 // By the design of stack allocator, the loop of this kind:
9050 //      while true; do while true; do break; done </dev/null; done
9051 // will look like a memory leak: ash plans to free expfname's
9052 // of "/dev/null" as soon as it finishes running the loop
9053 // (in this case, never).
9054 // This "fix" is wrong:
9055                         if (redir->nfile.expfname)
9056                                 stunalloc(redir->nfile.expfname);
9057 // It results in corrupted state of stacked allocations.
9058 #endif
9059                         redir->nfile.expfname = fn.list->text;
9060                         break;
9061                 case NFROMFD:
9062                 case NTOFD: /* >& */
9063                         if (redir->ndup.vname) {
9064                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9065                                 if (fn.list == NULL)
9066                                         ash_msg_and_raise_error("redir error");
9067 #if BASH_REDIR_OUTPUT
9068 //FIXME: we used expandarg with different args!
9069                                 if (!isdigit_str9(fn.list->text)) {
9070                                         /* >&file, not >&fd */
9071                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9072                                                 ash_msg_and_raise_error("redir error");
9073                                         redir->type = NTO2;
9074                                         goto store_expfname;
9075                                 }
9076 #endif
9077                                 fixredir(redir, fn.list->text, 1);
9078                         }
9079                         break;
9080                 }
9081         }
9082 }
9083
9084 /*
9085  * Evaluate a pipeline.  All the processes in the pipeline are children
9086  * of the process creating the pipeline.  (This differs from some versions
9087  * of the shell, which make the last process in a pipeline the parent
9088  * of all the rest.)
9089  */
9090 static int
9091 evalpipe(union node *n, int flags)
9092 {
9093         struct job *jp;
9094         struct nodelist *lp;
9095         int pipelen;
9096         int prevfd;
9097         int pip[2];
9098         int status = 0;
9099
9100         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9101         pipelen = 0;
9102         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9103                 pipelen++;
9104         flags |= EV_EXIT;
9105         INT_OFF;
9106         if (n->npipe.pipe_backgnd == 0)
9107                 get_tty_state();
9108         jp = makejob(/*n,*/ pipelen);
9109         prevfd = -1;
9110         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9111                 prehash(lp->n);
9112                 pip[1] = -1;
9113                 if (lp->next) {
9114                         if (pipe(pip) < 0) {
9115                                 close(prevfd);
9116                                 ash_msg_and_raise_error("pipe call failed");
9117                         }
9118                 }
9119                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9120                         /* child */
9121                         INT_ON;
9122                         if (pip[1] >= 0) {
9123                                 close(pip[0]);
9124                         }
9125                         if (prevfd > 0) {
9126                                 dup2(prevfd, 0);
9127                                 close(prevfd);
9128                         }
9129                         if (pip[1] > 1) {
9130                                 dup2(pip[1], 1);
9131                                 close(pip[1]);
9132                         }
9133                         evaltreenr(lp->n, flags);
9134                         /* never returns */
9135                 }
9136                 /* parent */
9137                 if (prevfd >= 0)
9138                         close(prevfd);
9139                 prevfd = pip[0];
9140                 /* Don't want to trigger debugging */
9141                 if (pip[1] != -1)
9142                         close(pip[1]);
9143         }
9144         if (n->npipe.pipe_backgnd == 0) {
9145                 status = waitforjob(jp);
9146                 TRACE(("evalpipe:  job done exit status %d\n", status));
9147         }
9148         INT_ON;
9149
9150         return status;
9151 }
9152
9153 /*
9154  * Controls whether the shell is interactive or not.
9155  */
9156 static void
9157 setinteractive(int on)
9158 {
9159         static smallint is_interactive;
9160
9161         if (++on == is_interactive)
9162                 return;
9163         is_interactive = on;
9164         setsignal(SIGINT);
9165         setsignal(SIGQUIT);
9166         setsignal(SIGTERM);
9167 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9168         if (is_interactive > 1) {
9169                 /* Looks like they want an interactive shell */
9170                 static smallint did_banner;
9171
9172                 if (!did_banner) {
9173                         /* note: ash and hush share this string */
9174                         out1fmt("\n\n%s %s\n"
9175                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9176                                 "\n",
9177                                 bb_banner,
9178                                 "built-in shell (ash)"
9179                         );
9180                         did_banner = 1;
9181                 }
9182         }
9183 #endif
9184 }
9185
9186 static void
9187 optschanged(void)
9188 {
9189 #if DEBUG
9190         opentrace();
9191 #endif
9192         setinteractive(iflag);
9193         setjobctl(mflag);
9194 #if ENABLE_FEATURE_EDITING_VI
9195         if (viflag)
9196                 line_input_state->flags |= VI_MODE;
9197         else
9198                 line_input_state->flags &= ~VI_MODE;
9199 #else
9200         viflag = 0; /* forcibly keep the option off */
9201 #endif
9202 }
9203
9204 static struct localvar *localvars;
9205
9206 /*
9207  * Called after a function returns.
9208  * Interrupts must be off.
9209  */
9210 static void
9211 poplocalvars(void)
9212 {
9213         struct localvar *lvp;
9214         struct var *vp;
9215
9216         while ((lvp = localvars) != NULL) {
9217                 localvars = lvp->next;
9218                 vp = lvp->vp;
9219                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9220                 if (vp == NULL) {       /* $- saved */
9221                         memcpy(optlist, lvp->text, sizeof(optlist));
9222                         free((char*)lvp->text);
9223                         optschanged();
9224                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9225                         unsetvar(vp->var_text);
9226                 } else {
9227                         if (vp->var_func)
9228                                 vp->var_func(var_end(lvp->text));
9229                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9230                                 free((char*)vp->var_text);
9231                         vp->flags = lvp->flags;
9232                         vp->var_text = lvp->text;
9233                 }
9234                 free(lvp);
9235         }
9236 }
9237
9238 static int
9239 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9240 {
9241         volatile struct shparam saveparam;
9242         struct localvar *volatile savelocalvars;
9243         struct jmploc *volatile savehandler;
9244         struct jmploc jmploc;
9245         int e;
9246
9247         saveparam = shellparam;
9248         savelocalvars = localvars;
9249         savehandler = exception_handler;
9250         e = setjmp(jmploc.loc);
9251         if (e) {
9252                 goto funcdone;
9253         }
9254         INT_OFF;
9255         exception_handler = &jmploc;
9256         localvars = NULL;
9257         shellparam.malloced = 0;
9258         func->count++;
9259         funcnest++;
9260         INT_ON;
9261         shellparam.nparam = argc - 1;
9262         shellparam.p = argv + 1;
9263 #if ENABLE_ASH_GETOPTS
9264         shellparam.optind = 1;
9265         shellparam.optoff = -1;
9266 #endif
9267         evaltree(func->n.narg.next, flags & EV_TESTED);
9268  funcdone:
9269         INT_OFF;
9270         funcnest--;
9271         freefunc(func);
9272         poplocalvars();
9273         localvars = savelocalvars;
9274         freeparam(&shellparam);
9275         shellparam = saveparam;
9276         exception_handler = savehandler;
9277         INT_ON;
9278         evalskip &= ~SKIPFUNC;
9279         return e;
9280 }
9281
9282 /*
9283  * Make a variable a local variable.  When a variable is made local, it's
9284  * value and flags are saved in a localvar structure.  The saved values
9285  * will be restored when the shell function returns.  We handle the name
9286  * "-" as a special case: it makes changes to "set +-options" local
9287  * (options will be restored on return from the function).
9288  */
9289 static void
9290 mklocal(char *name)
9291 {
9292         struct localvar *lvp;
9293         struct var **vpp;
9294         struct var *vp;
9295         char *eq = strchr(name, '=');
9296
9297         INT_OFF;
9298         /* Cater for duplicate "local". Examples:
9299          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9300          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9301          */
9302         lvp = localvars;
9303         while (lvp) {
9304                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9305                         if (eq)
9306                                 setvareq(name, 0);
9307                         /* else:
9308                          * it's a duplicate "local VAR" declaration, do nothing
9309                          */
9310                         goto ret;
9311                 }
9312                 lvp = lvp->next;
9313         }
9314
9315         lvp = ckzalloc(sizeof(*lvp));
9316         if (LONE_DASH(name)) {
9317                 char *p;
9318                 p = ckmalloc(sizeof(optlist));
9319                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9320                 vp = NULL;
9321         } else {
9322                 vpp = hashvar(name);
9323                 vp = *findvar(vpp, name);
9324                 if (vp == NULL) {
9325                         /* variable did not exist yet */
9326                         if (eq)
9327                                 setvareq(name, VSTRFIXED);
9328                         else
9329                                 setvar(name, NULL, VSTRFIXED);
9330                         vp = *vpp;      /* the new variable */
9331                         lvp->flags = VUNSET;
9332                 } else {
9333                         lvp->text = vp->var_text;
9334                         lvp->flags = vp->flags;
9335                         /* make sure neither "struct var" nor string gets freed
9336                          * during (un)setting:
9337                          */
9338                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9339                         if (eq)
9340                                 setvareq(name, 0);
9341                         else
9342                                 /* "local VAR" unsets VAR: */
9343                                 setvar0(name, NULL);
9344                 }
9345         }
9346         lvp->vp = vp;
9347         lvp->next = localvars;
9348         localvars = lvp;
9349  ret:
9350         INT_ON;
9351 }
9352
9353 /*
9354  * The "local" command.
9355  */
9356 static int FAST_FUNC
9357 localcmd(int argc UNUSED_PARAM, char **argv)
9358 {
9359         char *name;
9360
9361         if (!funcnest)
9362                 ash_msg_and_raise_error("not in a function");
9363
9364         argv = argptr;
9365         while ((name = *argv++) != NULL) {
9366                 mklocal(name);
9367         }
9368         return 0;
9369 }
9370
9371 static int FAST_FUNC
9372 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9373 {
9374         return 1;
9375 }
9376
9377 static int FAST_FUNC
9378 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9379 {
9380         return 0;
9381 }
9382
9383 static int FAST_FUNC
9384 execcmd(int argc UNUSED_PARAM, char **argv)
9385 {
9386         optionarg = NULL;
9387         while (nextopt("a:") != '\0')
9388                 /* nextopt() sets optionarg to "-a ARGV0" */;
9389
9390         argv = argptr;
9391         if (argv[0]) {
9392                 char *prog;
9393
9394                 iflag = 0;              /* exit on error */
9395                 mflag = 0;
9396                 optschanged();
9397                 /* We should set up signals for "exec CMD"
9398                  * the same way as for "CMD" without "exec".
9399                  * But optschanged->setinteractive->setsignal
9400                  * still thought we are a root shell. Therefore, for example,
9401                  * SIGQUIT is still set to IGN. Fix it:
9402                  */
9403                 shlvl++;
9404                 setsignal(SIGQUIT);
9405                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9406                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9407                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9408
9409                 prog = argv[0];
9410                 if (optionarg)
9411                         argv[0] = optionarg;
9412                 shellexec(prog, argv, pathval(), 0);
9413                 /* NOTREACHED */
9414         }
9415         return 0;
9416 }
9417
9418 /*
9419  * The return command.
9420  */
9421 static int FAST_FUNC
9422 returncmd(int argc UNUSED_PARAM, char **argv)
9423 {
9424         /*
9425          * If called outside a function, do what ksh does;
9426          * skip the rest of the file.
9427          */
9428         evalskip = SKIPFUNC;
9429         return argv[1] ? number(argv[1]) : exitstatus;
9430 }
9431
9432 /* Forward declarations for builtintab[] */
9433 static int breakcmd(int, char **) FAST_FUNC;
9434 static int dotcmd(int, char **) FAST_FUNC;
9435 static int evalcmd(int, char **, int) FAST_FUNC;
9436 static int exitcmd(int, char **) FAST_FUNC;
9437 static int exportcmd(int, char **) FAST_FUNC;
9438 #if ENABLE_ASH_GETOPTS
9439 static int getoptscmd(int, char **) FAST_FUNC;
9440 #endif
9441 #if ENABLE_ASH_HELP
9442 static int helpcmd(int, char **) FAST_FUNC;
9443 #endif
9444 #if MAX_HISTORY
9445 static int historycmd(int, char **) FAST_FUNC;
9446 #endif
9447 #if ENABLE_FEATURE_SH_MATH
9448 static int letcmd(int, char **) FAST_FUNC;
9449 #endif
9450 static int readcmd(int, char **) FAST_FUNC;
9451 static int setcmd(int, char **) FAST_FUNC;
9452 static int shiftcmd(int, char **) FAST_FUNC;
9453 static int timescmd(int, char **) FAST_FUNC;
9454 static int trapcmd(int, char **) FAST_FUNC;
9455 static int umaskcmd(int, char **) FAST_FUNC;
9456 static int unsetcmd(int, char **) FAST_FUNC;
9457 static int ulimitcmd(int, char **) FAST_FUNC;
9458
9459 #define BUILTIN_NOSPEC          "0"
9460 #define BUILTIN_SPECIAL         "1"
9461 #define BUILTIN_REGULAR         "2"
9462 #define BUILTIN_SPEC_REG        "3"
9463 #define BUILTIN_ASSIGN          "4"
9464 #define BUILTIN_SPEC_ASSG       "5"
9465 #define BUILTIN_REG_ASSG        "6"
9466 #define BUILTIN_SPEC_REG_ASSG   "7"
9467
9468 /* Stubs for calling non-FAST_FUNC's */
9469 #if ENABLE_ASH_ECHO
9470 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9471 #endif
9472 #if ENABLE_ASH_PRINTF
9473 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9474 #endif
9475 #if ENABLE_ASH_TEST || BASH_TEST2
9476 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9477 #endif
9478
9479 /* Keep these in proper order since it is searched via bsearch() */
9480 static const struct builtincmd builtintab[] = {
9481         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9482         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9483 #if ENABLE_ASH_TEST
9484         { BUILTIN_REGULAR       "["       , testcmd    },
9485 #endif
9486 #if BASH_TEST2
9487         { BUILTIN_REGULAR       "[["      , testcmd    },
9488 #endif
9489 #if ENABLE_ASH_ALIAS
9490         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9491 #endif
9492 #if JOBS
9493         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9494 #endif
9495         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9496         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9497         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9498 #if ENABLE_ASH_CMDCMD
9499         { BUILTIN_REGULAR       "command" , commandcmd },
9500 #endif
9501         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9502 #if ENABLE_ASH_ECHO
9503         { BUILTIN_REGULAR       "echo"    , echocmd    },
9504 #endif
9505         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9506         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9507         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9508         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9509         { BUILTIN_REGULAR       "false"   , falsecmd   },
9510 #if JOBS
9511         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9512 #endif
9513 #if ENABLE_ASH_GETOPTS
9514         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9515 #endif
9516         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9517 #if ENABLE_ASH_HELP
9518         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9519 #endif
9520 #if MAX_HISTORY
9521         { BUILTIN_NOSPEC        "history" , historycmd },
9522 #endif
9523 #if JOBS
9524         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9525         { BUILTIN_REGULAR       "kill"    , killcmd    },
9526 #endif
9527 #if ENABLE_FEATURE_SH_MATH
9528         { BUILTIN_NOSPEC        "let"     , letcmd     },
9529 #endif
9530         { BUILTIN_ASSIGN        "local"   , localcmd   },
9531 #if ENABLE_ASH_PRINTF
9532         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9533 #endif
9534         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9535         { BUILTIN_REGULAR       "read"    , readcmd    },
9536         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9537         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9538         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9539         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9540 #if BASH_SOURCE
9541         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9542 #endif
9543 #if ENABLE_ASH_TEST
9544         { BUILTIN_REGULAR       "test"    , testcmd    },
9545 #endif
9546         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9547         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9548         { BUILTIN_REGULAR       "true"    , truecmd    },
9549         { BUILTIN_NOSPEC        "type"    , typecmd    },
9550         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9551         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9552 #if ENABLE_ASH_ALIAS
9553         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9554 #endif
9555         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9556         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9557 };
9558
9559 /* Should match the above table! */
9560 #define COMMANDCMD (builtintab + \
9561         /* . : */       2 + \
9562         /* [ */         1 * ENABLE_ASH_TEST + \
9563         /* [[ */        1 * BASH_TEST2 + \
9564         /* alias */     1 * ENABLE_ASH_ALIAS + \
9565         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9566         /* break cd cddir  */   3)
9567 #define EVALCMD (COMMANDCMD + \
9568         /* command */   1 * ENABLE_ASH_CMDCMD + \
9569         /* continue */  1 + \
9570         /* echo */      1 * ENABLE_ASH_ECHO + \
9571         0)
9572 #define EXECCMD (EVALCMD + \
9573         /* eval */      1)
9574
9575 /*
9576  * Search the table of builtin commands.
9577  */
9578 static int
9579 pstrcmp1(const void *a, const void *b)
9580 {
9581         return strcmp((char*)a, *(char**)b + 1);
9582 }
9583 static struct builtincmd *
9584 find_builtin(const char *name)
9585 {
9586         struct builtincmd *bp;
9587
9588         bp = bsearch(
9589                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9590                 pstrcmp1
9591         );
9592         return bp;
9593 }
9594
9595 /*
9596  * Execute a simple command.
9597  */
9598 static int
9599 isassignment(const char *p)
9600 {
9601         const char *q = endofname(p);
9602         if (p == q)
9603                 return 0;
9604         return *q == '=';
9605 }
9606 static int FAST_FUNC
9607 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9608 {
9609         /* Preserve exitstatus of a previous possible redirection
9610          * as POSIX mandates */
9611         return back_exitstatus;
9612 }
9613 static int
9614 evalcommand(union node *cmd, int flags)
9615 {
9616         static const struct builtincmd null_bltin = {
9617                 "\0\0", bltincmd /* why three NULs? */
9618         };
9619         struct stackmark smark;
9620         union node *argp;
9621         struct arglist arglist;
9622         struct arglist varlist;
9623         char **argv;
9624         int argc;
9625         const struct strlist *sp;
9626         struct cmdentry cmdentry;
9627         struct job *jp;
9628         char *lastarg;
9629         const char *path;
9630         int spclbltin;
9631         int status;
9632         char **nargv;
9633         struct builtincmd *bcmd;
9634         smallint cmd_is_exec;
9635         smallint pseudovarflag = 0;
9636
9637         /* First expand the arguments. */
9638         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9639         setstackmark(&smark);
9640         back_exitstatus = 0;
9641
9642         cmdentry.cmdtype = CMDBUILTIN;
9643         cmdentry.u.cmd = &null_bltin;
9644         varlist.lastp = &varlist.list;
9645         *varlist.lastp = NULL;
9646         arglist.lastp = &arglist.list;
9647         *arglist.lastp = NULL;
9648
9649         argc = 0;
9650         if (cmd->ncmd.args) {
9651                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9652                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9653         }
9654
9655         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9656                 struct strlist **spp;
9657
9658                 spp = arglist.lastp;
9659                 if (pseudovarflag && isassignment(argp->narg.text))
9660                         expandarg(argp, &arglist, EXP_VARTILDE);
9661                 else
9662                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9663
9664                 for (sp = *spp; sp; sp = sp->next)
9665                         argc++;
9666         }
9667
9668         /* Reserve one extra spot at the front for shellexec. */
9669         nargv = stalloc(sizeof(char *) * (argc + 2));
9670         argv = ++nargv;
9671         for (sp = arglist.list; sp; sp = sp->next) {
9672                 TRACE(("evalcommand arg: %s\n", sp->text));
9673                 *nargv++ = sp->text;
9674         }
9675         *nargv = NULL;
9676
9677         lastarg = NULL;
9678         if (iflag && funcnest == 0 && argc > 0)
9679                 lastarg = nargv[-1];
9680
9681         preverrout_fd = 2;
9682         expredir(cmd->ncmd.redirect);
9683         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9684
9685         path = vpath.var_text;
9686         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9687                 struct strlist **spp;
9688                 char *p;
9689
9690                 spp = varlist.lastp;
9691                 expandarg(argp, &varlist, EXP_VARTILDE);
9692
9693                 /*
9694                  * Modify the command lookup path, if a PATH= assignment
9695                  * is present
9696                  */
9697                 p = (*spp)->text;
9698                 if (varcmp(p, path) == 0)
9699                         path = p;
9700         }
9701
9702         /* Print the command if xflag is set. */
9703         if (xflag) {
9704                 int n;
9705                 const char *p = " %s" + 1;
9706
9707                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9708                 sp = varlist.list;
9709                 for (n = 0; n < 2; n++) {
9710                         while (sp) {
9711                                 fdprintf(preverrout_fd, p, sp->text);
9712                                 sp = sp->next;
9713                                 p = " %s";
9714                         }
9715                         sp = arglist.list;
9716                 }
9717                 safe_write(preverrout_fd, "\n", 1);
9718         }
9719
9720         cmd_is_exec = 0;
9721         spclbltin = -1;
9722
9723         /* Now locate the command. */
9724         if (argc) {
9725                 int cmd_flag = DO_ERR;
9726 #if ENABLE_ASH_CMDCMD
9727                 const char *oldpath = path + 5;
9728 #endif
9729                 path += 5;
9730                 for (;;) {
9731                         find_command(argv[0], &cmdentry, cmd_flag, path);
9732                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9733                                 flush_stdout_stderr();
9734                                 status = 127;
9735                                 goto bail;
9736                         }
9737
9738                         /* implement bltin and command here */
9739                         if (cmdentry.cmdtype != CMDBUILTIN)
9740                                 break;
9741                         if (spclbltin < 0)
9742                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9743                         if (cmdentry.u.cmd == EXECCMD)
9744                                 cmd_is_exec = 1;
9745 #if ENABLE_ASH_CMDCMD
9746                         if (cmdentry.u.cmd == COMMANDCMD) {
9747                                 path = oldpath;
9748                                 nargv = parse_command_args(argv, &path);
9749                                 if (!nargv)
9750                                         break;
9751                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9752                                  * nargv => "PROG". path is updated if -p.
9753                                  */
9754                                 argc -= nargv - argv;
9755                                 argv = nargv;
9756                                 cmd_flag |= DO_NOFUNC;
9757                         } else
9758 #endif
9759                                 break;
9760                 }
9761         }
9762
9763         if (status) {
9764  bail:
9765                 exitstatus = status;
9766
9767                 /* We have a redirection error. */
9768                 if (spclbltin > 0)
9769                         raise_exception(EXERROR);
9770
9771                 goto out;
9772         }
9773
9774         /* Execute the command. */
9775         switch (cmdentry.cmdtype) {
9776         default: {
9777
9778 #if ENABLE_FEATURE_SH_NOFORK
9779 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9780  *     around run_nofork_applet() call.
9781  * (2) Should this check also be done in forkshell()?
9782  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9783  */
9784                 /* find_command() encodes applet_no as (-2 - applet_no) */
9785                 int applet_no = (- cmdentry.u.index - 2);
9786                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9787                         listsetvar(varlist.list, VEXPORT|VSTACK);
9788                         /* run <applet>_main() */
9789                         status = run_nofork_applet(applet_no, argv);
9790                         break;
9791                 }
9792 #endif
9793                 /* Can we avoid forking off? For example, very last command
9794                  * in a script or a subshell does not need forking,
9795                  * we can just exec it.
9796                  */
9797                 if (!(flags & EV_EXIT) || may_have_traps) {
9798                         /* No, forking off a child is necessary */
9799                         INT_OFF;
9800                         get_tty_state();
9801                         jp = makejob(/*cmd,*/ 1);
9802                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9803                                 /* parent */
9804                                 status = waitforjob(jp);
9805                                 INT_ON;
9806                                 TRACE(("forked child exited with %d\n", status));
9807                                 break;
9808                         }
9809                         /* child */
9810                         FORCE_INT_ON;
9811                         /* fall through to exec'ing external program */
9812                 }
9813                 listsetvar(varlist.list, VEXPORT|VSTACK);
9814                 shellexec(argv[0], argv, path, cmdentry.u.index);
9815                 /* NOTREACHED */
9816         } /* default */
9817         case CMDBUILTIN:
9818                 cmdenviron = varlist.list;
9819                 if (cmdenviron) {
9820                         struct strlist *list = cmdenviron;
9821                         int i = VNOSET;
9822                         if (spclbltin > 0 || argc == 0) {
9823                                 i = 0;
9824                                 if (cmd_is_exec && argc > 1)
9825                                         i = VEXPORT;
9826                         }
9827                         listsetvar(list, i);
9828                 }
9829                 /* Tight loop with builtins only:
9830                  * "while kill -0 $child; do true; done"
9831                  * will never exit even if $child died, unless we do this
9832                  * to reap the zombie and make kill detect that it's gone: */
9833                 dowait(DOWAIT_NONBLOCK, NULL);
9834
9835                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9836                         if (exception_type == EXERROR && spclbltin <= 0) {
9837                                 FORCE_INT_ON;
9838                                 goto readstatus;
9839                         }
9840  raise:
9841                         longjmp(exception_handler->loc, 1);
9842                 }
9843                 goto readstatus;
9844
9845         case CMDFUNCTION:
9846                 listsetvar(varlist.list, 0);
9847                 /* See above for the rationale */
9848                 dowait(DOWAIT_NONBLOCK, NULL);
9849                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9850                         goto raise;
9851  readstatus:
9852                 status = exitstatus;
9853                 break;
9854         } /* switch */
9855
9856  out:
9857         if (cmd->ncmd.redirect)
9858                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9859         if (lastarg) {
9860                 /* dsl: I think this is intended to be used to support
9861                  * '_' in 'vi' command mode during line editing...
9862                  * However I implemented that within libedit itself.
9863                  */
9864                 setvar0("_", lastarg);
9865         }
9866         popstackmark(&smark);
9867
9868         return status;
9869 }
9870
9871 static int
9872 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9873 {
9874         char *volatile savecmdname;
9875         struct jmploc *volatile savehandler;
9876         struct jmploc jmploc;
9877         int status;
9878         int i;
9879
9880         savecmdname = commandname;
9881         savehandler = exception_handler;
9882         i = setjmp(jmploc.loc);
9883         if (i)
9884                 goto cmddone;
9885         exception_handler = &jmploc;
9886         commandname = argv[0];
9887         argptr = argv + 1;
9888         optptr = NULL;                  /* initialize nextopt */
9889         if (cmd == EVALCMD)
9890                 status = evalcmd(argc, argv, flags);
9891         else
9892                 status = (*cmd->builtin)(argc, argv);
9893         flush_stdout_stderr();
9894         status |= ferror(stdout);
9895         exitstatus = status;
9896  cmddone:
9897         clearerr(stdout);
9898         commandname = savecmdname;
9899         exception_handler = savehandler;
9900
9901         return i;
9902 }
9903
9904 static int
9905 goodname(const char *p)
9906 {
9907         return endofname(p)[0] == '\0';
9908 }
9909
9910
9911 /*
9912  * Search for a command.  This is called before we fork so that the
9913  * location of the command will be available in the parent as well as
9914  * the child.  The check for "goodname" is an overly conservative
9915  * check that the name will not be subject to expansion.
9916  */
9917 static void
9918 prehash(union node *n)
9919 {
9920         struct cmdentry entry;
9921
9922         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9923                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9924 }
9925
9926
9927 /* ============ Builtin commands
9928  *
9929  * Builtin commands whose functions are closely tied to evaluation
9930  * are implemented here.
9931  */
9932
9933 /*
9934  * Handle break and continue commands.  Break, continue, and return are
9935  * all handled by setting the evalskip flag.  The evaluation routines
9936  * above all check this flag, and if it is set they start skipping
9937  * commands rather than executing them.  The variable skipcount is
9938  * the number of loops to break/continue, or the number of function
9939  * levels to return.  (The latter is always 1.)  It should probably
9940  * be an error to break out of more loops than exist, but it isn't
9941  * in the standard shell so we don't make it one here.
9942  */
9943 static int FAST_FUNC
9944 breakcmd(int argc UNUSED_PARAM, char **argv)
9945 {
9946         int n = argv[1] ? number(argv[1]) : 1;
9947
9948         if (n <= 0)
9949                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9950         if (n > loopnest)
9951                 n = loopnest;
9952         if (n > 0) {
9953                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9954                 skipcount = n;
9955         }
9956         return 0;
9957 }
9958
9959
9960 /*
9961  * This implements the input routines used by the parser.
9962  */
9963
9964 enum {
9965         INPUT_PUSH_FILE = 1,
9966         INPUT_NOFILE_OK = 2,
9967 };
9968
9969 static smallint checkkwd;
9970 /* values of checkkwd variable */
9971 #define CHKALIAS        0x1
9972 #define CHKKWD          0x2
9973 #define CHKNL           0x4
9974
9975 /*
9976  * Push a string back onto the input at this current parsefile level.
9977  * We handle aliases this way.
9978  */
9979 #if !ENABLE_ASH_ALIAS
9980 #define pushstring(s, ap) pushstring(s)
9981 #endif
9982 static void
9983 pushstring(char *s, struct alias *ap)
9984 {
9985         struct strpush *sp;
9986         int len;
9987
9988         len = strlen(s);
9989         INT_OFF;
9990         if (g_parsefile->strpush) {
9991                 sp = ckzalloc(sizeof(*sp));
9992                 sp->prev = g_parsefile->strpush;
9993         } else {
9994                 sp = &(g_parsefile->basestrpush);
9995         }
9996         g_parsefile->strpush = sp;
9997         sp->prev_string = g_parsefile->next_to_pgetc;
9998         sp->prev_left_in_line = g_parsefile->left_in_line;
9999         sp->unget = g_parsefile->unget;
10000         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10001 #if ENABLE_ASH_ALIAS
10002         sp->ap = ap;
10003         if (ap) {
10004                 ap->flag |= ALIASINUSE;
10005                 sp->string = s;
10006         }
10007 #endif
10008         g_parsefile->next_to_pgetc = s;
10009         g_parsefile->left_in_line = len;
10010         g_parsefile->unget = 0;
10011         INT_ON;
10012 }
10013
10014 static void
10015 popstring(void)
10016 {
10017         struct strpush *sp = g_parsefile->strpush;
10018
10019         INT_OFF;
10020 #if ENABLE_ASH_ALIAS
10021         if (sp->ap) {
10022                 if (g_parsefile->next_to_pgetc[-1] == ' '
10023                  || g_parsefile->next_to_pgetc[-1] == '\t'
10024                 ) {
10025                         checkkwd |= CHKALIAS;
10026                 }
10027                 if (sp->string != sp->ap->val) {
10028                         free(sp->string);
10029                 }
10030                 sp->ap->flag &= ~ALIASINUSE;
10031                 if (sp->ap->flag & ALIASDEAD) {
10032                         unalias(sp->ap->name);
10033                 }
10034         }
10035 #endif
10036         g_parsefile->next_to_pgetc = sp->prev_string;
10037         g_parsefile->left_in_line = sp->prev_left_in_line;
10038         g_parsefile->unget = sp->unget;
10039         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10040         g_parsefile->strpush = sp->prev;
10041         if (sp != &(g_parsefile->basestrpush))
10042                 free(sp);
10043         INT_ON;
10044 }
10045
10046 static int
10047 preadfd(void)
10048 {
10049         int nr;
10050         char *buf = g_parsefile->buf;
10051
10052         g_parsefile->next_to_pgetc = buf;
10053 #if ENABLE_FEATURE_EDITING
10054  retry:
10055         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10056                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10057         else {
10058                 int timeout = -1;
10059 # if ENABLE_ASH_IDLE_TIMEOUT
10060                 if (iflag) {
10061                         const char *tmout_var = lookupvar("TMOUT");
10062                         if (tmout_var) {
10063                                 timeout = atoi(tmout_var) * 1000;
10064                                 if (timeout <= 0)
10065                                         timeout = -1;
10066                         }
10067                 }
10068 # endif
10069 # if ENABLE_FEATURE_TAB_COMPLETION
10070                 line_input_state->path_lookup = pathval();
10071 # endif
10072                 reinit_unicode_for_ash();
10073                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10074                 if (nr == 0) {
10075                         /* ^C pressed, "convert" to SIGINT */
10076                         write(STDOUT_FILENO, "^C", 2);
10077                         if (trap[SIGINT]) {
10078                                 buf[0] = '\n';
10079                                 buf[1] = '\0';
10080                                 raise(SIGINT);
10081                                 return 1;
10082                         }
10083                         exitstatus = 128 + SIGINT;
10084                         bb_putchar('\n');
10085                         goto retry;
10086                 }
10087                 if (nr < 0) {
10088                         if (errno == 0) {
10089                                 /* Ctrl+D pressed */
10090                                 nr = 0;
10091                         }
10092 # if ENABLE_ASH_IDLE_TIMEOUT
10093                         else if (errno == EAGAIN && timeout > 0) {
10094                                 puts("\007timed out waiting for input: auto-logout");
10095                                 exitshell();
10096                         }
10097 # endif
10098                 }
10099         }
10100 #else
10101         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10102 #endif
10103
10104 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10105         if (nr < 0) {
10106                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10107                         int flags = fcntl(0, F_GETFL);
10108                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10109                                 flags &= ~O_NONBLOCK;
10110                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10111                                         out2str("sh: turning off NDELAY mode\n");
10112                                         goto retry;
10113                                 }
10114                         }
10115                 }
10116         }
10117 #endif
10118         return nr;
10119 }
10120
10121 /*
10122  * Refill the input buffer and return the next input character:
10123  *
10124  * 1) If a string was pushed back on the input, pop it;
10125  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10126  *    or we are reading from a string so we can't refill the buffer,
10127  *    return EOF.
10128  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10129  * 4) Process input up to the next newline, deleting nul characters.
10130  */
10131 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10132 #define pgetc_debug(...) ((void)0)
10133 static int pgetc(void);
10134 static int
10135 preadbuffer(void)
10136 {
10137         char *q;
10138         int more;
10139
10140         if (g_parsefile->strpush) {
10141 #if ENABLE_ASH_ALIAS
10142                 if (g_parsefile->left_in_line == -1
10143                  && g_parsefile->strpush->ap
10144                  && g_parsefile->next_to_pgetc[-1] != ' '
10145                  && g_parsefile->next_to_pgetc[-1] != '\t'
10146                 ) {
10147                         pgetc_debug("preadbuffer PEOA");
10148                         return PEOA;
10149                 }
10150 #endif
10151                 popstring();
10152                 return pgetc();
10153         }
10154         /* on both branches above g_parsefile->left_in_line < 0.
10155          * "pgetc" needs refilling.
10156          */
10157
10158         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10159          * pungetc() may increment it a few times.
10160          * Assuming it won't increment it to less than -90.
10161          */
10162         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10163                 pgetc_debug("preadbuffer PEOF1");
10164                 /* even in failure keep left_in_line and next_to_pgetc
10165                  * in lock step, for correct multi-layer pungetc.
10166                  * left_in_line was decremented before preadbuffer(),
10167                  * must inc next_to_pgetc: */
10168                 g_parsefile->next_to_pgetc++;
10169                 return PEOF;
10170         }
10171
10172         more = g_parsefile->left_in_buffer;
10173         if (more <= 0) {
10174                 flush_stdout_stderr();
10175  again:
10176                 more = preadfd();
10177                 if (more <= 0) {
10178                         /* don't try reading again */
10179                         g_parsefile->left_in_line = -99;
10180                         pgetc_debug("preadbuffer PEOF2");
10181                         g_parsefile->next_to_pgetc++;
10182                         return PEOF;
10183                 }
10184         }
10185
10186         /* Find out where's the end of line.
10187          * Set g_parsefile->left_in_line
10188          * and g_parsefile->left_in_buffer acordingly.
10189          * NUL chars are deleted.
10190          */
10191         q = g_parsefile->next_to_pgetc;
10192         for (;;) {
10193                 char c;
10194
10195                 more--;
10196
10197                 c = *q;
10198                 if (c == '\0') {
10199                         memmove(q, q + 1, more);
10200                 } else {
10201                         q++;
10202                         if (c == '\n') {
10203                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10204                                 break;
10205                         }
10206                 }
10207
10208                 if (more <= 0) {
10209                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10210                         if (g_parsefile->left_in_line < 0)
10211                                 goto again;
10212                         break;
10213                 }
10214         }
10215         g_parsefile->left_in_buffer = more;
10216
10217         if (vflag) {
10218                 char save = *q;
10219                 *q = '\0';
10220                 out2str(g_parsefile->next_to_pgetc);
10221                 *q = save;
10222         }
10223
10224         pgetc_debug("preadbuffer at %d:%p'%s'",
10225                         g_parsefile->left_in_line,
10226                         g_parsefile->next_to_pgetc,
10227                         g_parsefile->next_to_pgetc);
10228         return (unsigned char)*g_parsefile->next_to_pgetc++;
10229 }
10230
10231 static void
10232 nlprompt(void)
10233 {
10234         g_parsefile->linno++;
10235         setprompt_if(doprompt, 2);
10236 }
10237 static void
10238 nlnoprompt(void)
10239 {
10240         g_parsefile->linno++;
10241         needprompt = doprompt;
10242 }
10243
10244 static int
10245 pgetc(void)
10246 {
10247         int c;
10248
10249         pgetc_debug("pgetc at %d:%p'%s'",
10250                         g_parsefile->left_in_line,
10251                         g_parsefile->next_to_pgetc,
10252                         g_parsefile->next_to_pgetc);
10253         if (g_parsefile->unget)
10254                 return g_parsefile->lastc[--g_parsefile->unget];
10255
10256         if (--g_parsefile->left_in_line >= 0)
10257                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10258         else
10259                 c = preadbuffer();
10260
10261         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10262         g_parsefile->lastc[0] = c;
10263
10264         return c;
10265 }
10266
10267 #if ENABLE_ASH_ALIAS
10268 static int
10269 pgetc_without_PEOA(void)
10270 {
10271         int c;
10272         do {
10273                 pgetc_debug("pgetc at %d:%p'%s'",
10274                                 g_parsefile->left_in_line,
10275                                 g_parsefile->next_to_pgetc,
10276                                 g_parsefile->next_to_pgetc);
10277                 c = pgetc();
10278         } while (c == PEOA);
10279         return c;
10280 }
10281 #else
10282 # define pgetc_without_PEOA() pgetc()
10283 #endif
10284
10285 /*
10286  * Read a line from the script.
10287  */
10288 static char *
10289 pfgets(char *line, int len)
10290 {
10291         char *p = line;
10292         int nleft = len;
10293         int c;
10294
10295         while (--nleft > 0) {
10296                 c = pgetc_without_PEOA();
10297                 if (c == PEOF) {
10298                         if (p == line)
10299                                 return NULL;
10300                         break;
10301                 }
10302                 *p++ = c;
10303                 if (c == '\n')
10304                         break;
10305         }
10306         *p = '\0';
10307         return line;
10308 }
10309
10310 /*
10311  * Undo a call to pgetc.  Only two characters may be pushed back.
10312  * PEOF may be pushed back.
10313  */
10314 static void
10315 pungetc(void)
10316 {
10317         g_parsefile->unget++;
10318 }
10319
10320 /* This one eats backslash+newline */
10321 static int
10322 pgetc_eatbnl(void)
10323 {
10324         int c;
10325
10326         while ((c = pgetc()) == '\\') {
10327                 if (pgetc() != '\n') {
10328                         pungetc();
10329                         break;
10330                 }
10331
10332                 nlprompt();
10333         }
10334
10335         return c;
10336 }
10337
10338 /*
10339  * To handle the "." command, a stack of input files is used.  Pushfile
10340  * adds a new entry to the stack and popfile restores the previous level.
10341  */
10342 static void
10343 pushfile(void)
10344 {
10345         struct parsefile *pf;
10346
10347         pf = ckzalloc(sizeof(*pf));
10348         pf->prev = g_parsefile;
10349         pf->pf_fd = -1;
10350         /*pf->strpush = NULL; - ckzalloc did it */
10351         /*pf->basestrpush.prev = NULL;*/
10352         /*pf->unget = 0;*/
10353         g_parsefile = pf;
10354 }
10355
10356 static void
10357 popfile(void)
10358 {
10359         struct parsefile *pf = g_parsefile;
10360
10361         if (pf == &basepf)
10362                 return;
10363
10364         INT_OFF;
10365         if (pf->pf_fd >= 0)
10366                 close(pf->pf_fd);
10367         free(pf->buf);
10368         while (pf->strpush)
10369                 popstring();
10370         g_parsefile = pf->prev;
10371         free(pf);
10372         INT_ON;
10373 }
10374
10375 /*
10376  * Return to top level.
10377  */
10378 static void
10379 popallfiles(void)
10380 {
10381         while (g_parsefile != &basepf)
10382                 popfile();
10383 }
10384
10385 /*
10386  * Close the file(s) that the shell is reading commands from.  Called
10387  * after a fork is done.
10388  */
10389 static void
10390 closescript(void)
10391 {
10392         popallfiles();
10393         if (g_parsefile->pf_fd > 0) {
10394                 close(g_parsefile->pf_fd);
10395                 g_parsefile->pf_fd = 0;
10396         }
10397 }
10398
10399 /*
10400  * Like setinputfile, but takes an open file descriptor.  Call this with
10401  * interrupts off.
10402  */
10403 static void
10404 setinputfd(int fd, int push)
10405 {
10406         if (push) {
10407                 pushfile();
10408                 g_parsefile->buf = NULL;
10409         }
10410         g_parsefile->pf_fd = fd;
10411         if (g_parsefile->buf == NULL)
10412                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10413         g_parsefile->left_in_buffer = 0;
10414         g_parsefile->left_in_line = 0;
10415         g_parsefile->linno = 1;
10416 }
10417
10418 /*
10419  * Set the input to take input from a file.  If push is set, push the
10420  * old input onto the stack first.
10421  */
10422 static int
10423 setinputfile(const char *fname, int flags)
10424 {
10425         int fd;
10426
10427         INT_OFF;
10428         fd = open(fname, O_RDONLY);
10429         if (fd < 0) {
10430                 if (flags & INPUT_NOFILE_OK)
10431                         goto out;
10432                 exitstatus = 127;
10433                 ash_msg_and_raise_error("can't open '%s'", fname);
10434         }
10435         if (fd < 10)
10436                 fd = savefd(fd);
10437         else
10438                 close_on_exec_on(fd);
10439         setinputfd(fd, flags & INPUT_PUSH_FILE);
10440  out:
10441         INT_ON;
10442         return fd;
10443 }
10444
10445 /*
10446  * Like setinputfile, but takes input from a string.
10447  */
10448 static void
10449 setinputstring(char *string)
10450 {
10451         INT_OFF;
10452         pushfile();
10453         g_parsefile->next_to_pgetc = string;
10454         g_parsefile->left_in_line = strlen(string);
10455         g_parsefile->buf = NULL;
10456         g_parsefile->linno = 1;
10457         INT_ON;
10458 }
10459
10460
10461 /*
10462  * Routines to check for mail.
10463  */
10464
10465 #if ENABLE_ASH_MAIL
10466
10467 /* Hash of mtimes of mailboxes */
10468 static unsigned mailtime_hash;
10469 /* Set if MAIL or MAILPATH is changed. */
10470 static smallint mail_var_path_changed;
10471
10472 /*
10473  * Print appropriate message(s) if mail has arrived.
10474  * If mail_var_path_changed is set,
10475  * then the value of MAIL has mail_var_path_changed,
10476  * so we just update the values.
10477  */
10478 static void
10479 chkmail(void)
10480 {
10481         const char *mpath;
10482         char *p;
10483         char *q;
10484         unsigned new_hash;
10485         struct stackmark smark;
10486         struct stat statb;
10487
10488         setstackmark(&smark);
10489         mpath = mpathset() ? mpathval() : mailval();
10490         new_hash = 0;
10491         for (;;) {
10492                 p = path_advance(&mpath, nullstr);
10493                 if (p == NULL)
10494                         break;
10495                 if (*p == '\0')
10496                         continue;
10497                 for (q = p; *q; q++)
10498                         continue;
10499 #if DEBUG
10500                 if (q[-1] != '/')
10501                         abort();
10502 #endif
10503                 q[-1] = '\0';                   /* delete trailing '/' */
10504                 if (stat(p, &statb) < 0) {
10505                         continue;
10506                 }
10507                 /* Very simplistic "hash": just a sum of all mtimes */
10508                 new_hash += (unsigned)statb.st_mtime;
10509         }
10510         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10511                 if (mailtime_hash != 0)
10512                         out2str("you have mail\n");
10513                 mailtime_hash = new_hash;
10514         }
10515         mail_var_path_changed = 0;
10516         popstackmark(&smark);
10517 }
10518
10519 static void FAST_FUNC
10520 changemail(const char *val UNUSED_PARAM)
10521 {
10522         mail_var_path_changed = 1;
10523 }
10524
10525 #endif /* ASH_MAIL */
10526
10527
10528 /* ============ ??? */
10529
10530 /*
10531  * Set the shell parameters.
10532  */
10533 static void
10534 setparam(char **argv)
10535 {
10536         char **newparam;
10537         char **ap;
10538         int nparam;
10539
10540         for (nparam = 0; argv[nparam]; nparam++)
10541                 continue;
10542         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10543         while (*argv) {
10544                 *ap++ = ckstrdup(*argv++);
10545         }
10546         *ap = NULL;
10547         freeparam(&shellparam);
10548         shellparam.malloced = 1;
10549         shellparam.nparam = nparam;
10550         shellparam.p = newparam;
10551 #if ENABLE_ASH_GETOPTS
10552         shellparam.optind = 1;
10553         shellparam.optoff = -1;
10554 #endif
10555 }
10556
10557 /*
10558  * Process shell options.  The global variable argptr contains a pointer
10559  * to the argument list; we advance it past the options.
10560  *
10561  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10562  * For a non-interactive shell, an error condition encountered
10563  * by a special built-in ... shall cause the shell to write a diagnostic message
10564  * to standard error and exit as shown in the following table:
10565  * Error                                           Special Built-In
10566  * ...
10567  * Utility syntax error (option or operand error)  Shall exit
10568  * ...
10569  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10570  * we see that bash does not do that (set "finishes" with error code 1 instead,
10571  * and shell continues), and people rely on this behavior!
10572  * Testcase:
10573  * set -o barfoo 2>/dev/null
10574  * echo $?
10575  *
10576  * Oh well. Let's mimic that.
10577  */
10578 static int
10579 plus_minus_o(char *name, int val)
10580 {
10581         int i;
10582
10583         if (name) {
10584                 for (i = 0; i < NOPTS; i++) {
10585                         if (strcmp(name, optnames(i)) == 0) {
10586                                 optlist[i] = val;
10587                                 return 0;
10588                         }
10589                 }
10590                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10591                 return 1;
10592         }
10593         for (i = 0; i < NOPTS; i++) {
10594                 if (val) {
10595                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10596                 } else {
10597                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10598                 }
10599         }
10600         return 0;
10601 }
10602 static void
10603 setoption(int flag, int val)
10604 {
10605         int i;
10606
10607         for (i = 0; i < NOPTS; i++) {
10608                 if (optletters(i) == flag) {
10609                         optlist[i] = val;
10610                         return;
10611                 }
10612         }
10613         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10614         /* NOTREACHED */
10615 }
10616 static int
10617 options(int cmdline)
10618 {
10619         char *p;
10620         int val;
10621         int c;
10622
10623         if (cmdline)
10624                 minusc = NULL;
10625         while ((p = *argptr) != NULL) {
10626                 c = *p++;
10627                 if (c != '-' && c != '+')
10628                         break;
10629                 argptr++;
10630                 val = 0; /* val = 0 if c == '+' */
10631                 if (c == '-') {
10632                         val = 1;
10633                         if (p[0] == '\0' || LONE_DASH(p)) {
10634                                 if (!cmdline) {
10635                                         /* "-" means turn off -x and -v */
10636                                         if (p[0] == '\0')
10637                                                 xflag = vflag = 0;
10638                                         /* "--" means reset params */
10639                                         else if (*argptr == NULL)
10640                                                 setparam(argptr);
10641                                 }
10642                                 break;    /* "-" or "--" terminates options */
10643                         }
10644                 }
10645                 /* first char was + or - */
10646                 while ((c = *p++) != '\0') {
10647                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10648                         if (c == 'c' && cmdline) {
10649                                 minusc = p;     /* command is after shell args */
10650                         } else if (c == 'o') {
10651                                 if (plus_minus_o(*argptr, val)) {
10652                                         /* it already printed err message */
10653                                         return 1; /* error */
10654                                 }
10655                                 if (*argptr)
10656                                         argptr++;
10657                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10658                                 isloginsh = 1;
10659                         /* bash does not accept +-login, we also won't */
10660                         } else if (cmdline && val && (c == '-')) { /* long options */
10661                                 if (strcmp(p, "login") == 0)
10662                                         isloginsh = 1;
10663                                 break;
10664                         } else {
10665                                 setoption(c, val);
10666                         }
10667                 }
10668         }
10669         return 0;
10670 }
10671
10672 /*
10673  * The shift builtin command.
10674  */
10675 static int FAST_FUNC
10676 shiftcmd(int argc UNUSED_PARAM, char **argv)
10677 {
10678         int n;
10679         char **ap1, **ap2;
10680
10681         n = 1;
10682         if (argv[1])
10683                 n = number(argv[1]);
10684         if (n > shellparam.nparam)
10685                 n = 0; /* bash compat, was = shellparam.nparam; */
10686         INT_OFF;
10687         shellparam.nparam -= n;
10688         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10689                 if (shellparam.malloced)
10690                         free(*ap1);
10691         }
10692         ap2 = shellparam.p;
10693         while ((*ap2++ = *ap1++) != NULL)
10694                 continue;
10695 #if ENABLE_ASH_GETOPTS
10696         shellparam.optind = 1;
10697         shellparam.optoff = -1;
10698 #endif
10699         INT_ON;
10700         return 0;
10701 }
10702
10703 /*
10704  * POSIX requires that 'set' (but not export or readonly) output the
10705  * variables in lexicographic order - by the locale's collating order (sigh).
10706  * Maybe we could keep them in an ordered balanced binary tree
10707  * instead of hashed lists.
10708  * For now just roll 'em through qsort for printing...
10709  */
10710 static int
10711 showvars(const char *sep_prefix, int on, int off)
10712 {
10713         const char *sep;
10714         char **ep, **epend;
10715
10716         ep = listvars(on, off, &epend);
10717         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10718
10719         sep = *sep_prefix ? " " : sep_prefix;
10720
10721         for (; ep < epend; ep++) {
10722                 const char *p;
10723                 const char *q;
10724
10725                 p = strchrnul(*ep, '=');
10726                 q = nullstr;
10727                 if (*p)
10728                         q = single_quote(++p);
10729                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10730         }
10731         return 0;
10732 }
10733
10734 /*
10735  * The set command builtin.
10736  */
10737 static int FAST_FUNC
10738 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10739 {
10740         int retval;
10741
10742         if (!argv[1])
10743                 return showvars(nullstr, 0, VUNSET);
10744
10745         INT_OFF;
10746         retval = options(/*cmdline:*/ 0);
10747         if (retval == 0) { /* if no parse error... */
10748                 optschanged();
10749                 if (*argptr != NULL) {
10750                         setparam(argptr);
10751                 }
10752         }
10753         INT_ON;
10754         return retval;
10755 }
10756
10757 #if ENABLE_ASH_RANDOM_SUPPORT
10758 static void FAST_FUNC
10759 change_random(const char *value)
10760 {
10761         uint32_t t;
10762
10763         if (value == NULL) {
10764                 /* "get", generate */
10765                 t = next_random(&random_gen);
10766                 /* set without recursion */
10767                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10768                 vrandom.flags &= ~VNOFUNC;
10769         } else {
10770                 /* set/reset */
10771                 t = strtoul(value, NULL, 10);
10772                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10773         }
10774 }
10775 #endif
10776
10777 #if ENABLE_ASH_GETOPTS
10778 static int
10779 getopts(char *optstr, char *optvar, char **optfirst)
10780 {
10781         char *p, *q;
10782         char c = '?';
10783         int done = 0;
10784         char sbuf[2];
10785         char **optnext;
10786         int ind = shellparam.optind;
10787         int off = shellparam.optoff;
10788
10789         sbuf[1] = '\0';
10790
10791         shellparam.optind = -1;
10792         optnext = optfirst + ind - 1;
10793
10794         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10795                 p = NULL;
10796         else
10797                 p = optnext[-1] + off;
10798         if (p == NULL || *p == '\0') {
10799                 /* Current word is done, advance */
10800                 p = *optnext;
10801                 if (p == NULL || *p != '-' || *++p == '\0') {
10802  atend:
10803                         p = NULL;
10804                         done = 1;
10805                         goto out;
10806                 }
10807                 optnext++;
10808                 if (LONE_DASH(p))        /* check for "--" */
10809                         goto atend;
10810         }
10811
10812         c = *p++;
10813         for (q = optstr; *q != c;) {
10814                 if (*q == '\0') {
10815                         if (optstr[0] == ':') {
10816                                 sbuf[0] = c;
10817                                 /*sbuf[1] = '\0'; - already is */
10818                                 setvar0("OPTARG", sbuf);
10819                         } else {
10820                                 fprintf(stderr, "Illegal option -%c\n", c);
10821                                 unsetvar("OPTARG");
10822                         }
10823                         c = '?';
10824                         goto out;
10825                 }
10826                 if (*++q == ':')
10827                         q++;
10828         }
10829
10830         if (*++q == ':') {
10831                 if (*p == '\0' && (p = *optnext) == NULL) {
10832                         if (optstr[0] == ':') {
10833                                 sbuf[0] = c;
10834                                 /*sbuf[1] = '\0'; - already is */
10835                                 setvar0("OPTARG", sbuf);
10836                                 c = ':';
10837                         } else {
10838                                 fprintf(stderr, "No arg for -%c option\n", c);
10839                                 unsetvar("OPTARG");
10840                                 c = '?';
10841                         }
10842                         goto out;
10843                 }
10844
10845                 if (p == *optnext)
10846                         optnext++;
10847                 setvar0("OPTARG", p);
10848                 p = NULL;
10849         } else
10850                 setvar0("OPTARG", nullstr);
10851  out:
10852         ind = optnext - optfirst + 1;
10853         setvar("OPTIND", itoa(ind), VNOFUNC);
10854         sbuf[0] = c;
10855         /*sbuf[1] = '\0'; - already is */
10856         setvar0(optvar, sbuf);
10857
10858         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10859         shellparam.optind = ind;
10860
10861         return done;
10862 }
10863
10864 /*
10865  * The getopts builtin.  Shellparam.optnext points to the next argument
10866  * to be processed.  Shellparam.optptr points to the next character to
10867  * be processed in the current argument.  If shellparam.optnext is NULL,
10868  * then it's the first time getopts has been called.
10869  */
10870 static int FAST_FUNC
10871 getoptscmd(int argc, char **argv)
10872 {
10873         char **optbase;
10874
10875         if (argc < 3)
10876                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10877         if (argc == 3) {
10878                 optbase = shellparam.p;
10879                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10880                         shellparam.optind = 1;
10881                         shellparam.optoff = -1;
10882                 }
10883         } else {
10884                 optbase = &argv[3];
10885                 if ((unsigned)shellparam.optind > argc - 2) {
10886                         shellparam.optind = 1;
10887                         shellparam.optoff = -1;
10888                 }
10889         }
10890
10891         return getopts(argv[1], argv[2], optbase);
10892 }
10893 #endif /* ASH_GETOPTS */
10894
10895
10896 /* ============ Shell parser */
10897
10898 struct heredoc {
10899         struct heredoc *next;   /* next here document in list */
10900         union node *here;       /* redirection node */
10901         char *eofmark;          /* string indicating end of input */
10902         smallint striptabs;     /* if set, strip leading tabs */
10903 };
10904
10905 static smallint tokpushback;           /* last token pushed back */
10906 static smallint quoteflag;             /* set if (part of) last token was quoted */
10907 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10908 static struct heredoc *heredoclist;    /* list of here documents to read */
10909 static char *wordtext;                 /* text of last word returned by readtoken */
10910 static struct nodelist *backquotelist;
10911 static union node *redirnode;
10912 static struct heredoc *heredoc;
10913
10914 static const char *
10915 tokname(char *buf, int tok)
10916 {
10917         if (tok < TSEMI)
10918                 return tokname_array[tok];
10919         sprintf(buf, "\"%s\"", tokname_array[tok]);
10920         return buf;
10921 }
10922
10923 /* raise_error_unexpected_syntax:
10924  * Called when an unexpected token is read during the parse.  The argument
10925  * is the token that is expected, or -1 if more than one type of token can
10926  * occur at this point.
10927  */
10928 static void raise_error_unexpected_syntax(int) NORETURN;
10929 static void
10930 raise_error_unexpected_syntax(int token)
10931 {
10932         char msg[64];
10933         char buf[16];
10934         int l;
10935
10936         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10937         if (token >= 0)
10938                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10939         raise_error_syntax(msg);
10940         /* NOTREACHED */
10941 }
10942
10943 #define EOFMARKLEN 79
10944
10945 /* parsing is heavily cross-recursive, need these forward decls */
10946 static union node *andor(void);
10947 static union node *pipeline(void);
10948 static union node *parse_command(void);
10949 static void parseheredoc(void);
10950 static int peektoken(void);
10951 static int readtoken(void);
10952
10953 static union node *
10954 list(int nlflag)
10955 {
10956         union node *n1, *n2, *n3;
10957         int tok;
10958
10959         n1 = NULL;
10960         for (;;) {
10961                 switch (peektoken()) {
10962                 case TNL:
10963                         if (!(nlflag & 1))
10964                                 break;
10965                         parseheredoc();
10966                         return n1;
10967
10968                 case TEOF:
10969                         if (!n1 && (nlflag & 1))
10970                                 n1 = NODE_EOF;
10971                         parseheredoc();
10972                         return n1;
10973                 }
10974
10975                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10976                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10977                         return n1;
10978                 nlflag |= 2;
10979
10980                 n2 = andor();
10981                 tok = readtoken();
10982                 if (tok == TBACKGND) {
10983                         if (n2->type == NPIPE) {
10984                                 n2->npipe.pipe_backgnd = 1;
10985                         } else {
10986                                 if (n2->type != NREDIR) {
10987                                         n3 = stzalloc(sizeof(struct nredir));
10988                                         n3->nredir.n = n2;
10989                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10990                                         n2 = n3;
10991                                 }
10992                                 n2->type = NBACKGND;
10993                         }
10994                 }
10995                 if (n1 == NULL) {
10996                         n1 = n2;
10997                 } else {
10998                         n3 = stzalloc(sizeof(struct nbinary));
10999                         n3->type = NSEMI;
11000                         n3->nbinary.ch1 = n1;
11001                         n3->nbinary.ch2 = n2;
11002                         n1 = n3;
11003                 }
11004                 switch (tok) {
11005                 case TNL:
11006                 case TEOF:
11007                         tokpushback = 1;
11008                         /* fall through */
11009                 case TBACKGND:
11010                 case TSEMI:
11011                         break;
11012                 default:
11013                         if ((nlflag & 1))
11014                                 raise_error_unexpected_syntax(-1);
11015                         tokpushback = 1;
11016                         return n1;
11017                 }
11018         }
11019 }
11020
11021 static union node *
11022 andor(void)
11023 {
11024         union node *n1, *n2, *n3;
11025         int t;
11026
11027         n1 = pipeline();
11028         for (;;) {
11029                 t = readtoken();
11030                 if (t == TAND) {
11031                         t = NAND;
11032                 } else if (t == TOR) {
11033                         t = NOR;
11034                 } else {
11035                         tokpushback = 1;
11036                         return n1;
11037                 }
11038                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11039                 n2 = pipeline();
11040                 n3 = stzalloc(sizeof(struct nbinary));
11041                 n3->type = t;
11042                 n3->nbinary.ch1 = n1;
11043                 n3->nbinary.ch2 = n2;
11044                 n1 = n3;
11045         }
11046 }
11047
11048 static union node *
11049 pipeline(void)
11050 {
11051         union node *n1, *n2, *pipenode;
11052         struct nodelist *lp, *prev;
11053         int negate;
11054
11055         negate = 0;
11056         TRACE(("pipeline: entered\n"));
11057         if (readtoken() == TNOT) {
11058                 negate = !negate;
11059                 checkkwd = CHKKWD | CHKALIAS;
11060         } else
11061                 tokpushback = 1;
11062         n1 = parse_command();
11063         if (readtoken() == TPIPE) {
11064                 pipenode = stzalloc(sizeof(struct npipe));
11065                 pipenode->type = NPIPE;
11066                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11067                 lp = stzalloc(sizeof(struct nodelist));
11068                 pipenode->npipe.cmdlist = lp;
11069                 lp->n = n1;
11070                 do {
11071                         prev = lp;
11072                         lp = stzalloc(sizeof(struct nodelist));
11073                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11074                         lp->n = parse_command();
11075                         prev->next = lp;
11076                 } while (readtoken() == TPIPE);
11077                 lp->next = NULL;
11078                 n1 = pipenode;
11079         }
11080         tokpushback = 1;
11081         if (negate) {
11082                 n2 = stzalloc(sizeof(struct nnot));
11083                 n2->type = NNOT;
11084                 n2->nnot.com = n1;
11085                 return n2;
11086         }
11087         return n1;
11088 }
11089
11090 static union node *
11091 makename(void)
11092 {
11093         union node *n;
11094
11095         n = stzalloc(sizeof(struct narg));
11096         n->type = NARG;
11097         /*n->narg.next = NULL; - stzalloc did it */
11098         n->narg.text = wordtext;
11099         n->narg.backquote = backquotelist;
11100         return n;
11101 }
11102
11103 static void
11104 fixredir(union node *n, const char *text, int err)
11105 {
11106         int fd;
11107
11108         TRACE(("Fix redir %s %d\n", text, err));
11109         if (!err)
11110                 n->ndup.vname = NULL;
11111
11112         fd = bb_strtou(text, NULL, 10);
11113         if (!errno && fd >= 0)
11114                 n->ndup.dupfd = fd;
11115         else if (LONE_DASH(text))
11116                 n->ndup.dupfd = -1;
11117         else {
11118                 if (err)
11119                         raise_error_syntax("bad fd number");
11120                 n->ndup.vname = makename();
11121         }
11122 }
11123
11124 /*
11125  * Returns true if the text contains nothing to expand (no dollar signs
11126  * or backquotes).
11127  */
11128 static int
11129 noexpand(const char *text)
11130 {
11131         unsigned char c;
11132
11133         while ((c = *text++) != '\0') {
11134                 if (c == CTLQUOTEMARK)
11135                         continue;
11136                 if (c == CTLESC)
11137                         text++;
11138                 else if (SIT(c, BASESYNTAX) == CCTL)
11139                         return 0;
11140         }
11141         return 1;
11142 }
11143
11144 static void
11145 parsefname(void)
11146 {
11147         union node *n = redirnode;
11148
11149         if (readtoken() != TWORD)
11150                 raise_error_unexpected_syntax(-1);
11151         if (n->type == NHERE) {
11152                 struct heredoc *here = heredoc;
11153                 struct heredoc *p;
11154                 int i;
11155
11156                 if (quoteflag == 0)
11157                         n->type = NXHERE;
11158                 TRACE(("Here document %d\n", n->type));
11159                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11160                         raise_error_syntax("illegal eof marker for << redirection");
11161                 rmescapes(wordtext, 0);
11162                 here->eofmark = wordtext;
11163                 here->next = NULL;
11164                 if (heredoclist == NULL)
11165                         heredoclist = here;
11166                 else {
11167                         for (p = heredoclist; p->next; p = p->next)
11168                                 continue;
11169                         p->next = here;
11170                 }
11171         } else if (n->type == NTOFD || n->type == NFROMFD) {
11172                 fixredir(n, wordtext, 0);
11173         } else {
11174                 n->nfile.fname = makename();
11175         }
11176 }
11177
11178 static union node *
11179 simplecmd(void)
11180 {
11181         union node *args, **app;
11182         union node *n = NULL;
11183         union node *vars, **vpp;
11184         union node **rpp, *redir;
11185         int savecheckkwd;
11186 #if BASH_TEST2
11187         smallint double_brackets_flag = 0;
11188 #endif
11189         IF_BASH_FUNCTION(smallint function_flag = 0;)
11190
11191         args = NULL;
11192         app = &args;
11193         vars = NULL;
11194         vpp = &vars;
11195         redir = NULL;
11196         rpp = &redir;
11197
11198         savecheckkwd = CHKALIAS;
11199         for (;;) {
11200                 int t;
11201                 checkkwd = savecheckkwd;
11202                 t = readtoken();
11203                 switch (t) {
11204 #if BASH_FUNCTION
11205                 case TFUNCTION:
11206                         if (peektoken() != TWORD)
11207                                 raise_error_unexpected_syntax(TWORD);
11208                         function_flag = 1;
11209                         break;
11210 #endif
11211 #if BASH_TEST2
11212                 case TAND: /* "&&" */
11213                 case TOR: /* "||" */
11214                         if (!double_brackets_flag) {
11215                                 tokpushback = 1;
11216                                 goto out;
11217                         }
11218                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11219 #endif
11220                 case TWORD:
11221                         n = stzalloc(sizeof(struct narg));
11222                         n->type = NARG;
11223                         /*n->narg.next = NULL; - stzalloc did it */
11224                         n->narg.text = wordtext;
11225 #if BASH_TEST2
11226                         if (strcmp("[[", wordtext) == 0)
11227                                 double_brackets_flag = 1;
11228                         else if (strcmp("]]", wordtext) == 0)
11229                                 double_brackets_flag = 0;
11230 #endif
11231                         n->narg.backquote = backquotelist;
11232                         if (savecheckkwd && isassignment(wordtext)) {
11233                                 *vpp = n;
11234                                 vpp = &n->narg.next;
11235                         } else {
11236                                 *app = n;
11237                                 app = &n->narg.next;
11238                                 savecheckkwd = 0;
11239                         }
11240 #if BASH_FUNCTION
11241                         if (function_flag) {
11242                                 checkkwd = CHKNL | CHKKWD;
11243                                 switch (peektoken()) {
11244                                 case TBEGIN:
11245                                 case TIF:
11246                                 case TCASE:
11247                                 case TUNTIL:
11248                                 case TWHILE:
11249                                 case TFOR:
11250                                         goto do_func;
11251                                 case TLP:
11252                                         function_flag = 0;
11253                                         break;
11254                                 case TWORD:
11255                                         if (strcmp("[[", wordtext) == 0)
11256                                                 goto do_func;
11257                                         /* fall through */
11258                                 default:
11259                                         raise_error_unexpected_syntax(-1);
11260                                 }
11261                         }
11262 #endif
11263                         break;
11264                 case TREDIR:
11265                         *rpp = n = redirnode;
11266                         rpp = &n->nfile.next;
11267                         parsefname();   /* read name of redirection file */
11268                         break;
11269                 case TLP:
11270  IF_BASH_FUNCTION(do_func:)
11271                         if (args && app == &args->narg.next
11272                          && !vars && !redir
11273                         ) {
11274                                 struct builtincmd *bcmd;
11275                                 const char *name;
11276
11277                                 /* We have a function */
11278                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11279                                         raise_error_unexpected_syntax(TRP);
11280                                 name = n->narg.text;
11281                                 if (!goodname(name)
11282                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11283                                 ) {
11284                                         raise_error_syntax("bad function name");
11285                                 }
11286                                 n->type = NDEFUN;
11287                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11288                                 n->narg.next = parse_command();
11289                                 return n;
11290                         }
11291                         IF_BASH_FUNCTION(function_flag = 0;)
11292                         /* fall through */
11293                 default:
11294                         tokpushback = 1;
11295                         goto out;
11296                 }
11297         }
11298  out:
11299         *app = NULL;
11300         *vpp = NULL;
11301         *rpp = NULL;
11302         n = stzalloc(sizeof(struct ncmd));
11303         n->type = NCMD;
11304         n->ncmd.args = args;
11305         n->ncmd.assign = vars;
11306         n->ncmd.redirect = redir;
11307         return n;
11308 }
11309
11310 static union node *
11311 parse_command(void)
11312 {
11313         union node *n1, *n2;
11314         union node *ap, **app;
11315         union node *cp, **cpp;
11316         union node *redir, **rpp;
11317         union node **rpp2;
11318         int t;
11319
11320         redir = NULL;
11321         rpp2 = &redir;
11322
11323         switch (readtoken()) {
11324         default:
11325                 raise_error_unexpected_syntax(-1);
11326                 /* NOTREACHED */
11327         case TIF:
11328                 n1 = stzalloc(sizeof(struct nif));
11329                 n1->type = NIF;
11330                 n1->nif.test = list(0);
11331                 if (readtoken() != TTHEN)
11332                         raise_error_unexpected_syntax(TTHEN);
11333                 n1->nif.ifpart = list(0);
11334                 n2 = n1;
11335                 while (readtoken() == TELIF) {
11336                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11337                         n2 = n2->nif.elsepart;
11338                         n2->type = NIF;
11339                         n2->nif.test = list(0);
11340                         if (readtoken() != TTHEN)
11341                                 raise_error_unexpected_syntax(TTHEN);
11342                         n2->nif.ifpart = list(0);
11343                 }
11344                 if (lasttoken == TELSE)
11345                         n2->nif.elsepart = list(0);
11346                 else {
11347                         n2->nif.elsepart = NULL;
11348                         tokpushback = 1;
11349                 }
11350                 t = TFI;
11351                 break;
11352         case TWHILE:
11353         case TUNTIL: {
11354                 int got;
11355                 n1 = stzalloc(sizeof(struct nbinary));
11356                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11357                 n1->nbinary.ch1 = list(0);
11358                 got = readtoken();
11359                 if (got != TDO) {
11360                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11361                                         got == TWORD ? wordtext : ""));
11362                         raise_error_unexpected_syntax(TDO);
11363                 }
11364                 n1->nbinary.ch2 = list(0);
11365                 t = TDONE;
11366                 break;
11367         }
11368         case TFOR:
11369                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11370                         raise_error_syntax("bad for loop variable");
11371                 n1 = stzalloc(sizeof(struct nfor));
11372                 n1->type = NFOR;
11373                 n1->nfor.var = wordtext;
11374                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11375                 if (readtoken() == TIN) {
11376                         app = &ap;
11377                         while (readtoken() == TWORD) {
11378                                 n2 = stzalloc(sizeof(struct narg));
11379                                 n2->type = NARG;
11380                                 /*n2->narg.next = NULL; - stzalloc did it */
11381                                 n2->narg.text = wordtext;
11382                                 n2->narg.backquote = backquotelist;
11383                                 *app = n2;
11384                                 app = &n2->narg.next;
11385                         }
11386                         *app = NULL;
11387                         n1->nfor.args = ap;
11388                         if (lasttoken != TNL && lasttoken != TSEMI)
11389                                 raise_error_unexpected_syntax(-1);
11390                 } else {
11391                         n2 = stzalloc(sizeof(struct narg));
11392                         n2->type = NARG;
11393                         /*n2->narg.next = NULL; - stzalloc did it */
11394                         n2->narg.text = (char *)dolatstr;
11395                         /*n2->narg.backquote = NULL;*/
11396                         n1->nfor.args = n2;
11397                         /*
11398                          * Newline or semicolon here is optional (but note
11399                          * that the original Bourne shell only allowed NL).
11400                          */
11401                         if (lasttoken != TSEMI)
11402                                 tokpushback = 1;
11403                 }
11404                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11405                 if (readtoken() != TDO)
11406                         raise_error_unexpected_syntax(TDO);
11407                 n1->nfor.body = list(0);
11408                 t = TDONE;
11409                 break;
11410         case TCASE:
11411                 n1 = stzalloc(sizeof(struct ncase));
11412                 n1->type = NCASE;
11413                 if (readtoken() != TWORD)
11414                         raise_error_unexpected_syntax(TWORD);
11415                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11416                 n2->type = NARG;
11417                 /*n2->narg.next = NULL; - stzalloc did it */
11418                 n2->narg.text = wordtext;
11419                 n2->narg.backquote = backquotelist;
11420                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11421                 if (readtoken() != TIN)
11422                         raise_error_unexpected_syntax(TIN);
11423                 cpp = &n1->ncase.cases;
11424  next_case:
11425                 checkkwd = CHKNL | CHKKWD;
11426                 t = readtoken();
11427                 while (t != TESAC) {
11428                         if (lasttoken == TLP)
11429                                 readtoken();
11430                         *cpp = cp = stzalloc(sizeof(struct nclist));
11431                         cp->type = NCLIST;
11432                         app = &cp->nclist.pattern;
11433                         for (;;) {
11434                                 *app = ap = stzalloc(sizeof(struct narg));
11435                                 ap->type = NARG;
11436                                 /*ap->narg.next = NULL; - stzalloc did it */
11437                                 ap->narg.text = wordtext;
11438                                 ap->narg.backquote = backquotelist;
11439                                 if (readtoken() != TPIPE)
11440                                         break;
11441                                 app = &ap->narg.next;
11442                                 readtoken();
11443                         }
11444                         //ap->narg.next = NULL;
11445                         if (lasttoken != TRP)
11446                                 raise_error_unexpected_syntax(TRP);
11447                         cp->nclist.body = list(2);
11448
11449                         cpp = &cp->nclist.next;
11450
11451                         checkkwd = CHKNL | CHKKWD;
11452                         t = readtoken();
11453                         if (t != TESAC) {
11454                                 if (t != TENDCASE)
11455                                         raise_error_unexpected_syntax(TENDCASE);
11456                                 goto next_case;
11457                         }
11458                 }
11459                 *cpp = NULL;
11460                 goto redir;
11461         case TLP:
11462                 n1 = stzalloc(sizeof(struct nredir));
11463                 n1->type = NSUBSHELL;
11464                 n1->nredir.n = list(0);
11465                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11466                 t = TRP;
11467                 break;
11468         case TBEGIN:
11469                 n1 = list(0);
11470                 t = TEND;
11471                 break;
11472         IF_BASH_FUNCTION(case TFUNCTION:)
11473         case TWORD:
11474         case TREDIR:
11475                 tokpushback = 1;
11476                 return simplecmd();
11477         }
11478
11479         if (readtoken() != t)
11480                 raise_error_unexpected_syntax(t);
11481
11482  redir:
11483         /* Now check for redirection which may follow command */
11484         checkkwd = CHKKWD | CHKALIAS;
11485         rpp = rpp2;
11486         while (readtoken() == TREDIR) {
11487                 *rpp = n2 = redirnode;
11488                 rpp = &n2->nfile.next;
11489                 parsefname();
11490         }
11491         tokpushback = 1;
11492         *rpp = NULL;
11493         if (redir) {
11494                 if (n1->type != NSUBSHELL) {
11495                         n2 = stzalloc(sizeof(struct nredir));
11496                         n2->type = NREDIR;
11497                         n2->nredir.n = n1;
11498                         n1 = n2;
11499                 }
11500                 n1->nredir.redirect = redir;
11501         }
11502         return n1;
11503 }
11504
11505 #if BASH_DOLLAR_SQUOTE
11506 static int
11507 decode_dollar_squote(void)
11508 {
11509         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11510         int c, cnt;
11511         char *p;
11512         char buf[4];
11513
11514         c = pgetc();
11515         p = strchr(C_escapes, c);
11516         if (p) {
11517                 buf[0] = c;
11518                 p = buf;
11519                 cnt = 3;
11520                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11521                         do {
11522                                 c = pgetc();
11523                                 *++p = c;
11524                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11525                         pungetc();
11526                 } else if (c == 'x') { /* \xHH */
11527                         do {
11528                                 c = pgetc();
11529                                 *++p = c;
11530                         } while (isxdigit(c) && --cnt);
11531                         pungetc();
11532                         if (cnt == 3) { /* \x but next char is "bad" */
11533                                 c = 'x';
11534                                 goto unrecognized;
11535                         }
11536                 } else { /* simple seq like \\ or \t */
11537                         p++;
11538                 }
11539                 *p = '\0';
11540                 p = buf;
11541                 c = bb_process_escape_sequence((void*)&p);
11542         } else { /* unrecognized "\z": print both chars unless ' or " */
11543                 if (c != '\'' && c != '"') {
11544  unrecognized:
11545                         c |= 0x100; /* "please encode \, then me" */
11546                 }
11547         }
11548         return c;
11549 }
11550 #endif
11551
11552 /*
11553  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11554  * is not NULL, read a here document.  In the latter case, eofmark is the
11555  * word which marks the end of the document and striptabs is true if
11556  * leading tabs should be stripped from the document.  The argument c
11557  * is the first character of the input token or document.
11558  *
11559  * Because C does not have internal subroutines, I have simulated them
11560  * using goto's to implement the subroutine linkage.  The following macros
11561  * will run code that appears at the end of readtoken1.
11562  */
11563 #define CHECKEND()      {goto checkend; checkend_return:;}
11564 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11565 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11566 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11567 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11568 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11569 static int
11570 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11571 {
11572         /* NB: syntax parameter fits into smallint */
11573         /* c parameter is an unsigned char or PEOF or PEOA */
11574         char *out;
11575         size_t len;
11576         char line[EOFMARKLEN + 1];
11577         struct nodelist *bqlist;
11578         smallint quotef;
11579         smallint dblquote;
11580         smallint oldstyle;
11581         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11582         smallint pssyntax;   /* we are expanding a prompt string */
11583         int varnest;         /* levels of variables expansion */
11584         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11585         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11586         int dqvarnest;       /* levels of variables expansion within double quotes */
11587
11588         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11589
11590         startlinno = g_parsefile->linno;
11591         bqlist = NULL;
11592         quotef = 0;
11593         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11594         pssyntax = (syntax == PSSYNTAX);
11595         if (pssyntax)
11596                 syntax = DQSYNTAX;
11597         dblquote = (syntax == DQSYNTAX);
11598         varnest = 0;
11599         IF_FEATURE_SH_MATH(arinest = 0;)
11600         IF_FEATURE_SH_MATH(parenlevel = 0;)
11601         dqvarnest = 0;
11602
11603         STARTSTACKSTR(out);
11604  loop:
11605         /* For each line, until end of word */
11606         CHECKEND();     /* set c to PEOF if at end of here document */
11607         for (;;) {      /* until end of line or end of word */
11608                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11609                 switch (SIT(c, syntax)) {
11610                 case CNL:       /* '\n' */
11611                         if (syntax == BASESYNTAX)
11612                                 goto endword;   /* exit outer loop */
11613                         USTPUTC(c, out);
11614                         nlprompt();
11615                         c = pgetc();
11616                         goto loop;              /* continue outer loop */
11617                 case CWORD:
11618                         USTPUTC(c, out);
11619                         break;
11620                 case CCTL:
11621 #if BASH_DOLLAR_SQUOTE
11622                         if (c == '\\' && bash_dollar_squote) {
11623                                 c = decode_dollar_squote();
11624                                 if (c == '\0') {
11625                                         /* skip $'\000', $'\x00' (like bash) */
11626                                         break;
11627                                 }
11628                                 if (c & 0x100) {
11629                                         /* Unknown escape. Encode as '\z' */
11630                                         c = (unsigned char)c;
11631                                         if (eofmark == NULL || dblquote)
11632                                                 USTPUTC(CTLESC, out);
11633                                         USTPUTC('\\', out);
11634                                 }
11635                         }
11636 #endif
11637                         if (eofmark == NULL || dblquote)
11638                                 USTPUTC(CTLESC, out);
11639                         USTPUTC(c, out);
11640                         break;
11641                 case CBACK:     /* backslash */
11642                         c = pgetc_without_PEOA();
11643                         if (c == PEOF) {
11644                                 USTPUTC(CTLESC, out);
11645                                 USTPUTC('\\', out);
11646                                 pungetc();
11647                         } else if (c == '\n') {
11648                                 nlprompt();
11649                         } else {
11650                                 if (c == '$' && pssyntax) {
11651                                         USTPUTC(CTLESC, out);
11652                                         USTPUTC('\\', out);
11653                                 }
11654                                 /* Backslash is retained if we are in "str" and next char isn't special */
11655                                 if (dblquote
11656                                  && c != '\\'
11657                                  && c != '`'
11658                                  && c != '$'
11659                                  && (c != '"' || eofmark != NULL)
11660                                 ) {
11661                                         USTPUTC('\\', out);
11662                                 }
11663                                 USTPUTC(CTLESC, out);
11664                                 USTPUTC(c, out);
11665                                 quotef = 1;
11666                         }
11667                         break;
11668                 case CSQUOTE:
11669                         syntax = SQSYNTAX;
11670  quotemark:
11671                         if (eofmark == NULL) {
11672                                 USTPUTC(CTLQUOTEMARK, out);
11673                         }
11674                         break;
11675                 case CDQUOTE:
11676                         syntax = DQSYNTAX;
11677                         dblquote = 1;
11678                         goto quotemark;
11679                 case CENDQUOTE:
11680                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11681                         if (eofmark != NULL && varnest == 0) {
11682                                 USTPUTC(c, out);
11683                         } else {
11684                                 if (dqvarnest == 0) {
11685                                         syntax = BASESYNTAX;
11686                                         dblquote = 0;
11687                                 }
11688                                 quotef = 1;
11689                                 goto quotemark;
11690                         }
11691                         break;
11692                 case CVAR:      /* '$' */
11693                         PARSESUB();             /* parse substitution */
11694                         break;
11695                 case CENDVAR:   /* '}' */
11696                         if (varnest > 0) {
11697                                 varnest--;
11698                                 if (dqvarnest > 0) {
11699                                         dqvarnest--;
11700                                 }
11701                                 c = CTLENDVAR;
11702                         }
11703                         USTPUTC(c, out);
11704                         break;
11705 #if ENABLE_FEATURE_SH_MATH
11706                 case CLP:       /* '(' in arithmetic */
11707                         parenlevel++;
11708                         USTPUTC(c, out);
11709                         break;
11710                 case CRP:       /* ')' in arithmetic */
11711                         if (parenlevel > 0) {
11712                                 parenlevel--;
11713                         } else {
11714                                 if (pgetc_eatbnl() == ')') {
11715                                         c = CTLENDARI;
11716                                         if (--arinest == 0) {
11717                                                 syntax = prevsyntax;
11718                                         }
11719                                 } else {
11720                                         /*
11721                                          * unbalanced parens
11722                                          * (don't 2nd guess - no error)
11723                                          */
11724                                         pungetc();
11725                                 }
11726                         }
11727                         USTPUTC(c, out);
11728                         break;
11729 #endif
11730                 case CBQUOTE:   /* '`' */
11731                         PARSEBACKQOLD();
11732                         break;
11733                 case CENDFILE:
11734                         goto endword;           /* exit outer loop */
11735                 case CIGN:
11736                         break;
11737                 default:
11738                         if (varnest == 0) {
11739 #if BASH_REDIR_OUTPUT
11740                                 if (c == '&') {
11741 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11742                                         if (pgetc() == '>')
11743                                                 c = 0x100 + '>'; /* flag &> */
11744                                         pungetc();
11745                                 }
11746 #endif
11747                                 goto endword;   /* exit outer loop */
11748                         }
11749                         IF_ASH_ALIAS(if (c != PEOA))
11750                                 USTPUTC(c, out);
11751                 }
11752                 c = pgetc();
11753         } /* for (;;) */
11754  endword:
11755
11756 #if ENABLE_FEATURE_SH_MATH
11757         if (syntax == ARISYNTAX)
11758                 raise_error_syntax("missing '))'");
11759 #endif
11760         if (syntax != BASESYNTAX && eofmark == NULL)
11761                 raise_error_syntax("unterminated quoted string");
11762         if (varnest != 0) {
11763                 startlinno = g_parsefile->linno;
11764                 /* { */
11765                 raise_error_syntax("missing '}'");
11766         }
11767         USTPUTC('\0', out);
11768         len = out - (char *)stackblock();
11769         out = stackblock();
11770         if (eofmark == NULL) {
11771                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11772                  && quotef == 0
11773                 ) {
11774                         if (isdigit_str9(out)) {
11775                                 PARSEREDIR(); /* passed as params: out, c */
11776                                 lasttoken = TREDIR;
11777                                 return lasttoken;
11778                         }
11779                         /* else: non-number X seen, interpret it
11780                          * as "NNNX>file" = "NNNX >file" */
11781                 }
11782                 pungetc();
11783         }
11784         quoteflag = quotef;
11785         backquotelist = bqlist;
11786         grabstackblock(len);
11787         wordtext = out;
11788         lasttoken = TWORD;
11789         return lasttoken;
11790 /* end of readtoken routine */
11791
11792 /*
11793  * Check to see whether we are at the end of the here document.  When this
11794  * is called, c is set to the first character of the next input line.  If
11795  * we are at the end of the here document, this routine sets the c to PEOF.
11796  */
11797 checkend: {
11798         if (eofmark) {
11799 #if ENABLE_ASH_ALIAS
11800                 if (c == PEOA)
11801                         c = pgetc_without_PEOA();
11802 #endif
11803                 if (striptabs) {
11804                         while (c == '\t') {
11805                                 c = pgetc_without_PEOA();
11806                         }
11807                 }
11808                 if (c == *eofmark) {
11809                         if (pfgets(line, sizeof(line)) != NULL) {
11810                                 char *p, *q;
11811                                 int cc;
11812
11813                                 p = line;
11814                                 for (q = eofmark + 1;; p++, q++) {
11815                                         cc = *p;
11816                                         if (cc == '\n')
11817                                                 cc = 0;
11818                                         if (!*q || cc != *q)
11819                                                 break;
11820                                 }
11821                                 if (cc == *q) {
11822                                         c = PEOF;
11823                                         nlnoprompt();
11824                                 } else {
11825                                         pushstring(line, NULL);
11826                                 }
11827                         }
11828                 }
11829         }
11830         goto checkend_return;
11831 }
11832
11833 /*
11834  * Parse a redirection operator.  The variable "out" points to a string
11835  * specifying the fd to be redirected.  The variable "c" contains the
11836  * first character of the redirection operator.
11837  */
11838 parseredir: {
11839         /* out is already checked to be a valid number or "" */
11840         int fd = (*out == '\0' ? -1 : atoi(out));
11841         union node *np;
11842
11843         np = stzalloc(sizeof(struct nfile));
11844         if (c == '>') {
11845                 np->nfile.fd = 1;
11846                 c = pgetc();
11847                 if (c == '>')
11848                         np->type = NAPPEND;
11849                 else if (c == '|')
11850                         np->type = NCLOBBER;
11851                 else if (c == '&')
11852                         np->type = NTOFD;
11853                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11854                 else {
11855                         np->type = NTO;
11856                         pungetc();
11857                 }
11858         }
11859 #if BASH_REDIR_OUTPUT
11860         else if (c == 0x100 + '>') { /* this flags &> redirection */
11861                 np->nfile.fd = 1;
11862                 pgetc(); /* this is '>', no need to check */
11863                 np->type = NTO2;
11864         }
11865 #endif
11866         else { /* c == '<' */
11867                 /*np->nfile.fd = 0; - stzalloc did it */
11868                 c = pgetc();
11869                 switch (c) {
11870                 case '<':
11871                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11872                                 np = stzalloc(sizeof(struct nhere));
11873                                 /*np->nfile.fd = 0; - stzalloc did it */
11874                         }
11875                         np->type = NHERE;
11876                         heredoc = stzalloc(sizeof(struct heredoc));
11877                         heredoc->here = np;
11878                         c = pgetc();
11879                         if (c == '-') {
11880                                 heredoc->striptabs = 1;
11881                         } else {
11882                                 /*heredoc->striptabs = 0; - stzalloc did it */
11883                                 pungetc();
11884                         }
11885                         break;
11886
11887                 case '&':
11888                         np->type = NFROMFD;
11889                         break;
11890
11891                 case '>':
11892                         np->type = NFROMTO;
11893                         break;
11894
11895                 default:
11896                         np->type = NFROM;
11897                         pungetc();
11898                         break;
11899                 }
11900         }
11901         if (fd >= 0)
11902                 np->nfile.fd = fd;
11903         redirnode = np;
11904         goto parseredir_return;
11905 }
11906
11907 /*
11908  * Parse a substitution.  At this point, we have read the dollar sign
11909  * and nothing else.
11910  */
11911
11912 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11913  * (assuming ascii char codes, as the original implementation did) */
11914 #define is_special(c) \
11915         (((unsigned)(c) - 33 < 32) \
11916                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11917 parsesub: {
11918         unsigned char subtype;
11919         int typeloc;
11920
11921         c = pgetc_eatbnl();
11922         if (c > 255 /* PEOA or PEOF */
11923          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11924         ) {
11925 #if BASH_DOLLAR_SQUOTE
11926                 if (syntax != DQSYNTAX && c == '\'')
11927                         bash_dollar_squote = 1;
11928                 else
11929 #endif
11930                         USTPUTC('$', out);
11931                 pungetc();
11932         } else if (c == '(') {
11933                 /* $(command) or $((arith)) */
11934                 if (pgetc_eatbnl() == '(') {
11935 #if ENABLE_FEATURE_SH_MATH
11936                         PARSEARITH();
11937 #else
11938                         raise_error_syntax("support for $((arith)) is disabled");
11939 #endif
11940                 } else {
11941                         pungetc();
11942                         PARSEBACKQNEW();
11943                 }
11944         } else {
11945                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11946                 USTPUTC(CTLVAR, out);
11947                 typeloc = out - (char *)stackblock();
11948                 STADJUST(1, out);
11949                 subtype = VSNORMAL;
11950                 if (c == '{') {
11951                         c = pgetc_eatbnl();
11952                         subtype = 0;
11953                 }
11954  varname:
11955                 if (is_name(c)) {
11956                         /* $[{[#]]NAME[}] */
11957                         do {
11958                                 STPUTC(c, out);
11959                                 c = pgetc_eatbnl();
11960                         } while (is_in_name(c));
11961                 } else if (isdigit(c)) {
11962                         /* $[{[#]]NUM[}] */
11963                         do {
11964                                 STPUTC(c, out);
11965                                 c = pgetc_eatbnl();
11966                         } while (isdigit(c));
11967                 } else if (is_special(c)) {
11968                         /* $[{[#]]<specialchar>[}] */
11969                         int cc = c;
11970
11971                         c = pgetc_eatbnl();
11972                         if (!subtype && cc == '#') {
11973                                 subtype = VSLENGTH;
11974                                 if (c == '_' || isalnum(c))
11975                                         goto varname;
11976                                 cc = c;
11977                                 c = pgetc_eatbnl();
11978                                 if (cc == '}' || c != '}') {
11979                                         pungetc();
11980                                         subtype = 0;
11981                                         c = cc;
11982                                         cc = '#';
11983                                 }
11984                         }
11985                         USTPUTC(cc, out);
11986                 } else {
11987                         goto badsub;
11988                 }
11989                 if (c != '}' && subtype == VSLENGTH) {
11990                         /* ${#VAR didn't end with } */
11991                         goto badsub;
11992                 }
11993
11994                 if (subtype == 0) {
11995                         static const char types[] ALIGN1 = "}-+?=";
11996                         /* ${VAR...} but not $VAR or ${#VAR} */
11997                         /* c == first char after VAR */
11998                         switch (c) {
11999                         case ':':
12000                                 c = pgetc_eatbnl();
12001 #if BASH_SUBSTR
12002                                 /* This check is only needed to not misinterpret
12003                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12004                                  * constructs.
12005                                  */
12006                                 if (!strchr(types, c)) {
12007                                         subtype = VSSUBSTR;
12008                                         pungetc();
12009                                         break; /* "goto badsub" is bigger (!) */
12010                                 }
12011 #endif
12012                                 subtype = VSNUL;
12013                                 /*FALLTHROUGH*/
12014                         default: {
12015                                 const char *p = strchr(types, c);
12016                                 if (p == NULL)
12017                                         break;
12018                                 subtype |= p - types + VSNORMAL;
12019                                 break;
12020                         }
12021                         case '%':
12022                         case '#': {
12023                                 int cc = c;
12024                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12025                                 c = pgetc_eatbnl();
12026                                 if (c != cc)
12027                                         goto badsub;
12028                                 subtype++;
12029                                 break;
12030                         }
12031 #if BASH_PATTERN_SUBST
12032                         case '/':
12033                                 /* ${v/[/]pattern/repl} */
12034 //TODO: encode pattern and repl separately.
12035 // Currently ${v/$var_with_slash/repl} is horribly broken
12036                                 subtype = VSREPLACE;
12037                                 c = pgetc_eatbnl();
12038                                 if (c != '/')
12039                                         goto badsub;
12040                                 subtype++; /* VSREPLACEALL */
12041                                 break;
12042 #endif
12043                         }
12044                 } else {
12045  badsub:
12046                         pungetc();
12047                 }
12048                 ((unsigned char *)stackblock())[typeloc] = subtype;
12049                 if (subtype != VSNORMAL) {
12050                         varnest++;
12051                         if (dblquote)
12052                                 dqvarnest++;
12053                 }
12054                 STPUTC('=', out);
12055         }
12056         goto parsesub_return;
12057 }
12058
12059 /*
12060  * Called to parse command substitutions.  Newstyle is set if the command
12061  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12062  * list of commands (passed by reference), and savelen is the number of
12063  * characters on the top of the stack which must be preserved.
12064  */
12065 parsebackq: {
12066         struct nodelist **nlpp;
12067         union node *n;
12068         char *str;
12069         size_t savelen;
12070         smallint saveprompt = 0;
12071
12072         str = NULL;
12073         savelen = out - (char *)stackblock();
12074         if (savelen > 0) {
12075                 /*
12076                  * FIXME: this can allocate very large block on stack and SEGV.
12077                  * Example:
12078                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12079                  * allocates 100kb for every command subst. With about
12080                  * a hundred command substitutions stack overflows.
12081                  * With larger prepended string, SEGV happens sooner.
12082                  */
12083                 str = alloca(savelen);
12084                 memcpy(str, stackblock(), savelen);
12085         }
12086
12087         if (oldstyle) {
12088                 /* We must read until the closing backquote, giving special
12089                  * treatment to some slashes, and then push the string and
12090                  * reread it as input, interpreting it normally.
12091                  */
12092                 char *pout;
12093                 size_t psavelen;
12094                 char *pstr;
12095
12096                 STARTSTACKSTR(pout);
12097                 for (;;) {
12098                         int pc;
12099
12100                         setprompt_if(needprompt, 2);
12101                         pc = pgetc();
12102                         switch (pc) {
12103                         case '`':
12104                                 goto done;
12105
12106                         case '\\':
12107                                 pc = pgetc();
12108                                 if (pc == '\n') {
12109                                         nlprompt();
12110                                         /*
12111                                          * If eating a newline, avoid putting
12112                                          * the newline into the new character
12113                                          * stream (via the STPUTC after the
12114                                          * switch).
12115                                          */
12116                                         continue;
12117                                 }
12118                                 if (pc != '\\' && pc != '`' && pc != '$'
12119                                  && (!dblquote || pc != '"')
12120                                 ) {
12121                                         STPUTC('\\', pout);
12122                                 }
12123                                 if (pc <= 255 /* not PEOA or PEOF */) {
12124                                         break;
12125                                 }
12126                                 /* fall through */
12127
12128                         case PEOF:
12129                         IF_ASH_ALIAS(case PEOA:)
12130                                 startlinno = g_parsefile->linno;
12131                                 raise_error_syntax("EOF in backquote substitution");
12132
12133                         case '\n':
12134                                 nlnoprompt();
12135                                 break;
12136
12137                         default:
12138                                 break;
12139                         }
12140                         STPUTC(pc, pout);
12141                 }
12142  done:
12143                 STPUTC('\0', pout);
12144                 psavelen = pout - (char *)stackblock();
12145                 if (psavelen > 0) {
12146                         pstr = grabstackstr(pout);
12147                         setinputstring(pstr);
12148                 }
12149         }
12150         nlpp = &bqlist;
12151         while (*nlpp)
12152                 nlpp = &(*nlpp)->next;
12153         *nlpp = stzalloc(sizeof(**nlpp));
12154         /* (*nlpp)->next = NULL; - stzalloc did it */
12155
12156         if (oldstyle) {
12157                 saveprompt = doprompt;
12158                 doprompt = 0;
12159         }
12160
12161         n = list(2);
12162
12163         if (oldstyle)
12164                 doprompt = saveprompt;
12165         else if (readtoken() != TRP)
12166                 raise_error_unexpected_syntax(TRP);
12167
12168         (*nlpp)->n = n;
12169         if (oldstyle) {
12170                 /*
12171                  * Start reading from old file again, ignoring any pushed back
12172                  * tokens left from the backquote parsing
12173                  */
12174                 popfile();
12175                 tokpushback = 0;
12176         }
12177         while (stackblocksize() <= savelen)
12178                 growstackblock();
12179         STARTSTACKSTR(out);
12180         if (str) {
12181                 memcpy(out, str, savelen);
12182                 STADJUST(savelen, out);
12183         }
12184         USTPUTC(CTLBACKQ, out);
12185         if (oldstyle)
12186                 goto parsebackq_oldreturn;
12187         goto parsebackq_newreturn;
12188 }
12189
12190 #if ENABLE_FEATURE_SH_MATH
12191 /*
12192  * Parse an arithmetic expansion (indicate start of one and set state)
12193  */
12194 parsearith: {
12195         if (++arinest == 1) {
12196                 prevsyntax = syntax;
12197                 syntax = ARISYNTAX;
12198         }
12199         USTPUTC(CTLARI, out);
12200         goto parsearith_return;
12201 }
12202 #endif
12203 } /* end of readtoken */
12204
12205 /*
12206  * Read the next input token.
12207  * If the token is a word, we set backquotelist to the list of cmds in
12208  *      backquotes.  We set quoteflag to true if any part of the word was
12209  *      quoted.
12210  * If the token is TREDIR, then we set redirnode to a structure containing
12211  *      the redirection.
12212  * In all cases, the variable startlinno is set to the number of the line
12213  *      on which the token starts.
12214  *
12215  * [Change comment:  here documents and internal procedures]
12216  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12217  *  word parsing code into a separate routine.  In this case, readtoken
12218  *  doesn't need to have any internal procedures, but parseword does.
12219  *  We could also make parseoperator in essence the main routine, and
12220  *  have parseword (readtoken1?) handle both words and redirection.]
12221  */
12222 #define NEW_xxreadtoken
12223 #ifdef NEW_xxreadtoken
12224 /* singles must be first! */
12225 static const char xxreadtoken_chars[7] ALIGN1 = {
12226         '\n', '(', ')', /* singles */
12227         '&', '|', ';',  /* doubles */
12228         0
12229 };
12230
12231 #define xxreadtoken_singles 3
12232 #define xxreadtoken_doubles 3
12233
12234 static const char xxreadtoken_tokens[] ALIGN1 = {
12235         TNL, TLP, TRP,          /* only single occurrence allowed */
12236         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12237         TEOF,                   /* corresponds to trailing nul */
12238         TAND, TOR, TENDCASE     /* if double occurrence */
12239 };
12240
12241 static int
12242 xxreadtoken(void)
12243 {
12244         int c;
12245
12246         if (tokpushback) {
12247                 tokpushback = 0;
12248                 return lasttoken;
12249         }
12250         setprompt_if(needprompt, 2);
12251         startlinno = g_parsefile->linno;
12252         for (;;) {                      /* until token or start of word found */
12253                 c = pgetc();
12254                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12255                         continue;
12256
12257                 if (c == '#') {
12258                         while ((c = pgetc()) != '\n' && c != PEOF)
12259                                 continue;
12260                         pungetc();
12261                 } else if (c == '\\') {
12262                         if (pgetc() != '\n') {
12263                                 pungetc();
12264                                 break; /* return readtoken1(...) */
12265                         }
12266                         nlprompt();
12267                 } else {
12268                         const char *p;
12269
12270                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12271                         if (c != PEOF) {
12272                                 if (c == '\n') {
12273                                         nlnoprompt();
12274                                 }
12275
12276                                 p = strchr(xxreadtoken_chars, c);
12277                                 if (p == NULL)
12278                                         break; /* return readtoken1(...) */
12279
12280                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12281                                         int cc = pgetc();
12282                                         if (cc == c) {    /* double occurrence? */
12283                                                 p += xxreadtoken_doubles + 1;
12284                                         } else {
12285                                                 pungetc();
12286 #if BASH_REDIR_OUTPUT
12287                                                 if (c == '&' && cc == '>') /* &> */
12288                                                         break; /* return readtoken1(...) */
12289 #endif
12290                                         }
12291                                 }
12292                         }
12293                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12294                         return lasttoken;
12295                 }
12296         } /* for (;;) */
12297
12298         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12299 }
12300 #else /* old xxreadtoken */
12301 #define RETURN(token)   return lasttoken = token
12302 static int
12303 xxreadtoken(void)
12304 {
12305         int c;
12306
12307         if (tokpushback) {
12308                 tokpushback = 0;
12309                 return lasttoken;
12310         }
12311         setprompt_if(needprompt, 2);
12312         startlinno = g_parsefile->linno;
12313         for (;;) {      /* until token or start of word found */
12314                 c = pgetc();
12315                 switch (c) {
12316                 case ' ': case '\t':
12317                 IF_ASH_ALIAS(case PEOA:)
12318                         continue;
12319                 case '#':
12320                         while ((c = pgetc()) != '\n' && c != PEOF)
12321                                 continue;
12322                         pungetc();
12323                         continue;
12324                 case '\\':
12325                         if (pgetc() == '\n') {
12326                                 nlprompt();
12327                                 continue;
12328                         }
12329                         pungetc();
12330                         goto breakloop;
12331                 case '\n':
12332                         nlnoprompt();
12333                         RETURN(TNL);
12334                 case PEOF:
12335                         RETURN(TEOF);
12336                 case '&':
12337                         if (pgetc() == '&')
12338                                 RETURN(TAND);
12339                         pungetc();
12340                         RETURN(TBACKGND);
12341                 case '|':
12342                         if (pgetc() == '|')
12343                                 RETURN(TOR);
12344                         pungetc();
12345                         RETURN(TPIPE);
12346                 case ';':
12347                         if (pgetc() == ';')
12348                                 RETURN(TENDCASE);
12349                         pungetc();
12350                         RETURN(TSEMI);
12351                 case '(':
12352                         RETURN(TLP);
12353                 case ')':
12354                         RETURN(TRP);
12355                 default:
12356                         goto breakloop;
12357                 }
12358         }
12359  breakloop:
12360         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12361 #undef RETURN
12362 }
12363 #endif /* old xxreadtoken */
12364
12365 static int
12366 readtoken(void)
12367 {
12368         int t;
12369         int kwd = checkkwd;
12370 #if DEBUG
12371         smallint alreadyseen = tokpushback;
12372 #endif
12373
12374 #if ENABLE_ASH_ALIAS
12375  top:
12376 #endif
12377
12378         t = xxreadtoken();
12379
12380         /*
12381          * eat newlines
12382          */
12383         if (kwd & CHKNL) {
12384                 while (t == TNL) {
12385                         parseheredoc();
12386                         t = xxreadtoken();
12387                 }
12388         }
12389
12390         if (t != TWORD || quoteflag) {
12391                 goto out;
12392         }
12393
12394         /*
12395          * check for keywords
12396          */
12397         if (kwd & CHKKWD) {
12398                 const char *const *pp;
12399
12400                 pp = findkwd(wordtext);
12401                 if (pp) {
12402                         lasttoken = t = pp - tokname_array;
12403                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12404                         goto out;
12405                 }
12406         }
12407
12408         if (checkkwd & CHKALIAS) {
12409 #if ENABLE_ASH_ALIAS
12410                 struct alias *ap;
12411                 ap = lookupalias(wordtext, 1);
12412                 if (ap != NULL) {
12413                         if (*ap->val) {
12414                                 pushstring(ap->val, ap);
12415                         }
12416                         goto top;
12417                 }
12418 #endif
12419         }
12420  out:
12421         checkkwd = 0;
12422 #if DEBUG
12423         if (!alreadyseen)
12424                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12425         else
12426                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12427 #endif
12428         return t;
12429 }
12430
12431 static int
12432 peektoken(void)
12433 {
12434         int t;
12435
12436         t = readtoken();
12437         tokpushback = 1;
12438         return t;
12439 }
12440
12441 /*
12442  * Read and parse a command.  Returns NODE_EOF on end of file.
12443  * (NULL is a valid parse tree indicating a blank line.)
12444  */
12445 static union node *
12446 parsecmd(int interact)
12447 {
12448         tokpushback = 0;
12449         checkkwd = 0;
12450         heredoclist = 0;
12451         doprompt = interact;
12452         setprompt_if(doprompt, doprompt);
12453         needprompt = 0;
12454         return list(1);
12455 }
12456
12457 /*
12458  * Input any here documents.
12459  */
12460 static void
12461 parseheredoc(void)
12462 {
12463         struct heredoc *here;
12464         union node *n;
12465
12466         here = heredoclist;
12467         heredoclist = NULL;
12468
12469         while (here) {
12470                 setprompt_if(needprompt, 2);
12471                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12472                                 here->eofmark, here->striptabs);
12473                 n = stzalloc(sizeof(struct narg));
12474                 n->narg.type = NARG;
12475                 /*n->narg.next = NULL; - stzalloc did it */
12476                 n->narg.text = wordtext;
12477                 n->narg.backquote = backquotelist;
12478                 here->here->nhere.doc = n;
12479                 here = here->next;
12480         }
12481 }
12482
12483
12484 /*
12485  * called by editline -- any expansions to the prompt should be added here.
12486  */
12487 static const char *
12488 expandstr(const char *ps)
12489 {
12490         union node n;
12491         int saveprompt;
12492
12493         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12494          * and token processing _can_ alter it (delete NULs etc). */
12495         setinputstring((char *)ps);
12496
12497         saveprompt = doprompt;
12498         doprompt = 0;
12499         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12500         doprompt = saveprompt;
12501
12502         popfile();
12503
12504         n.narg.type = NARG;
12505         n.narg.next = NULL;
12506         n.narg.text = wordtext;
12507         n.narg.backquote = backquotelist;
12508
12509         expandarg(&n, NULL, EXP_QUOTED);
12510         return stackblock();
12511 }
12512
12513 /*
12514  * Execute a command or commands contained in a string.
12515  */
12516 static int
12517 evalstring(char *s, int flags)
12518 {
12519         struct jmploc *volatile savehandler;
12520         struct jmploc jmploc;
12521         int ex;
12522
12523         union node *n;
12524         struct stackmark smark;
12525         int status;
12526
12527         s = sstrdup(s);
12528         setinputstring(s);
12529         setstackmark(&smark);
12530
12531         status = 0;
12532         /* On exception inside execution loop, we must popfile().
12533          * Try interactively:
12534          *      readonly a=a
12535          *      command eval "a=b"  # throws "is read only" error
12536          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12537          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12538          */
12539         savehandler = exception_handler;
12540         ex = setjmp(jmploc.loc);
12541         if (ex)
12542                 goto out;
12543         exception_handler = &jmploc;
12544
12545         while ((n = parsecmd(0)) != NODE_EOF) {
12546                 int i;
12547
12548                 i = evaltree(n, flags);
12549                 if (n)
12550                         status = i;
12551                 popstackmark(&smark);
12552                 if (evalskip)
12553                         break;
12554         }
12555  out:
12556         popstackmark(&smark);
12557         popfile();
12558         stunalloc(s);
12559
12560         exception_handler = savehandler;
12561         if (ex)
12562                 longjmp(exception_handler->loc, ex);
12563
12564         return status;
12565 }
12566
12567 /*
12568  * The eval command.
12569  */
12570 static int FAST_FUNC
12571 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12572 {
12573         char *p;
12574         char *concat;
12575
12576         if (argv[1]) {
12577                 p = argv[1];
12578                 argv += 2;
12579                 if (argv[0]) {
12580                         STARTSTACKSTR(concat);
12581                         for (;;) {
12582                                 concat = stack_putstr(p, concat);
12583                                 p = *argv++;
12584                                 if (p == NULL)
12585                                         break;
12586                                 STPUTC(' ', concat);
12587                         }
12588                         STPUTC('\0', concat);
12589                         p = grabstackstr(concat);
12590                 }
12591                 return evalstring(p, flags & EV_TESTED);
12592         }
12593         return 0;
12594 }
12595
12596 /*
12597  * Read and execute commands.
12598  * "Top" is nonzero for the top level command loop;
12599  * it turns on prompting if the shell is interactive.
12600  */
12601 static int
12602 cmdloop(int top)
12603 {
12604         union node *n;
12605         struct stackmark smark;
12606         int inter;
12607         int status = 0;
12608         int numeof = 0;
12609
12610         TRACE(("cmdloop(%d) called\n", top));
12611         for (;;) {
12612                 int skip;
12613
12614                 setstackmark(&smark);
12615 #if JOBS
12616                 if (doing_jobctl)
12617                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12618 #endif
12619                 inter = 0;
12620                 if (iflag && top) {
12621                         inter++;
12622                         chkmail();
12623                 }
12624                 n = parsecmd(inter);
12625 #if DEBUG
12626                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12627                         showtree(n);
12628 #endif
12629                 if (n == NODE_EOF) {
12630                         if (!top || numeof >= 50)
12631                                 break;
12632                         if (!stoppedjobs()) {
12633                                 if (!Iflag)
12634                                         break;
12635                                 out2str("\nUse \"exit\" to leave shell.\n");
12636                         }
12637                         numeof++;
12638                 } else if (nflag == 0) {
12639                         int i;
12640
12641                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12642                         job_warning >>= 1;
12643                         numeof = 0;
12644                         i = evaltree(n, 0);
12645                         if (n)
12646                                 status = i;
12647                 }
12648                 popstackmark(&smark);
12649                 skip = evalskip;
12650
12651                 if (skip) {
12652                         evalskip &= ~SKIPFUNC;
12653                         break;
12654                 }
12655         }
12656         return status;
12657 }
12658
12659 /*
12660  * Take commands from a file.  To be compatible we should do a path
12661  * search for the file, which is necessary to find sub-commands.
12662  */
12663 static char *
12664 find_dot_file(char *name)
12665 {
12666         char *fullname;
12667         const char *path = pathval();
12668         struct stat statb;
12669
12670         /* don't try this for absolute or relative paths */
12671         if (strchr(name, '/'))
12672                 return name;
12673
12674         while ((fullname = path_advance(&path, name)) != NULL) {
12675                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12676                         /*
12677                          * Don't bother freeing here, since it will
12678                          * be freed by the caller.
12679                          */
12680                         return fullname;
12681                 }
12682                 if (fullname != name)
12683                         stunalloc(fullname);
12684         }
12685
12686         /* not found in the PATH */
12687         ash_msg_and_raise_error("%s: not found", name);
12688         /* NOTREACHED */
12689 }
12690
12691 static int FAST_FUNC
12692 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12693 {
12694         /* "false; . empty_file; echo $?" should print 0, not 1: */
12695         int status = 0;
12696         char *fullname;
12697         char **argv;
12698         char *args_need_save;
12699         struct strlist *sp;
12700         volatile struct shparam saveparam;
12701
12702         for (sp = cmdenviron; sp; sp = sp->next)
12703                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12704
12705         nextopt(nullstr); /* handle possible "--" */
12706         argv = argptr;
12707
12708         if (!argv[0]) {
12709                 /* bash says: "bash: .: filename argument required" */
12710                 return 2; /* bash compat */
12711         }
12712
12713         /* This aborts if file isn't found, which is POSIXly correct.
12714          * bash returns exitcode 1 instead.
12715          */
12716         fullname = find_dot_file(argv[0]);
12717         argv++;
12718         args_need_save = argv[0];
12719         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12720                 int argc;
12721                 saveparam = shellparam;
12722                 shellparam.malloced = 0;
12723                 argc = 1;
12724                 while (argv[argc])
12725                         argc++;
12726                 shellparam.nparam = argc;
12727                 shellparam.p = argv;
12728         };
12729
12730         /* This aborts if file can't be opened, which is POSIXly correct.
12731          * bash returns exitcode 1 instead.
12732          */
12733         setinputfile(fullname, INPUT_PUSH_FILE);
12734         commandname = fullname;
12735         status = cmdloop(0);
12736         popfile();
12737
12738         if (args_need_save) {
12739                 freeparam(&shellparam);
12740                 shellparam = saveparam;
12741         };
12742
12743         return status;
12744 }
12745
12746 static int FAST_FUNC
12747 exitcmd(int argc UNUSED_PARAM, char **argv)
12748 {
12749         if (stoppedjobs())
12750                 return 0;
12751         if (argv[1])
12752                 exitstatus = number(argv[1]);
12753         raise_exception(EXEXIT);
12754         /* NOTREACHED */
12755 }
12756
12757 /*
12758  * Read a file containing shell functions.
12759  */
12760 static void
12761 readcmdfile(char *name)
12762 {
12763         setinputfile(name, INPUT_PUSH_FILE);
12764         cmdloop(0);
12765         popfile();
12766 }
12767
12768
12769 /* ============ find_command inplementation */
12770
12771 /*
12772  * Resolve a command name.  If you change this routine, you may have to
12773  * change the shellexec routine as well.
12774  */
12775 static void
12776 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12777 {
12778         struct tblentry *cmdp;
12779         int idx;
12780         int prev;
12781         char *fullname;
12782         struct stat statb;
12783         int e;
12784         int updatetbl;
12785         struct builtincmd *bcmd;
12786
12787         /* If name contains a slash, don't use PATH or hash table */
12788         if (strchr(name, '/') != NULL) {
12789                 entry->u.index = -1;
12790                 if (act & DO_ABS) {
12791                         while (stat(name, &statb) < 0) {
12792 #ifdef SYSV
12793                                 if (errno == EINTR)
12794                                         continue;
12795 #endif
12796                                 entry->cmdtype = CMDUNKNOWN;
12797                                 return;
12798                         }
12799                 }
12800                 entry->cmdtype = CMDNORMAL;
12801                 return;
12802         }
12803
12804 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12805
12806         updatetbl = (path == pathval());
12807         if (!updatetbl) {
12808                 act |= DO_ALTPATH;
12809                 if (strstr(path, "%builtin") != NULL)
12810                         act |= DO_ALTBLTIN;
12811         }
12812
12813         /* If name is in the table, check answer will be ok */
12814         cmdp = cmdlookup(name, 0);
12815         if (cmdp != NULL) {
12816                 int bit;
12817
12818                 switch (cmdp->cmdtype) {
12819                 default:
12820 #if DEBUG
12821                         abort();
12822 #endif
12823                 case CMDNORMAL:
12824                         bit = DO_ALTPATH;
12825                         break;
12826                 case CMDFUNCTION:
12827                         bit = DO_NOFUNC;
12828                         break;
12829                 case CMDBUILTIN:
12830                         bit = DO_ALTBLTIN;
12831                         break;
12832                 }
12833                 if (act & bit) {
12834                         updatetbl = 0;
12835                         cmdp = NULL;
12836                 } else if (cmdp->rehash == 0)
12837                         /* if not invalidated by cd, we're done */
12838                         goto success;
12839         }
12840
12841         /* If %builtin not in path, check for builtin next */
12842         bcmd = find_builtin(name);
12843         if (bcmd) {
12844                 if (IS_BUILTIN_REGULAR(bcmd))
12845                         goto builtin_success;
12846                 if (act & DO_ALTPATH) {
12847                         if (!(act & DO_ALTBLTIN))
12848                                 goto builtin_success;
12849                 } else if (builtinloc <= 0) {
12850                         goto builtin_success;
12851                 }
12852         }
12853
12854 #if ENABLE_FEATURE_SH_STANDALONE
12855         {
12856                 int applet_no = find_applet_by_name(name);
12857                 if (applet_no >= 0) {
12858                         entry->cmdtype = CMDNORMAL;
12859                         entry->u.index = -2 - applet_no;
12860                         return;
12861                 }
12862         }
12863 #endif
12864
12865         /* We have to search path. */
12866         prev = -1;              /* where to start */
12867         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12868                 if (cmdp->cmdtype == CMDBUILTIN)
12869                         prev = builtinloc;
12870                 else
12871                         prev = cmdp->param.index;
12872         }
12873
12874         e = ENOENT;
12875         idx = -1;
12876  loop:
12877         while ((fullname = path_advance(&path, name)) != NULL) {
12878                 stunalloc(fullname);
12879                 /* NB: code below will still use fullname
12880                  * despite it being "unallocated" */
12881                 idx++;
12882                 if (pathopt) {
12883                         if (prefix(pathopt, "builtin")) {
12884                                 if (bcmd)
12885                                         goto builtin_success;
12886                                 continue;
12887                         }
12888                         if ((act & DO_NOFUNC)
12889                          || !prefix(pathopt, "func")
12890                         ) {     /* ignore unimplemented options */
12891                                 continue;
12892                         }
12893                 }
12894                 /* if rehash, don't redo absolute path names */
12895                 if (fullname[0] == '/' && idx <= prev) {
12896                         if (idx < prev)
12897                                 continue;
12898                         TRACE(("searchexec \"%s\": no change\n", name));
12899                         goto success;
12900                 }
12901                 while (stat(fullname, &statb) < 0) {
12902 #ifdef SYSV
12903                         if (errno == EINTR)
12904                                 continue;
12905 #endif
12906                         if (errno != ENOENT && errno != ENOTDIR)
12907                                 e = errno;
12908                         goto loop;
12909                 }
12910                 e = EACCES;     /* if we fail, this will be the error */
12911                 if (!S_ISREG(statb.st_mode))
12912                         continue;
12913                 if (pathopt) {          /* this is a %func directory */
12914                         stalloc(strlen(fullname) + 1);
12915                         /* NB: stalloc will return space pointed by fullname
12916                          * (because we don't have any intervening allocations
12917                          * between stunalloc above and this stalloc) */
12918                         readcmdfile(fullname);
12919                         cmdp = cmdlookup(name, 0);
12920                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12921                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12922                         stunalloc(fullname);
12923                         goto success;
12924                 }
12925                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12926                 if (!updatetbl) {
12927                         entry->cmdtype = CMDNORMAL;
12928                         entry->u.index = idx;
12929                         return;
12930                 }
12931                 INT_OFF;
12932                 cmdp = cmdlookup(name, 1);
12933                 cmdp->cmdtype = CMDNORMAL;
12934                 cmdp->param.index = idx;
12935                 INT_ON;
12936                 goto success;
12937         }
12938
12939         /* We failed.  If there was an entry for this command, delete it */
12940         if (cmdp && updatetbl)
12941                 delete_cmd_entry();
12942         if (act & DO_ERR)
12943                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12944         entry->cmdtype = CMDUNKNOWN;
12945         return;
12946
12947  builtin_success:
12948         if (!updatetbl) {
12949                 entry->cmdtype = CMDBUILTIN;
12950                 entry->u.cmd = bcmd;
12951                 return;
12952         }
12953         INT_OFF;
12954         cmdp = cmdlookup(name, 1);
12955         cmdp->cmdtype = CMDBUILTIN;
12956         cmdp->param.cmd = bcmd;
12957         INT_ON;
12958  success:
12959         cmdp->rehash = 0;
12960         entry->cmdtype = cmdp->cmdtype;
12961         entry->u = cmdp->param;
12962 }
12963
12964
12965 /*
12966  * The trap builtin.
12967  */
12968 static int FAST_FUNC
12969 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12970 {
12971         char *action;
12972         char **ap;
12973         int signo, exitcode;
12974
12975         nextopt(nullstr);
12976         ap = argptr;
12977         if (!*ap) {
12978                 for (signo = 0; signo < NSIG; signo++) {
12979                         char *tr = trap_ptr[signo];
12980                         if (tr) {
12981                                 /* note: bash adds "SIG", but only if invoked
12982                                  * as "bash". If called as "sh", or if set -o posix,
12983                                  * then it prints short signal names.
12984                                  * We are printing short names: */
12985                                 out1fmt("trap -- %s %s\n",
12986                                                 single_quote(tr),
12987                                                 get_signame(signo));
12988                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12989                  * In this case, we will exit very soon, no need to free(). */
12990                                 /* if (trap_ptr != trap && tp[0]) */
12991                                 /*      free(tr); */
12992                         }
12993                 }
12994                 /*
12995                 if (trap_ptr != trap) {
12996                         free(trap_ptr);
12997                         trap_ptr = trap;
12998                 }
12999                 */
13000                 return 0;
13001         }
13002
13003         action = NULL;
13004         if (ap[1])
13005                 action = *ap++;
13006         exitcode = 0;
13007         while (*ap) {
13008                 signo = get_signum(*ap);
13009                 if (signo < 0 || signo >= NSIG) {
13010                         /* Mimic bash message exactly */
13011                         ash_msg("%s: invalid signal specification", *ap);
13012                         exitcode = 1;
13013                         goto next;
13014                 }
13015                 INT_OFF;
13016                 if (action) {
13017                         if (LONE_DASH(action))
13018                                 action = NULL;
13019                         else {
13020                                 if (action[0]) /* not NULL and not "" and not "-" */
13021                                         may_have_traps = 1;
13022                                 action = ckstrdup(action);
13023                         }
13024                 }
13025                 free(trap[signo]);
13026                 trap[signo] = action;
13027                 if (signo != 0)
13028                         setsignal(signo);
13029                 INT_ON;
13030  next:
13031                 ap++;
13032         }
13033         return exitcode;
13034 }
13035
13036
13037 /* ============ Builtins */
13038
13039 #if ENABLE_ASH_HELP
13040 static int FAST_FUNC
13041 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13042 {
13043         unsigned col;
13044         unsigned i;
13045
13046         out1fmt(
13047                 "Built-in commands:\n"
13048                 "------------------\n");
13049         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13050                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13051                                         builtintab[i].name + 1);
13052                 if (col > 60) {
13053                         out1fmt("\n");
13054                         col = 0;
13055                 }
13056         }
13057 # if ENABLE_FEATURE_SH_STANDALONE
13058         {
13059                 const char *a = applet_names;
13060                 while (*a) {
13061                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13062                         if (col > 60) {
13063                                 out1fmt("\n");
13064                                 col = 0;
13065                         }
13066                         while (*a++ != '\0')
13067                                 continue;
13068                 }
13069         }
13070 # endif
13071         newline_and_flush(stdout);
13072         return EXIT_SUCCESS;
13073 }
13074 #endif
13075
13076 #if MAX_HISTORY
13077 static int FAST_FUNC
13078 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13079 {
13080         show_history(line_input_state);
13081         return EXIT_SUCCESS;
13082 }
13083 #endif
13084
13085 /*
13086  * The export and readonly commands.
13087  */
13088 static int FAST_FUNC
13089 exportcmd(int argc UNUSED_PARAM, char **argv)
13090 {
13091         struct var *vp;
13092         char *name;
13093         const char *p;
13094         char **aptr;
13095         char opt;
13096         int flag;
13097         int flag_off;
13098
13099         /* "readonly" in bash accepts, but ignores -n.
13100          * We do the same: it saves a conditional in nextopt's param.
13101          */
13102         flag_off = 0;
13103         while ((opt = nextopt("np")) != '\0') {
13104                 if (opt == 'n')
13105                         flag_off = VEXPORT;
13106         }
13107         flag = VEXPORT;
13108         if (argv[0][0] == 'r') {
13109                 flag = VREADONLY;
13110                 flag_off = 0; /* readonly ignores -n */
13111         }
13112         flag_off = ~flag_off;
13113
13114         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13115         {
13116                 aptr = argptr;
13117                 name = *aptr;
13118                 if (name) {
13119                         do {
13120                                 p = strchr(name, '=');
13121                                 if (p != NULL) {
13122                                         p++;
13123                                 } else {
13124                                         vp = *findvar(hashvar(name), name);
13125                                         if (vp) {
13126                                                 vp->flags = ((vp->flags | flag) & flag_off);
13127                                                 continue;
13128                                         }
13129                                 }
13130                                 setvar(name, p, (flag & flag_off));
13131                         } while ((name = *++aptr) != NULL);
13132                         return 0;
13133                 }
13134         }
13135
13136         /* No arguments. Show the list of exported or readonly vars.
13137          * -n is ignored.
13138          */
13139         showvars(argv[0], flag, 0);
13140         return 0;
13141 }
13142
13143 /*
13144  * Delete a function if it exists.
13145  */
13146 static void
13147 unsetfunc(const char *name)
13148 {
13149         struct tblentry *cmdp;
13150
13151         cmdp = cmdlookup(name, 0);
13152         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13153                 delete_cmd_entry();
13154 }
13155
13156 /*
13157  * The unset builtin command.  We unset the function before we unset the
13158  * variable to allow a function to be unset when there is a readonly variable
13159  * with the same name.
13160  */
13161 static int FAST_FUNC
13162 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13163 {
13164         char **ap;
13165         int i;
13166         int flag = 0;
13167         int ret = 0;
13168
13169         while ((i = nextopt("vf")) != 0) {
13170                 flag = i;
13171         }
13172
13173         for (ap = argptr; *ap; ap++) {
13174                 if (flag != 'f') {
13175                         i = unsetvar(*ap);
13176                         ret |= i;
13177                         if (!(i & 2))
13178                                 continue;
13179                 }
13180                 if (flag != 'v')
13181                         unsetfunc(*ap);
13182         }
13183         return ret & 1;
13184 }
13185
13186 static const unsigned char timescmd_str[] ALIGN1 = {
13187         ' ',  offsetof(struct tms, tms_utime),
13188         '\n', offsetof(struct tms, tms_stime),
13189         ' ',  offsetof(struct tms, tms_cutime),
13190         '\n', offsetof(struct tms, tms_cstime),
13191         0
13192 };
13193 static int FAST_FUNC
13194 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13195 {
13196         unsigned long clk_tck, s, t;
13197         const unsigned char *p;
13198         struct tms buf;
13199
13200         clk_tck = bb_clk_tck();
13201         times(&buf);
13202
13203         p = timescmd_str;
13204         do {
13205                 t = *(clock_t *)(((char *) &buf) + p[1]);
13206                 s = t / clk_tck;
13207                 t = t % clk_tck;
13208                 out1fmt("%lum%lu.%03lus%c",
13209                         s / 60, s % 60,
13210                         (t * 1000) / clk_tck,
13211                         p[0]);
13212                 p += 2;
13213         } while (*p);
13214
13215         return 0;
13216 }
13217
13218 #if ENABLE_FEATURE_SH_MATH
13219 /*
13220  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13221  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13222  *
13223  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13224  */
13225 static int FAST_FUNC
13226 letcmd(int argc UNUSED_PARAM, char **argv)
13227 {
13228         arith_t i;
13229
13230         argv++;
13231         if (!*argv)
13232                 ash_msg_and_raise_error("expression expected");
13233         do {
13234                 i = ash_arith(*argv);
13235         } while (*++argv);
13236
13237         return !i;
13238 }
13239 #endif
13240
13241 /*
13242  * The read builtin. Options:
13243  *      -r              Do not interpret '\' specially
13244  *      -s              Turn off echo (tty only)
13245  *      -n NCHARS       Read NCHARS max
13246  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13247  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13248  *      -u FD           Read from given FD instead of fd 0
13249  * This uses unbuffered input, which may be avoidable in some cases.
13250  * TODO: bash also has:
13251  *      -a ARRAY        Read into array[0],[1],etc
13252  *      -d DELIM        End on DELIM char, not newline
13253  *      -e              Use line editing (tty only)
13254  */
13255 static int FAST_FUNC
13256 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13257 {
13258         char *opt_n = NULL;
13259         char *opt_p = NULL;
13260         char *opt_t = NULL;
13261         char *opt_u = NULL;
13262         int read_flags = 0;
13263         const char *r;
13264         int i;
13265
13266         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13267                 switch (i) {
13268                 case 'p':
13269                         opt_p = optionarg;
13270                         break;
13271                 case 'n':
13272                         opt_n = optionarg;
13273                         break;
13274                 case 's':
13275                         read_flags |= BUILTIN_READ_SILENT;
13276                         break;
13277                 case 't':
13278                         opt_t = optionarg;
13279                         break;
13280                 case 'r':
13281                         read_flags |= BUILTIN_READ_RAW;
13282                         break;
13283                 case 'u':
13284                         opt_u = optionarg;
13285                         break;
13286                 default:
13287                         break;
13288                 }
13289         }
13290
13291         /* "read -s" needs to save/restore termios, can't allow ^C
13292          * to jump out of it.
13293          */
13294  again:
13295         INT_OFF;
13296         r = shell_builtin_read(setvar0,
13297                 argptr,
13298                 bltinlookup("IFS"), /* can be NULL */
13299                 read_flags,
13300                 opt_n,
13301                 opt_p,
13302                 opt_t,
13303                 opt_u
13304         );
13305         INT_ON;
13306
13307         if ((uintptr_t)r == 1 && errno == EINTR) {
13308                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13309                 if (pending_sig == 0)
13310                         goto again;
13311         }
13312
13313         if ((uintptr_t)r > 1)
13314                 ash_msg_and_raise_error(r);
13315
13316         return (uintptr_t)r;
13317 }
13318
13319 static int FAST_FUNC
13320 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13321 {
13322         static const char permuser[3] ALIGN1 = "ogu";
13323
13324         mode_t mask;
13325         int symbolic_mode = 0;
13326
13327         while (nextopt("S") != '\0') {
13328                 symbolic_mode = 1;
13329         }
13330
13331         INT_OFF;
13332         mask = umask(0);
13333         umask(mask);
13334         INT_ON;
13335
13336         if (*argptr == NULL) {
13337                 if (symbolic_mode) {
13338                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13339                         char *p = buf;
13340                         int i;
13341
13342                         i = 2;
13343                         for (;;) {
13344                                 *p++ = ',';
13345                                 *p++ = permuser[i];
13346                                 *p++ = '=';
13347                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13348                                 if (!(mask & 0400)) *p++ = 'r';
13349                                 if (!(mask & 0200)) *p++ = 'w';
13350                                 if (!(mask & 0100)) *p++ = 'x';
13351                                 mask <<= 3;
13352                                 if (--i < 0)
13353                                         break;
13354                         }
13355                         *p = '\0';
13356                         puts(buf + 1);
13357                 } else {
13358                         out1fmt("%04o\n", mask);
13359                 }
13360         } else {
13361                 char *modestr = *argptr;
13362                 /* numeric umasks are taken as-is */
13363                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13364                 if (!isdigit(modestr[0]))
13365                         mask ^= 0777;
13366                 mask = bb_parse_mode(modestr, mask);
13367                 if ((unsigned)mask > 0777) {
13368                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13369                 }
13370                 if (!isdigit(modestr[0]))
13371                         mask ^= 0777;
13372                 umask(mask);
13373         }
13374         return 0;
13375 }
13376
13377 static int FAST_FUNC
13378 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13379 {
13380         return shell_builtin_ulimit(argv);
13381 }
13382
13383 /* ============ main() and helpers */
13384
13385 /*
13386  * Called to exit the shell.
13387  */
13388 static void
13389 exitshell(void)
13390 {
13391         struct jmploc loc;
13392         char *p;
13393         int status;
13394
13395 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13396         save_history(line_input_state);
13397 #endif
13398         status = exitstatus;
13399         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13400         if (setjmp(loc.loc)) {
13401                 if (exception_type == EXEXIT)
13402                         status = exitstatus;
13403                 goto out;
13404         }
13405         exception_handler = &loc;
13406         p = trap[0];
13407         if (p) {
13408                 trap[0] = NULL;
13409                 evalskip = 0;
13410                 evalstring(p, 0);
13411                 /*free(p); - we'll exit soon */
13412         }
13413  out:
13414         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13415          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13416          */
13417         setjobctl(0);
13418         flush_stdout_stderr();
13419         _exit(status);
13420         /* NOTREACHED */
13421 }
13422
13423 static void
13424 init(void)
13425 {
13426         /* we will never free this */
13427         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13428
13429         sigmode[SIGCHLD - 1] = S_DFL;
13430         setsignal(SIGCHLD);
13431
13432         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13433          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13434          */
13435         signal(SIGHUP, SIG_DFL);
13436
13437         {
13438                 char **envp;
13439                 const char *p;
13440                 struct stat st1, st2;
13441
13442                 initvar();
13443                 for (envp = environ; envp && *envp; envp++) {
13444                         p = endofname(*envp);
13445                         if (p != *envp && *p == '=') {
13446                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13447                         }
13448                 }
13449
13450                 setvareq((char*)defoptindvar, VTEXTFIXED);
13451
13452                 setvar0("PPID", utoa(getppid()));
13453 #if BASH_SHLVL_VAR
13454                 p = lookupvar("SHLVL");
13455                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13456 #endif
13457 #if BASH_HOSTNAME_VAR
13458                 if (!lookupvar("HOSTNAME")) {
13459                         struct utsname uts;
13460                         uname(&uts);
13461                         setvar0("HOSTNAME", uts.nodename);
13462                 }
13463 #endif
13464                 p = lookupvar("PWD");
13465                 if (p) {
13466                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13467                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13468                         ) {
13469                                 p = NULL;
13470                         }
13471                 }
13472                 setpwd(p, 0);
13473         }
13474 }
13475
13476
13477 //usage:#define ash_trivial_usage
13478 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13479 //usage:#define ash_full_usage "\n\n"
13480 //usage:        "Unix shell interpreter"
13481
13482 /*
13483  * Process the shell command line arguments.
13484  */
13485 static void
13486 procargs(char **argv)
13487 {
13488         int i;
13489         const char *xminusc;
13490         char **xargv;
13491
13492         xargv = argv;
13493         arg0 = xargv[0];
13494         /* if (xargv[0]) - mmm, this is always true! */
13495                 xargv++;
13496         for (i = 0; i < NOPTS; i++)
13497                 optlist[i] = 2;
13498         argptr = xargv;
13499         if (options(/*cmdline:*/ 1)) {
13500                 /* it already printed err message */
13501                 raise_exception(EXERROR);
13502         }
13503         xargv = argptr;
13504         xminusc = minusc;
13505         if (*xargv == NULL) {
13506                 if (xminusc)
13507                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13508                 sflag = 1;
13509         }
13510         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13511                 iflag = 1;
13512         if (mflag == 2)
13513                 mflag = iflag;
13514         for (i = 0; i < NOPTS; i++)
13515                 if (optlist[i] == 2)
13516                         optlist[i] = 0;
13517 #if DEBUG == 2
13518         debug = 1;
13519 #endif
13520         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13521         if (xminusc) {
13522                 minusc = *xargv++;
13523                 if (*xargv)
13524                         goto setarg0;
13525         } else if (!sflag) {
13526                 setinputfile(*xargv, 0);
13527  setarg0:
13528                 arg0 = *xargv++;
13529                 commandname = arg0;
13530         }
13531
13532         shellparam.p = xargv;
13533 #if ENABLE_ASH_GETOPTS
13534         shellparam.optind = 1;
13535         shellparam.optoff = -1;
13536 #endif
13537         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13538         while (*xargv) {
13539                 shellparam.nparam++;
13540                 xargv++;
13541         }
13542         optschanged();
13543 }
13544
13545 /*
13546  * Read /etc/profile, ~/.profile, $ENV.
13547  */
13548 static void
13549 read_profile(const char *name)
13550 {
13551         name = expandstr(name);
13552         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13553                 return;
13554         cmdloop(0);
13555         popfile();
13556 }
13557
13558 /*
13559  * This routine is called when an error or an interrupt occurs in an
13560  * interactive shell and control is returned to the main command loop.
13561  * (In dash, this function is auto-generated by build machinery).
13562  */
13563 static void
13564 reset(void)
13565 {
13566         /* from eval.c: */
13567         evalskip = 0;
13568         loopnest = 0;
13569
13570         /* from expand.c: */
13571         ifsfree();
13572
13573         /* from input.c: */
13574         g_parsefile->left_in_buffer = 0;
13575         g_parsefile->left_in_line = 0;      /* clear input buffer */
13576         popallfiles();
13577
13578         /* from redir.c: */
13579         while (redirlist)
13580                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13581 }
13582
13583 #if PROFILE
13584 static short profile_buf[16384];
13585 extern int etext();
13586 #endif
13587
13588 /*
13589  * Main routine.  We initialize things, parse the arguments, execute
13590  * profiles if we're a login shell, and then call cmdloop to execute
13591  * commands.  The setjmp call sets up the location to jump to when an
13592  * exception occurs.  When an exception occurs the variable "state"
13593  * is used to figure out how far we had gotten.
13594  */
13595 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13596 int ash_main(int argc UNUSED_PARAM, char **argv)
13597 {
13598         volatile smallint state;
13599         struct jmploc jmploc;
13600         struct stackmark smark;
13601
13602         /* Initialize global data */
13603         INIT_G_misc();
13604         INIT_G_memstack();
13605         INIT_G_var();
13606 #if ENABLE_ASH_ALIAS
13607         INIT_G_alias();
13608 #endif
13609         INIT_G_cmdtable();
13610
13611 #if PROFILE
13612         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13613 #endif
13614
13615 #if ENABLE_FEATURE_EDITING
13616         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13617 #endif
13618         state = 0;
13619         if (setjmp(jmploc.loc)) {
13620                 smallint e;
13621                 smallint s;
13622
13623                 reset();
13624
13625                 e = exception_type;
13626                 s = state;
13627                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13628                         exitshell();
13629                 }
13630                 if (e == EXINT) {
13631                         newline_and_flush(stderr);
13632                 }
13633
13634                 popstackmark(&smark);
13635                 FORCE_INT_ON; /* enable interrupts */
13636                 if (s == 1)
13637                         goto state1;
13638                 if (s == 2)
13639                         goto state2;
13640                 if (s == 3)
13641                         goto state3;
13642                 goto state4;
13643         }
13644         exception_handler = &jmploc;
13645         rootpid = getpid();
13646
13647         init();
13648         setstackmark(&smark);
13649         procargs(argv);
13650 #if DEBUG
13651         TRACE(("Shell args: "));
13652         trace_puts_args(argv);
13653 #endif
13654
13655         if (argv[0] && argv[0][0] == '-')
13656                 isloginsh = 1;
13657         if (isloginsh) {
13658                 const char *hp;
13659
13660                 state = 1;
13661                 read_profile("/etc/profile");
13662  state1:
13663                 state = 2;
13664                 hp = lookupvar("HOME");
13665                 if (hp)
13666                         read_profile("$HOME/.profile");
13667         }
13668  state2:
13669         state = 3;
13670         if (
13671 #ifndef linux
13672          getuid() == geteuid() && getgid() == getegid() &&
13673 #endif
13674          iflag
13675         ) {
13676                 const char *shinit = lookupvar("ENV");
13677                 if (shinit != NULL && *shinit != '\0')
13678                         read_profile(shinit);
13679         }
13680         popstackmark(&smark);
13681  state3:
13682         state = 4;
13683         if (minusc) {
13684                 /* evalstring pushes parsefile stack.
13685                  * Ensure we don't falsely claim that 0 (stdin)
13686                  * is one of stacked source fds.
13687                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13688                 // if (!sflag) g_parsefile->pf_fd = -1;
13689                 // ^^ not necessary since now we special-case fd 0
13690                 // in is_hidden_fd() to not be considered "hidden fd"
13691                 evalstring(minusc, 0);
13692         }
13693
13694         if (sflag || minusc == NULL) {
13695 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13696                 if (iflag) {
13697                         const char *hp = lookupvar("HISTFILE");
13698                         if (!hp) {
13699                                 hp = lookupvar("HOME");
13700                                 if (hp) {
13701                                         INT_OFF;
13702                                         hp = concat_path_file(hp, ".ash_history");
13703                                         setvar0("HISTFILE", hp);
13704                                         free((char*)hp);
13705                                         INT_ON;
13706                                         hp = lookupvar("HISTFILE");
13707                                 }
13708                         }
13709                         if (hp)
13710                                 line_input_state->hist_file = hp;
13711 # if ENABLE_FEATURE_SH_HISTFILESIZE
13712                         hp = lookupvar("HISTFILESIZE");
13713                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13714 # endif
13715                 }
13716 #endif
13717  state4: /* XXX ??? - why isn't this before the "if" statement */
13718                 cmdloop(1);
13719         }
13720 #if PROFILE
13721         monitor(0);
13722 #endif
13723 #ifdef GPROF
13724         {
13725                 extern void _mcleanup(void);
13726                 _mcleanup();
13727         }
13728 #endif
13729         TRACE(("End of main reached\n"));
13730         exitshell();
13731         /* NOTREACHED */
13732 }
13733
13734
13735 /*-
13736  * Copyright (c) 1989, 1991, 1993, 1994
13737  *      The Regents of the University of California.  All rights reserved.
13738  *
13739  * This code is derived from software contributed to Berkeley by
13740  * Kenneth Almquist.
13741  *
13742  * Redistribution and use in source and binary forms, with or without
13743  * modification, are permitted provided that the following conditions
13744  * are met:
13745  * 1. Redistributions of source code must retain the above copyright
13746  *    notice, this list of conditions and the following disclaimer.
13747  * 2. Redistributions in binary form must reproduce the above copyright
13748  *    notice, this list of conditions and the following disclaimer in the
13749  *    documentation and/or other materials provided with the distribution.
13750  * 3. Neither the name of the University nor the names of its contributors
13751  *    may be used to endorse or promote products derived from this software
13752  *    without specific prior written permission.
13753  *
13754  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13755  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13756  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13757  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13758  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13759  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13760  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13761  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13762  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13763  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13764  * SUCH DAMAGE.
13765  */