ash: add INT_OFF/ON around allocations
[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 #if ENABLE_ASH_EXPAND_PRMT
2462 /* expandstr() needs parsing machinery, so it is far away ahead... */
2463 static const char *expandstr(const char *ps);
2464 #else
2465 #define expandstr(s) s
2466 #endif
2467
2468 static void
2469 setprompt_if(smallint do_set, int whichprompt)
2470 {
2471         const char *prompt;
2472         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2473
2474         if (!do_set)
2475                 return;
2476
2477         needprompt = 0;
2478
2479         switch (whichprompt) {
2480         case 1:
2481                 prompt = ps1val();
2482                 break;
2483         case 2:
2484                 prompt = ps2val();
2485                 break;
2486         default:                        /* 0 */
2487                 prompt = nullstr;
2488         }
2489 #if ENABLE_ASH_EXPAND_PRMT
2490         pushstackmark(&smark, stackblocksize());
2491 #endif
2492         putprompt(expandstr(prompt));
2493 #if ENABLE_ASH_EXPAND_PRMT
2494         popstackmark(&smark);
2495 #endif
2496 }
2497
2498
2499 /* ============ The cd and pwd commands */
2500
2501 #define CD_PHYSICAL 1
2502 #define CD_PRINT 2
2503
2504 static int
2505 cdopt(void)
2506 {
2507         int flags = 0;
2508         int i, j;
2509
2510         j = 'L';
2511         while ((i = nextopt("LP")) != '\0') {
2512                 if (i != j) {
2513                         flags ^= CD_PHYSICAL;
2514                         j = i;
2515                 }
2516         }
2517
2518         return flags;
2519 }
2520
2521 /*
2522  * Update curdir (the name of the current directory) in response to a
2523  * cd command.
2524  */
2525 static const char *
2526 updatepwd(const char *dir)
2527 {
2528         char *new;
2529         char *p;
2530         char *cdcomppath;
2531         const char *lim;
2532
2533         cdcomppath = sstrdup(dir);
2534         STARTSTACKSTR(new);
2535         if (*dir != '/') {
2536                 if (curdir == nullstr)
2537                         return 0;
2538                 new = stack_putstr(curdir, new);
2539         }
2540         new = makestrspace(strlen(dir) + 2, new);
2541         lim = (char *)stackblock() + 1;
2542         if (*dir != '/') {
2543                 if (new[-1] != '/')
2544                         USTPUTC('/', new);
2545                 if (new > lim && *lim == '/')
2546                         lim++;
2547         } else {
2548                 USTPUTC('/', new);
2549                 cdcomppath++;
2550                 if (dir[1] == '/' && dir[2] != '/') {
2551                         USTPUTC('/', new);
2552                         cdcomppath++;
2553                         lim++;
2554                 }
2555         }
2556         p = strtok(cdcomppath, "/");
2557         while (p) {
2558                 switch (*p) {
2559                 case '.':
2560                         if (p[1] == '.' && p[2] == '\0') {
2561                                 while (new > lim) {
2562                                         STUNPUTC(new);
2563                                         if (new[-1] == '/')
2564                                                 break;
2565                                 }
2566                                 break;
2567                         }
2568                         if (p[1] == '\0')
2569                                 break;
2570                         /* fall through */
2571                 default:
2572                         new = stack_putstr(p, new);
2573                         USTPUTC('/', new);
2574                 }
2575                 p = strtok(NULL, "/");
2576         }
2577         if (new > lim)
2578                 STUNPUTC(new);
2579         *new = 0;
2580         return stackblock();
2581 }
2582
2583 /*
2584  * Find out what the current directory is. If we already know the current
2585  * directory, this routine returns immediately.
2586  */
2587 static char *
2588 getpwd(void)
2589 {
2590         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2591         return dir ? dir : nullstr;
2592 }
2593
2594 static void
2595 setpwd(const char *val, int setold)
2596 {
2597         char *oldcur, *dir;
2598
2599         oldcur = dir = curdir;
2600
2601         if (setold) {
2602                 setvar("OLDPWD", oldcur, VEXPORT);
2603         }
2604         INT_OFF;
2605         if (physdir != nullstr) {
2606                 if (physdir != oldcur)
2607                         free(physdir);
2608                 physdir = nullstr;
2609         }
2610         if (oldcur == val || !val) {
2611                 char *s = getpwd();
2612                 physdir = s;
2613                 if (!val)
2614                         dir = s;
2615         } else
2616                 dir = ckstrdup(val);
2617         if (oldcur != dir && oldcur != nullstr) {
2618                 free(oldcur);
2619         }
2620         curdir = dir;
2621         INT_ON;
2622         setvar("PWD", dir, VEXPORT);
2623 }
2624
2625 static void hashcd(void);
2626
2627 /*
2628  * Actually do the chdir.  We also call hashcd to let other routines
2629  * know that the current directory has changed.
2630  */
2631 static int
2632 docd(const char *dest, int flags)
2633 {
2634         const char *dir = NULL;
2635         int err;
2636
2637         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2638
2639         INT_OFF;
2640         if (!(flags & CD_PHYSICAL)) {
2641                 dir = updatepwd(dest);
2642                 if (dir)
2643                         dest = dir;
2644         }
2645         err = chdir(dest);
2646         if (err)
2647                 goto out;
2648         setpwd(dir, 1);
2649         hashcd();
2650  out:
2651         INT_ON;
2652         return err;
2653 }
2654
2655 static int FAST_FUNC
2656 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2657 {
2658         const char *dest;
2659         const char *path;
2660         const char *p;
2661         char c;
2662         struct stat statb;
2663         int flags;
2664
2665         flags = cdopt();
2666         dest = *argptr;
2667         if (!dest)
2668                 dest = bltinlookup("HOME");
2669         else if (LONE_DASH(dest)) {
2670                 dest = bltinlookup("OLDPWD");
2671                 flags |= CD_PRINT;
2672         }
2673         if (!dest)
2674                 dest = nullstr;
2675         if (*dest == '/')
2676                 goto step6;
2677         if (*dest == '.') {
2678                 c = dest[1];
2679  dotdot:
2680                 switch (c) {
2681                 case '\0':
2682                 case '/':
2683                         goto step6;
2684                 case '.':
2685                         c = dest[2];
2686                         if (c != '.')
2687                                 goto dotdot;
2688                 }
2689         }
2690         if (!*dest)
2691                 dest = ".";
2692         path = bltinlookup("CDPATH");
2693         while (path) {
2694                 c = *path;
2695                 p = path_advance(&path, dest);
2696                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2697                         if (c && c != ':')
2698                                 flags |= CD_PRINT;
2699  docd:
2700                         if (!docd(p, flags))
2701                                 goto out;
2702                         goto err;
2703                 }
2704         }
2705
2706  step6:
2707         p = dest;
2708         goto docd;
2709
2710  err:
2711         ash_msg_and_raise_error("can't cd to %s", dest);
2712         /* NOTREACHED */
2713  out:
2714         if (flags & CD_PRINT)
2715                 out1fmt("%s\n", curdir);
2716         return 0;
2717 }
2718
2719 static int FAST_FUNC
2720 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2721 {
2722         int flags;
2723         const char *dir = curdir;
2724
2725         flags = cdopt();
2726         if (flags) {
2727                 if (physdir == nullstr)
2728                         setpwd(dir, 0);
2729                 dir = physdir;
2730         }
2731         out1fmt("%s\n", dir);
2732         return 0;
2733 }
2734
2735
2736 /* ============ ... */
2737
2738
2739 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2740
2741 /* Syntax classes */
2742 #define CWORD     0             /* character is nothing special */
2743 #define CNL       1             /* newline character */
2744 #define CBACK     2             /* a backslash character */
2745 #define CSQUOTE   3             /* single quote */
2746 #define CDQUOTE   4             /* double quote */
2747 #define CENDQUOTE 5             /* a terminating quote */
2748 #define CBQUOTE   6             /* backwards single quote */
2749 #define CVAR      7             /* a dollar sign */
2750 #define CENDVAR   8             /* a '}' character */
2751 #define CLP       9             /* a left paren in arithmetic */
2752 #define CRP      10             /* a right paren in arithmetic */
2753 #define CENDFILE 11             /* end of file */
2754 #define CCTL     12             /* like CWORD, except it must be escaped */
2755 #define CSPCL    13             /* these terminate a word */
2756 #define CIGN     14             /* character should be ignored */
2757
2758 #define PEOF     256
2759 #if ENABLE_ASH_ALIAS
2760 # define PEOA    257
2761 #endif
2762
2763 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2764
2765 #if ENABLE_FEATURE_SH_MATH
2766 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2767 #else
2768 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2769 #endif
2770 static const uint16_t S_I_T[] ALIGN2 = {
2771 #if ENABLE_ASH_ALIAS
2772         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2773 #endif
2774         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2775         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2776         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2777         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2778         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2779         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2780         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2781         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2782         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2783         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2784         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2785 #if !USE_SIT_FUNCTION
2786         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2787         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2788         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2789 #endif
2790 #undef SIT_ITEM
2791 };
2792 /* Constants below must match table above */
2793 enum {
2794 #if ENABLE_ASH_ALIAS
2795         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2796 #endif
2797         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2798         CNL_CNL_CNL_CNL                    , /*  2 */
2799         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2800         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2801         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2802         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2803         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2804         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2805         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2806         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2807         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2808         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2809         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2810         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2811 };
2812
2813 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2814  * caller must ensure proper cast on it if c is *char_ptr!
2815  */
2816 /* Values for syntax param */
2817 #define BASESYNTAX 0    /* not in quotes */
2818 #define DQSYNTAX   1    /* in double quotes */
2819 #define SQSYNTAX   2    /* in single quotes */
2820 #define ARISYNTAX  3    /* in arithmetic */
2821 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2822
2823 #if USE_SIT_FUNCTION
2824
2825 static int
2826 SIT(int c, int syntax)
2827 {
2828         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2829         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2830         /*
2831          * This causes '/' to be prepended with CTLESC in dquoted string,
2832          * making "./file"* treated incorrectly because we feed
2833          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2834          * The "homegrown" glob implementation is okay with that,
2835          * but glibc one isn't. With '/' always treated as CWORD,
2836          * both work fine.
2837          */
2838 # if ENABLE_ASH_ALIAS
2839         static const uint8_t syntax_index_table[] ALIGN1 = {
2840                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2841                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2842                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2843                 11, 3                           /* "}~" */
2844         };
2845 # else
2846         static const uint8_t syntax_index_table[] ALIGN1 = {
2847                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2848                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2849                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2850                 10, 2                           /* "}~" */
2851         };
2852 # endif
2853         const char *s;
2854         int indx;
2855
2856         if (c == PEOF)
2857                 return CENDFILE;
2858 # if ENABLE_ASH_ALIAS
2859         if (c == PEOA)
2860                 indx = 0;
2861         else
2862 # endif
2863         {
2864                 /* Cast is purely for paranoia here,
2865                  * just in case someone passed signed char to us */
2866                 if ((unsigned char)c >= CTL_FIRST
2867                  && (unsigned char)c <= CTL_LAST
2868                 ) {
2869                         return CCTL;
2870                 }
2871                 s = strchrnul(spec_symbls, c);
2872                 if (*s == '\0')
2873                         return CWORD;
2874                 indx = syntax_index_table[s - spec_symbls];
2875         }
2876         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2877 }
2878
2879 #else   /* !USE_SIT_FUNCTION */
2880
2881 static const uint8_t syntax_index_table[] ALIGN1 = {
2882         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2883         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2884         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2885         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2886         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2887         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2888         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2889         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2890         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2891         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2892         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2893         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2894         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2895         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2896         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2897         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2898         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2899         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2900         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2901         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2902         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2903         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2904         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2912         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2913         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2914         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2915         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2916         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2917         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2918         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2919         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2920         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2921         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2922         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2923         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2924         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2925         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2926         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2927         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2928         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2929         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2930 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2931         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2933         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2935         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2936         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2938         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2939         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2940         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2941         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2943         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2944         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2945         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2946         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2947         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2948         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2956         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2977         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2978         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2981         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2984         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2985         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2986         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2987         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2988         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2989         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
2990         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
2991         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
2992         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
2993         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3009         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3010         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3011         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3012         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3013         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3014         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3015         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3016         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3017         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3018         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3019         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3020         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3021         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3022         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3023         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3024         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3025         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3026         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3027         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3028         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3029         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3030         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3031         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3140         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3141 # if ENABLE_ASH_ALIAS
3142         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3143 # endif
3144 };
3145
3146 #if 1
3147 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3148 #else /* debug version, caught one signed char bug */
3149 # define SIT(c, syntax) \
3150         ({ \
3151                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3152                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3153                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3154                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3155                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3156         })
3157 #endif
3158
3159 #endif  /* !USE_SIT_FUNCTION */
3160
3161
3162 /* ============ Alias handling */
3163
3164 #if ENABLE_ASH_ALIAS
3165
3166 #define ALIASINUSE 1
3167 #define ALIASDEAD  2
3168
3169 struct alias {
3170         struct alias *next;
3171         char *name;
3172         char *val;
3173         int flag;
3174 };
3175
3176
3177 static struct alias **atab; // [ATABSIZE];
3178 #define INIT_G_alias() do { \
3179         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3180 } while (0)
3181
3182
3183 static struct alias **
3184 __lookupalias(const char *name)
3185 {
3186         unsigned int hashval;
3187         struct alias **app;
3188         const char *p;
3189         unsigned int ch;
3190
3191         p = name;
3192
3193         ch = (unsigned char)*p;
3194         hashval = ch << 4;
3195         while (ch) {
3196                 hashval += ch;
3197                 ch = (unsigned char)*++p;
3198         }
3199         app = &atab[hashval % ATABSIZE];
3200
3201         for (; *app; app = &(*app)->next) {
3202                 if (strcmp(name, (*app)->name) == 0) {
3203                         break;
3204                 }
3205         }
3206
3207         return app;
3208 }
3209
3210 static struct alias *
3211 lookupalias(const char *name, int check)
3212 {
3213         struct alias *ap = *__lookupalias(name);
3214
3215         if (check && ap && (ap->flag & ALIASINUSE))
3216                 return NULL;
3217         return ap;
3218 }
3219
3220 static struct alias *
3221 freealias(struct alias *ap)
3222 {
3223         struct alias *next;
3224
3225         if (ap->flag & ALIASINUSE) {
3226                 ap->flag |= ALIASDEAD;
3227                 return ap;
3228         }
3229
3230         next = ap->next;
3231         free(ap->name);
3232         free(ap->val);
3233         free(ap);
3234         return next;
3235 }
3236
3237 static void
3238 setalias(const char *name, const char *val)
3239 {
3240         struct alias *ap, **app;
3241
3242         app = __lookupalias(name);
3243         ap = *app;
3244         INT_OFF;
3245         if (ap) {
3246                 if (!(ap->flag & ALIASINUSE)) {
3247                         free(ap->val);
3248                 }
3249                 ap->val = ckstrdup(val);
3250                 ap->flag &= ~ALIASDEAD;
3251         } else {
3252                 /* not found */
3253                 ap = ckzalloc(sizeof(struct alias));
3254                 ap->name = ckstrdup(name);
3255                 ap->val = ckstrdup(val);
3256                 /*ap->flag = 0; - ckzalloc did it */
3257                 /*ap->next = NULL;*/
3258                 *app = ap;
3259         }
3260         INT_ON;
3261 }
3262
3263 static int
3264 unalias(const char *name)
3265 {
3266         struct alias **app;
3267
3268         app = __lookupalias(name);
3269
3270         if (*app) {
3271                 INT_OFF;
3272                 *app = freealias(*app);
3273                 INT_ON;
3274                 return 0;
3275         }
3276
3277         return 1;
3278 }
3279
3280 static void
3281 rmaliases(void)
3282 {
3283         struct alias *ap, **app;
3284         int i;
3285
3286         INT_OFF;
3287         for (i = 0; i < ATABSIZE; i++) {
3288                 app = &atab[i];
3289                 for (ap = *app; ap; ap = *app) {
3290                         *app = freealias(*app);
3291                         if (ap == *app) {
3292                                 app = &ap->next;
3293                         }
3294                 }
3295         }
3296         INT_ON;
3297 }
3298
3299 static void
3300 printalias(const struct alias *ap)
3301 {
3302         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3303 }
3304
3305 /*
3306  * TODO - sort output
3307  */
3308 static int FAST_FUNC
3309 aliascmd(int argc UNUSED_PARAM, char **argv)
3310 {
3311         char *n, *v;
3312         int ret = 0;
3313         struct alias *ap;
3314
3315         if (!argv[1]) {
3316                 int i;
3317
3318                 for (i = 0; i < ATABSIZE; i++) {
3319                         for (ap = atab[i]; ap; ap = ap->next) {
3320                                 printalias(ap);
3321                         }
3322                 }
3323                 return 0;
3324         }
3325         while ((n = *++argv) != NULL) {
3326                 v = strchr(n+1, '=');
3327                 if (v == NULL) { /* n+1: funny ksh stuff */
3328                         ap = *__lookupalias(n);
3329                         if (ap == NULL) {
3330                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3331                                 ret = 1;
3332                         } else
3333                                 printalias(ap);
3334                 } else {
3335                         *v++ = '\0';
3336                         setalias(n, v);
3337                 }
3338         }
3339
3340         return ret;
3341 }
3342
3343 static int FAST_FUNC
3344 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3345 {
3346         int i;
3347
3348         while ((i = nextopt("a")) != '\0') {
3349                 if (i == 'a') {
3350                         rmaliases();
3351                         return 0;
3352                 }
3353         }
3354         for (i = 0; *argptr; argptr++) {
3355                 if (unalias(*argptr)) {
3356                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3357                         i = 1;
3358                 }
3359         }
3360
3361         return i;
3362 }
3363
3364 #endif /* ASH_ALIAS */
3365
3366
3367 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3368 #define FORK_FG    0
3369 #define FORK_BG    1
3370 #define FORK_NOJOB 2
3371
3372 /* mode flags for showjob(s) */
3373 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3374 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3375 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3376 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3377
3378 /*
3379  * A job structure contains information about a job.  A job is either a
3380  * single process or a set of processes contained in a pipeline.  In the
3381  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3382  * array of pids.
3383  */
3384 struct procstat {
3385         pid_t   ps_pid;         /* process id */
3386         int     ps_status;      /* last process status from wait() */
3387         char    *ps_cmd;        /* text of command being run */
3388 };
3389
3390 struct job {
3391         struct procstat ps0;    /* status of process */
3392         struct procstat *ps;    /* status or processes when more than one */
3393 #if JOBS
3394         int stopstatus;         /* status of a stopped job */
3395 #endif
3396         unsigned nprocs;        /* number of processes */
3397
3398 #define JOBRUNNING      0       /* at least one proc running */
3399 #define JOBSTOPPED      1       /* all procs are stopped */
3400 #define JOBDONE         2       /* all procs are completed */
3401         unsigned
3402                 state: 8,
3403 #if JOBS
3404                 sigint: 1,      /* job was killed by SIGINT */
3405                 jobctl: 1,      /* job running under job control */
3406 #endif
3407                 waited: 1,      /* true if this entry has been waited for */
3408                 used: 1,        /* true if this entry is in used */
3409                 changed: 1;     /* true if status has changed */
3410         struct job *prev_job;   /* previous job */
3411 };
3412
3413 static struct job *makejob(/*union node *,*/ int);
3414 static int forkshell(struct job *, union node *, int);
3415 static int waitforjob(struct job *);
3416
3417 #if !JOBS
3418 enum { doing_jobctl = 0 };
3419 #define setjobctl(on) do {} while (0)
3420 #else
3421 static smallint doing_jobctl; //references:8
3422 static void setjobctl(int);
3423 #endif
3424
3425 /*
3426  * Ignore a signal.
3427  */
3428 static void
3429 ignoresig(int signo)
3430 {
3431         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3432         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3433                 /* No, need to do it */
3434                 signal(signo, SIG_IGN);
3435         }
3436         sigmode[signo - 1] = S_HARD_IGN;
3437 }
3438
3439 /*
3440  * Only one usage site - in setsignal()
3441  */
3442 static void
3443 signal_handler(int signo)
3444 {
3445         if (signo == SIGCHLD) {
3446                 got_sigchld = 1;
3447                 if (!trap[SIGCHLD])
3448                         return;
3449         }
3450
3451         gotsig[signo - 1] = 1;
3452         pending_sig = signo;
3453
3454         if (signo == SIGINT && !trap[SIGINT]) {
3455                 if (!suppress_int) {
3456                         pending_sig = 0;
3457                         raise_interrupt(); /* does not return */
3458                 }
3459                 pending_int = 1;
3460         }
3461 }
3462
3463 /*
3464  * Set the signal handler for the specified signal.  The routine figures
3465  * out what it should be set to.
3466  */
3467 static void
3468 setsignal(int signo)
3469 {
3470         char *t;
3471         char cur_act, new_act;
3472         struct sigaction act;
3473
3474         t = trap[signo];
3475         new_act = S_DFL;
3476         if (t != NULL) { /* trap for this sig is set */
3477                 new_act = S_CATCH;
3478                 if (t[0] == '\0') /* trap is "": ignore this sig */
3479                         new_act = S_IGN;
3480         }
3481
3482         if (rootshell && new_act == S_DFL) {
3483                 switch (signo) {
3484                 case SIGINT:
3485                         if (iflag || minusc || sflag == 0)
3486                                 new_act = S_CATCH;
3487                         break;
3488                 case SIGQUIT:
3489 #if DEBUG
3490                         if (debug)
3491                                 break;
3492 #endif
3493                         /* man bash:
3494                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3495                          * commands run by bash have signal handlers
3496                          * set to the values inherited by the shell
3497                          * from its parent". */
3498                         new_act = S_IGN;
3499                         break;
3500                 case SIGTERM:
3501                         if (iflag)
3502                                 new_act = S_IGN;
3503                         break;
3504 #if JOBS
3505                 case SIGTSTP:
3506                 case SIGTTOU:
3507                         if (mflag)
3508                                 new_act = S_IGN;
3509                         break;
3510 #endif
3511                 }
3512         }
3513 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3514 //whereas we have to restore it to what shell got on entry
3515 //from the parent. See comment above
3516
3517         if (signo == SIGCHLD)
3518                 new_act = S_CATCH;
3519
3520         t = &sigmode[signo - 1];
3521         cur_act = *t;
3522         if (cur_act == 0) {
3523                 /* current setting is not yet known */
3524                 if (sigaction(signo, NULL, &act)) {
3525                         /* pretend it worked; maybe we should give a warning,
3526                          * but other shells don't. We don't alter sigmode,
3527                          * so we retry every time.
3528                          * btw, in Linux it never fails. --vda */
3529                         return;
3530                 }
3531                 if (act.sa_handler == SIG_IGN) {
3532                         cur_act = S_HARD_IGN;
3533                         if (mflag
3534                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3535                         ) {
3536                                 cur_act = S_IGN;   /* don't hard ignore these */
3537                         }
3538                 }
3539         }
3540         if (cur_act == S_HARD_IGN || cur_act == new_act)
3541                 return;
3542
3543         act.sa_handler = SIG_DFL;
3544         switch (new_act) {
3545         case S_CATCH:
3546                 act.sa_handler = signal_handler;
3547                 break;
3548         case S_IGN:
3549                 act.sa_handler = SIG_IGN;
3550                 break;
3551         }
3552
3553         /* flags and mask matter only if !DFL and !IGN, but we do it
3554          * for all cases for more deterministic behavior:
3555          */
3556         act.sa_flags = 0;
3557         sigfillset(&act.sa_mask);
3558
3559         sigaction_set(signo, &act);
3560
3561         *t = new_act;
3562 }
3563
3564 /* mode flags for set_curjob */
3565 #define CUR_DELETE 2
3566 #define CUR_RUNNING 1
3567 #define CUR_STOPPED 0
3568
3569 #if JOBS
3570 /* pgrp of shell on invocation */
3571 static int initialpgrp; //references:2
3572 static int ttyfd = -1; //5
3573 #endif
3574 /* array of jobs */
3575 static struct job *jobtab; //5
3576 /* size of array */
3577 static unsigned njobs; //4
3578 /* current job */
3579 static struct job *curjob; //lots
3580 /* number of presumed living untracked jobs */
3581 static int jobless; //4
3582
3583 #if 0
3584 /* Bash has a feature: it restores termios after a successful wait for
3585  * a foreground job which had at least one stopped or sigkilled member.
3586  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3587  * properly restoring tty state. Should we do this too?
3588  * A reproducer: ^Z an interactive python:
3589  *
3590  * # python
3591  * Python 2.7.12 (...)
3592  * >>> ^Z
3593  *      { python leaves tty in -icanon -echo state. We do survive that... }
3594  *  [1]+  Stopped                    python
3595  *      { ...however, next program (python #2) does not survive it well: }
3596  * # python
3597  * Python 2.7.12 (...)
3598  * >>> Traceback (most recent call last):
3599  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3600  *   File "<stdin>", line 1, in <module>
3601  * NameError: name 'qwerty' is not defined
3602  *
3603  * The implementation below is modeled on bash code and seems to work.
3604  * However, I'm not sure we should do this. For one: what if I'd fg
3605  * the stopped python instead? It'll be confused by "restored" tty state.
3606  */
3607 static struct termios shell_tty_info;
3608 static void
3609 get_tty_state(void)
3610 {
3611         if (rootshell && ttyfd >= 0)
3612                 tcgetattr(ttyfd, &shell_tty_info);
3613 }
3614 static void
3615 set_tty_state(void)
3616 {
3617         /* if (rootshell) - caller ensures this */
3618         if (ttyfd >= 0)
3619                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3620 }
3621 static int
3622 job_signal_status(struct job *jp)
3623 {
3624         int status;
3625         unsigned i;
3626         struct procstat *ps = jp->ps;
3627         for (i = 0; i < jp->nprocs; i++) {
3628                 status = ps[i].ps_status;
3629                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3630                         return status;
3631         }
3632         return 0;
3633 }
3634 static void
3635 restore_tty_if_stopped_or_signaled(struct job *jp)
3636 {
3637 //TODO: check what happens if we come from waitforjob() in expbackq()
3638         if (rootshell) {
3639                 int s = job_signal_status(jp);
3640                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3641                         set_tty_state();
3642         }
3643 }
3644 #else
3645 # define get_tty_state() ((void)0)
3646 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3647 #endif
3648
3649 static void
3650 set_curjob(struct job *jp, unsigned mode)
3651 {
3652         struct job *jp1;
3653         struct job **jpp, **curp;
3654
3655         /* first remove from list */
3656         jpp = curp = &curjob;
3657         while (1) {
3658                 jp1 = *jpp;
3659                 if (jp1 == jp)
3660                         break;
3661                 jpp = &jp1->prev_job;
3662         }
3663         *jpp = jp1->prev_job;
3664
3665         /* Then re-insert in correct position */
3666         jpp = curp;
3667         switch (mode) {
3668         default:
3669 #if DEBUG
3670                 abort();
3671 #endif
3672         case CUR_DELETE:
3673                 /* job being deleted */
3674                 break;
3675         case CUR_RUNNING:
3676                 /* newly created job or backgrounded job,
3677                  * put after all stopped jobs.
3678                  */
3679                 while (1) {
3680                         jp1 = *jpp;
3681 #if JOBS
3682                         if (!jp1 || jp1->state != JOBSTOPPED)
3683 #endif
3684                                 break;
3685                         jpp = &jp1->prev_job;
3686                 }
3687                 /* FALLTHROUGH */
3688 #if JOBS
3689         case CUR_STOPPED:
3690 #endif
3691                 /* newly stopped job - becomes curjob */
3692                 jp->prev_job = *jpp;
3693                 *jpp = jp;
3694                 break;
3695         }
3696 }
3697
3698 #if JOBS || DEBUG
3699 static int
3700 jobno(const struct job *jp)
3701 {
3702         return jp - jobtab + 1;
3703 }
3704 #endif
3705
3706 /*
3707  * Convert a job name to a job structure.
3708  */
3709 #if !JOBS
3710 #define getjob(name, getctl) getjob(name)
3711 #endif
3712 static struct job *
3713 getjob(const char *name, int getctl)
3714 {
3715         struct job *jp;
3716         struct job *found;
3717         const char *err_msg = "%s: no such job";
3718         unsigned num;
3719         int c;
3720         const char *p;
3721         char *(*match)(const char *, const char *);
3722
3723         jp = curjob;
3724         p = name;
3725         if (!p)
3726                 goto currentjob;
3727
3728         if (*p != '%')
3729                 goto err;
3730
3731         c = *++p;
3732         if (!c)
3733                 goto currentjob;
3734
3735         if (!p[1]) {
3736                 if (c == '+' || c == '%') {
3737  currentjob:
3738                         err_msg = "No current job";
3739                         goto check;
3740                 }
3741                 if (c == '-') {
3742                         if (jp)
3743                                 jp = jp->prev_job;
3744                         err_msg = "No previous job";
3745  check:
3746                         if (!jp)
3747                                 goto err;
3748                         goto gotit;
3749                 }
3750         }
3751
3752         if (is_number(p)) {
3753                 num = atoi(p);
3754                 if (num > 0 && num <= njobs) {
3755                         jp = jobtab + num - 1;
3756                         if (jp->used)
3757                                 goto gotit;
3758                         goto err;
3759                 }
3760         }
3761
3762         match = prefix;
3763         if (*p == '?') {
3764                 match = strstr;
3765                 p++;
3766         }
3767
3768         found = NULL;
3769         while (jp) {
3770                 if (match(jp->ps[0].ps_cmd, p)) {
3771                         if (found)
3772                                 goto err;
3773                         found = jp;
3774                         err_msg = "%s: ambiguous";
3775                 }
3776                 jp = jp->prev_job;
3777         }
3778         if (!found)
3779                 goto err;
3780         jp = found;
3781
3782  gotit:
3783 #if JOBS
3784         err_msg = "job %s not created under job control";
3785         if (getctl && jp->jobctl == 0)
3786                 goto err;
3787 #endif
3788         return jp;
3789  err:
3790         ash_msg_and_raise_error(err_msg, name);
3791 }
3792
3793 /*
3794  * Mark a job structure as unused.
3795  */
3796 static void
3797 freejob(struct job *jp)
3798 {
3799         struct procstat *ps;
3800         int i;
3801
3802         INT_OFF;
3803         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3804                 if (ps->ps_cmd != nullstr)
3805                         free(ps->ps_cmd);
3806         }
3807         if (jp->ps != &jp->ps0)
3808                 free(jp->ps);
3809         jp->used = 0;
3810         set_curjob(jp, CUR_DELETE);
3811         INT_ON;
3812 }
3813
3814 #if JOBS
3815 static void
3816 xtcsetpgrp(int fd, pid_t pgrp)
3817 {
3818         if (tcsetpgrp(fd, pgrp))
3819                 ash_msg_and_raise_error("can't set tty process group (%m)");
3820 }
3821
3822 /*
3823  * Turn job control on and off.
3824  *
3825  * Note:  This code assumes that the third arg to ioctl is a character
3826  * pointer, which is true on Berkeley systems but not System V.  Since
3827  * System V doesn't have job control yet, this isn't a problem now.
3828  *
3829  * Called with interrupts off.
3830  */
3831 static void
3832 setjobctl(int on)
3833 {
3834         int fd;
3835         int pgrp;
3836
3837         if (on == doing_jobctl || rootshell == 0)
3838                 return;
3839         if (on) {
3840                 int ofd;
3841                 ofd = fd = open(_PATH_TTY, O_RDWR);
3842                 if (fd < 0) {
3843         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3844          * That sometimes helps to acquire controlling tty.
3845          * Obviously, a workaround for bugs when someone
3846          * failed to provide a controlling tty to bash! :) */
3847                         fd = 2;
3848                         while (!isatty(fd))
3849                                 if (--fd < 0)
3850                                         goto out;
3851                 }
3852                 /* fd is a tty at this point */
3853                 fd = fcntl(fd, F_DUPFD, 10);
3854                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, dont */
3855                         close(ofd);
3856                 if (fd < 0)
3857                         goto out; /* F_DUPFD failed */
3858                 close_on_exec_on(fd);
3859                 while (1) { /* while we are in the background */
3860                         pgrp = tcgetpgrp(fd);
3861                         if (pgrp < 0) {
3862  out:
3863                                 ash_msg("can't access tty; job control turned off");
3864                                 mflag = on = 0;
3865                                 goto close;
3866                         }
3867                         if (pgrp == getpgrp())
3868                                 break;
3869                         killpg(0, SIGTTIN);
3870                 }
3871                 initialpgrp = pgrp;
3872
3873                 setsignal(SIGTSTP);
3874                 setsignal(SIGTTOU);
3875                 setsignal(SIGTTIN);
3876                 pgrp = rootpid;
3877                 setpgid(0, pgrp);
3878                 xtcsetpgrp(fd, pgrp);
3879         } else {
3880                 /* turning job control off */
3881                 fd = ttyfd;
3882                 pgrp = initialpgrp;
3883                 /* was xtcsetpgrp, but this can make exiting ash
3884                  * loop forever if pty is already deleted */
3885                 tcsetpgrp(fd, pgrp);
3886                 setpgid(0, pgrp);
3887                 setsignal(SIGTSTP);
3888                 setsignal(SIGTTOU);
3889                 setsignal(SIGTTIN);
3890  close:
3891                 if (fd >= 0)
3892                         close(fd);
3893                 fd = -1;
3894         }
3895         ttyfd = fd;
3896         doing_jobctl = on;
3897 }
3898
3899 static int FAST_FUNC
3900 killcmd(int argc, char **argv)
3901 {
3902         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3903                 int i = 1;
3904                 do {
3905                         if (argv[i][0] == '%') {
3906                                 /*
3907                                  * "kill %N" - job kill
3908                                  * Converting to pgrp / pid kill
3909                                  */
3910                                 struct job *jp;
3911                                 char *dst;
3912                                 int j, n;
3913
3914                                 jp = getjob(argv[i], 0);
3915                                 /*
3916                                  * In jobs started under job control, we signal
3917                                  * entire process group by kill -PGRP_ID.
3918                                  * This happens, f.e., in interactive shell.
3919                                  *
3920                                  * Otherwise, we signal each child via
3921                                  * kill PID1 PID2 PID3.
3922                                  * Testcases:
3923                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3924                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3925                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3926                                  */
3927                                 n = jp->nprocs; /* can't be 0 (I hope) */
3928                                 if (jp->jobctl)
3929                                         n = 1;
3930                                 dst = alloca(n * sizeof(int)*4);
3931                                 argv[i] = dst;
3932                                 for (j = 0; j < n; j++) {
3933                                         struct procstat *ps = &jp->ps[j];
3934                                         /* Skip non-running and not-stopped members
3935                                          * (i.e. dead members) of the job
3936                                          */
3937                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3938                                                 continue;
3939                                         /*
3940                                          * kill_main has matching code to expect
3941                                          * leading space. Needed to not confuse
3942                                          * negative pids with "kill -SIGNAL_NO" syntax
3943                                          */
3944                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3945                                 }
3946                                 *dst = '\0';
3947                         }
3948                 } while (argv[++i]);
3949         }
3950         return kill_main(argc, argv);
3951 }
3952
3953 static void
3954 showpipe(struct job *jp /*, FILE *out*/)
3955 {
3956         struct procstat *ps;
3957         struct procstat *psend;
3958
3959         psend = jp->ps + jp->nprocs;
3960         for (ps = jp->ps + 1; ps < psend; ps++)
3961                 printf(" | %s", ps->ps_cmd);
3962         newline_and_flush(stdout);
3963         flush_stdout_stderr();
3964 }
3965
3966
3967 static int
3968 restartjob(struct job *jp, int mode)
3969 {
3970         struct procstat *ps;
3971         int i;
3972         int status;
3973         pid_t pgid;
3974
3975         INT_OFF;
3976         if (jp->state == JOBDONE)
3977                 goto out;
3978         jp->state = JOBRUNNING;
3979         pgid = jp->ps[0].ps_pid;
3980         if (mode == FORK_FG) {
3981                 get_tty_state();
3982                 xtcsetpgrp(ttyfd, pgid);
3983         }
3984         killpg(pgid, SIGCONT);
3985         ps = jp->ps;
3986         i = jp->nprocs;
3987         do {
3988                 if (WIFSTOPPED(ps->ps_status)) {
3989                         ps->ps_status = -1;
3990                 }
3991                 ps++;
3992         } while (--i);
3993  out:
3994         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3995         INT_ON;
3996         return status;
3997 }
3998
3999 static int FAST_FUNC
4000 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4001 {
4002         struct job *jp;
4003         int mode;
4004         int retval;
4005
4006         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4007         nextopt(nullstr);
4008         argv = argptr;
4009         do {
4010                 jp = getjob(*argv, 1);
4011                 if (mode == FORK_BG) {
4012                         set_curjob(jp, CUR_RUNNING);
4013                         printf("[%d] ", jobno(jp));
4014                 }
4015                 out1str(jp->ps[0].ps_cmd);
4016                 showpipe(jp /*, stdout*/);
4017                 retval = restartjob(jp, mode);
4018         } while (*argv && *++argv);
4019         return retval;
4020 }
4021 #endif
4022
4023 static int
4024 sprint_status48(char *s, int status, int sigonly)
4025 {
4026         int col;
4027         int st;
4028
4029         col = 0;
4030         if (!WIFEXITED(status)) {
4031                 if (JOBS && WIFSTOPPED(status))
4032                         st = WSTOPSIG(status);
4033                 else
4034                         st = WTERMSIG(status);
4035                 if (sigonly) {
4036                         if (st == SIGINT || st == SIGPIPE)
4037                                 goto out;
4038                         if (JOBS && WIFSTOPPED(status))
4039                                 goto out;
4040                 }
4041                 st &= 0x7f;
4042 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4043                 col = fmtstr(s, 32, strsignal(st));
4044                 if (WCOREDUMP(status)) {
4045                         strcpy(s + col, " (core dumped)");
4046                         col += sizeof(" (core dumped)")-1;
4047                 }
4048         } else if (!sigonly) {
4049                 st = WEXITSTATUS(status);
4050                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4051         }
4052  out:
4053         return col;
4054 }
4055
4056 static int
4057 wait_block_or_sig(int *status)
4058 {
4059         int pid;
4060
4061         do {
4062                 sigset_t mask;
4063
4064                 /* Poll all children for changes in their state */
4065                 got_sigchld = 0;
4066                 /* if job control is active, accept stopped processes too */
4067                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4068                 if (pid != 0)
4069                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4070
4071                 /* Children exist, but none are ready. Sleep until interesting signal */
4072 #if 1
4073                 sigfillset(&mask);
4074                 sigprocmask(SIG_SETMASK, &mask, &mask);
4075                 while (!got_sigchld && !pending_sig)
4076                         sigsuspend(&mask);
4077                 sigprocmask(SIG_SETMASK, &mask, NULL);
4078 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4079                 while (!got_sigchld && !pending_sig)
4080                         pause();
4081 #endif
4082
4083                 /* If it was SIGCHLD, poll children again */
4084         } while (got_sigchld);
4085
4086         return pid;
4087 }
4088
4089 #define DOWAIT_NONBLOCK 0
4090 #define DOWAIT_BLOCK    1
4091 #define DOWAIT_BLOCK_OR_SIG 2
4092
4093 static int
4094 dowait(int block, struct job *job)
4095 {
4096         int pid;
4097         int status;
4098         struct job *jp;
4099         struct job *thisjob = NULL;
4100
4101         TRACE(("dowait(0x%x) called\n", block));
4102
4103         /* It's wrong to call waitpid() outside of INT_OFF region:
4104          * signal can arrive just after syscall return and handler can
4105          * longjmp away, losing stop/exit notification processing.
4106          * Thus, for "jobs" builtin, and for waiting for a fg job,
4107          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4108          *
4109          * However, for "wait" builtin it is wrong to simply call waitpid()
4110          * in INT_OFF region: "wait" needs to wait for any running job
4111          * to change state, but should exit on any trap too.
4112          * In INT_OFF region, a signal just before syscall entry can set
4113          * pending_sig variables, but we can't check them, and we would
4114          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4115          *
4116          * Because of this, we run inside INT_OFF, but use a special routine
4117          * which combines waitpid() and sigsuspend().
4118          * This is the reason why we need to have a handler for SIGCHLD:
4119          * SIG_DFL handler does not wake sigsuspend().
4120          */
4121         INT_OFF;
4122         if (block == DOWAIT_BLOCK_OR_SIG) {
4123                 pid = wait_block_or_sig(&status);
4124         } else {
4125                 int wait_flags = 0;
4126                 if (block == DOWAIT_NONBLOCK)
4127                         wait_flags = WNOHANG;
4128                 /* if job control is active, accept stopped processes too */
4129                 if (doing_jobctl)
4130                         wait_flags |= WUNTRACED;
4131                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4132                 pid = waitpid(-1, &status, wait_flags);
4133         }
4134         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4135                                 pid, status, errno, strerror(errno)));
4136         if (pid <= 0)
4137                 goto out;
4138
4139         thisjob = NULL;
4140         for (jp = curjob; jp; jp = jp->prev_job) {
4141                 int jobstate;
4142                 struct procstat *ps;
4143                 struct procstat *psend;
4144                 if (jp->state == JOBDONE)
4145                         continue;
4146                 jobstate = JOBDONE;
4147                 ps = jp->ps;
4148                 psend = ps + jp->nprocs;
4149                 do {
4150                         if (ps->ps_pid == pid) {
4151                                 TRACE(("Job %d: changing status of proc %d "
4152                                         "from 0x%x to 0x%x\n",
4153                                         jobno(jp), pid, ps->ps_status, status));
4154                                 ps->ps_status = status;
4155                                 thisjob = jp;
4156                         }
4157                         if (ps->ps_status == -1)
4158                                 jobstate = JOBRUNNING;
4159 #if JOBS
4160                         if (jobstate == JOBRUNNING)
4161                                 continue;
4162                         if (WIFSTOPPED(ps->ps_status)) {
4163                                 jp->stopstatus = ps->ps_status;
4164                                 jobstate = JOBSTOPPED;
4165                         }
4166 #endif
4167                 } while (++ps < psend);
4168                 if (!thisjob)
4169                         continue;
4170
4171                 /* Found the job where one of its processes changed its state.
4172                  * Is there at least one live and running process in this job? */
4173                 if (jobstate != JOBRUNNING) {
4174                         /* No. All live processes in the job are stopped
4175                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4176                          */
4177                         thisjob->changed = 1;
4178                         if (thisjob->state != jobstate) {
4179                                 TRACE(("Job %d: changing state from %d to %d\n",
4180                                         jobno(thisjob), thisjob->state, jobstate));
4181                                 thisjob->state = jobstate;
4182 #if JOBS
4183                                 if (jobstate == JOBSTOPPED)
4184                                         set_curjob(thisjob, CUR_STOPPED);
4185 #endif
4186                         }
4187                 }
4188                 goto out;
4189         }
4190         /* The process wasn't found in job list */
4191         if (JOBS && !WIFSTOPPED(status))
4192                 jobless--;
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                         inquotes = ~inquotes;
5923                         p++;
5924                         protect_against_glob = globbing;
5925                         continue;
5926                 }
5927                 if ((unsigned char)*p == CTLESC) {
5928                         p++;
5929 #if DEBUG
5930                         if (*p == '\0')
5931                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5932 #endif
5933                         if (protect_against_glob) {
5934                                 *q++ = '\\';
5935                         }
5936                 } else if (*p == '\\' && !inquotes) {
5937                         /* naked back slash */
5938                         protect_against_glob = 0;
5939                         goto copy;
5940                 }
5941 #if BASH_PATTERN_SUBST
5942                 else if (*p == '/' && slash) {
5943                         /* stop handling globbing and mark location of slash */
5944                         globbing = slash = 0;
5945                         *p = CTLESC;
5946                 }
5947 #endif
5948                 protect_against_glob = globbing;
5949  copy:
5950                 *q++ = *p++;
5951         }
5952         *q = '\0';
5953         if (flag & RMESCAPE_GROW) {
5954                 expdest = r;
5955                 STADJUST(q - r + 1, expdest);
5956         }
5957         return r;
5958 }
5959 #define pmatch(a, b) !fnmatch((a), (b), 0)
5960
5961 /*
5962  * Prepare a pattern for a expmeta (internal glob(3)) call.
5963  *
5964  * Returns an stalloced string.
5965  */
5966 static char *
5967 preglob(const char *pattern, int flag)
5968 {
5969         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5970 }
5971
5972 /*
5973  * Put a string on the stack.
5974  */
5975 static void
5976 memtodest(const char *p, size_t len, int syntax, int quotes)
5977 {
5978         char *q;
5979
5980         if (!len)
5981                 return;
5982
5983         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5984
5985         do {
5986                 unsigned char c = *p++;
5987                 if (c) {
5988                         if (quotes & QUOTES_ESC) {
5989                                 int n = SIT(c, syntax);
5990                                 if (n == CCTL
5991                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5992                                      && n == CBACK
5993                                     )
5994                                 ) {
5995                                         USTPUTC(CTLESC, q);
5996                                 }
5997                         }
5998                 } else if (!(quotes & QUOTES_KEEPNUL))
5999                         continue;
6000                 USTPUTC(c, q);
6001         } while (--len);
6002
6003         expdest = q;
6004 }
6005
6006 static size_t
6007 strtodest(const char *p, int syntax, int quotes)
6008 {
6009         size_t len = strlen(p);
6010         memtodest(p, len, syntax, quotes);
6011         return len;
6012 }
6013
6014 /*
6015  * Record the fact that we have to scan this region of the
6016  * string for IFS characters.
6017  */
6018 static void
6019 recordregion(int start, int end, int nulonly)
6020 {
6021         struct ifsregion *ifsp;
6022
6023         if (ifslastp == NULL) {
6024                 ifsp = &ifsfirst;
6025         } else {
6026                 INT_OFF;
6027                 ifsp = ckzalloc(sizeof(*ifsp));
6028                 /*ifsp->next = NULL; - ckzalloc did it */
6029                 ifslastp->next = ifsp;
6030                 INT_ON;
6031         }
6032         ifslastp = ifsp;
6033         ifslastp->begoff = start;
6034         ifslastp->endoff = end;
6035         ifslastp->nulonly = nulonly;
6036 }
6037
6038 static void
6039 removerecordregions(int endoff)
6040 {
6041         if (ifslastp == NULL)
6042                 return;
6043
6044         if (ifsfirst.endoff > endoff) {
6045                 while (ifsfirst.next) {
6046                         struct ifsregion *ifsp;
6047                         INT_OFF;
6048                         ifsp = ifsfirst.next->next;
6049                         free(ifsfirst.next);
6050                         ifsfirst.next = ifsp;
6051                         INT_ON;
6052                 }
6053                 if (ifsfirst.begoff > endoff) {
6054                         ifslastp = NULL;
6055                 } else {
6056                         ifslastp = &ifsfirst;
6057                         ifsfirst.endoff = endoff;
6058                 }
6059                 return;
6060         }
6061
6062         ifslastp = &ifsfirst;
6063         while (ifslastp->next && ifslastp->next->begoff < endoff)
6064                 ifslastp = ifslastp->next;
6065         while (ifslastp->next) {
6066                 struct ifsregion *ifsp;
6067                 INT_OFF;
6068                 ifsp = ifslastp->next->next;
6069                 free(ifslastp->next);
6070                 ifslastp->next = ifsp;
6071                 INT_ON;
6072         }
6073         if (ifslastp->endoff > endoff)
6074                 ifslastp->endoff = endoff;
6075 }
6076
6077 static char *
6078 exptilde(char *startp, char *p, int flags)
6079 {
6080         unsigned char c;
6081         char *name;
6082         struct passwd *pw;
6083         const char *home;
6084         int quotes = flags & QUOTES_ESC;
6085
6086         name = p + 1;
6087
6088         while ((c = *++p) != '\0') {
6089                 switch (c) {
6090                 case CTLESC:
6091                         return startp;
6092                 case CTLQUOTEMARK:
6093                         return startp;
6094                 case ':':
6095                         if (flags & EXP_VARTILDE)
6096                                 goto done;
6097                         break;
6098                 case '/':
6099                 case CTLENDVAR:
6100                         goto done;
6101                 }
6102         }
6103  done:
6104         *p = '\0';
6105         if (*name == '\0') {
6106                 home = lookupvar("HOME");
6107         } else {
6108                 pw = getpwnam(name);
6109                 if (pw == NULL)
6110                         goto lose;
6111                 home = pw->pw_dir;
6112         }
6113         if (!home || !*home)
6114                 goto lose;
6115         *p = c;
6116         strtodest(home, SQSYNTAX, quotes);
6117         return p;
6118  lose:
6119         *p = c;
6120         return startp;
6121 }
6122
6123 /*
6124  * Execute a command inside back quotes.  If it's a builtin command, we
6125  * want to save its output in a block obtained from malloc.  Otherwise
6126  * we fork off a subprocess and get the output of the command via a pipe.
6127  * Should be called with interrupts off.
6128  */
6129 struct backcmd {                /* result of evalbackcmd */
6130         int fd;                 /* file descriptor to read from */
6131         int nleft;              /* number of chars in buffer */
6132         char *buf;              /* buffer */
6133         struct job *jp;         /* job structure for command */
6134 };
6135
6136 /* These forward decls are needed to use "eval" code for backticks handling: */
6137 #define EV_EXIT 01              /* exit after evaluating tree */
6138 static int evaltree(union node *, int);
6139
6140 static void FAST_FUNC
6141 evalbackcmd(union node *n, struct backcmd *result)
6142 {
6143         int pip[2];
6144         struct job *jp;
6145
6146         result->fd = -1;
6147         result->buf = NULL;
6148         result->nleft = 0;
6149         result->jp = NULL;
6150         if (n == NULL) {
6151                 goto out;
6152         }
6153
6154         if (pipe(pip) < 0)
6155                 ash_msg_and_raise_error("pipe call failed");
6156         jp = makejob(/*n,*/ 1);
6157         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6158                 /* child */
6159                 FORCE_INT_ON;
6160                 close(pip[0]);
6161                 if (pip[1] != 1) {
6162                         /*close(1);*/
6163                         dup2_or_raise(pip[1], 1);
6164                         close(pip[1]);
6165                 }
6166 /* TODO: eflag clearing makes the following not abort:
6167  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6168  * which is what bash does (unless it is in POSIX mode).
6169  * dash deleted "eflag = 0" line in the commit
6170  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6171  *  [EVAL] Don't clear eflag in evalbackcmd
6172  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6173  */
6174                 eflag = 0;
6175                 ifsfree();
6176                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6177                 /* NOTREACHED */
6178         }
6179         /* parent */
6180         close(pip[1]);
6181         result->fd = pip[0];
6182         result->jp = jp;
6183
6184  out:
6185         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6186                 result->fd, result->buf, result->nleft, result->jp));
6187 }
6188
6189 /*
6190  * Expand stuff in backwards quotes.
6191  */
6192 static void
6193 expbackq(union node *cmd, int flag)
6194 {
6195         struct backcmd in;
6196         int i;
6197         char buf[128];
6198         char *p;
6199         char *dest;
6200         int startloc;
6201         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6202         struct stackmark smark;
6203
6204         INT_OFF;
6205         startloc = expdest - (char *)stackblock();
6206         pushstackmark(&smark, startloc);
6207         evalbackcmd(cmd, &in);
6208         popstackmark(&smark);
6209
6210         p = in.buf;
6211         i = in.nleft;
6212         if (i == 0)
6213                 goto read;
6214         for (;;) {
6215                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6216  read:
6217                 if (in.fd < 0)
6218                         break;
6219                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6220                 TRACE(("expbackq: read returns %d\n", i));
6221                 if (i <= 0)
6222                         break;
6223                 p = buf;
6224         }
6225
6226         free(in.buf);
6227         if (in.fd >= 0) {
6228                 close(in.fd);
6229                 back_exitstatus = waitforjob(in.jp);
6230         }
6231         INT_ON;
6232
6233         /* Eat all trailing newlines */
6234         dest = expdest;
6235         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6236                 STUNPUTC(dest);
6237         expdest = dest;
6238
6239         if (!(flag & EXP_QUOTED))
6240                 recordregion(startloc, dest - (char *)stackblock(), 0);
6241         TRACE(("evalbackq: size:%d:'%.*s'\n",
6242                 (int)((dest - (char *)stackblock()) - startloc),
6243                 (int)((dest - (char *)stackblock()) - startloc),
6244                 stackblock() + startloc));
6245 }
6246
6247 #if ENABLE_FEATURE_SH_MATH
6248 /*
6249  * Expand arithmetic expression.  Backup to start of expression,
6250  * evaluate, place result in (backed up) result, adjust string position.
6251  */
6252 static void
6253 expari(int flag)
6254 {
6255         char *p, *start;
6256         int begoff;
6257         int len;
6258
6259         /* ifsfree(); */
6260
6261         /*
6262          * This routine is slightly over-complicated for
6263          * efficiency.  Next we scan backwards looking for the
6264          * start of arithmetic.
6265          */
6266         start = stackblock();
6267         p = expdest - 1;
6268         *p = '\0';
6269         p--;
6270         while (1) {
6271                 int esc;
6272
6273                 while ((unsigned char)*p != CTLARI) {
6274                         p--;
6275 #if DEBUG
6276                         if (p < start) {
6277                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6278                         }
6279 #endif
6280                 }
6281
6282                 esc = esclen(start, p);
6283                 if (!(esc % 2)) {
6284                         break;
6285                 }
6286
6287                 p -= esc + 1;
6288         }
6289
6290         begoff = p - start;
6291
6292         removerecordregions(begoff);
6293
6294         expdest = p;
6295
6296         if (flag & QUOTES_ESC)
6297                 rmescapes(p + 1, 0);
6298
6299         len = cvtnum(ash_arith(p + 1));
6300
6301         if (!(flag & EXP_QUOTED))
6302                 recordregion(begoff, begoff + len, 0);
6303 }
6304 #endif
6305
6306 /* argstr needs it */
6307 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6308
6309 /*
6310  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6311  * characters to allow for further processing.  Otherwise treat
6312  * $@ like $* since no splitting will be performed.
6313  *
6314  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6315  * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
6316  * for correct expansion of "B=$A" word.
6317  */
6318 static void
6319 argstr(char *p, int flags, struct strlist *var_str_list)
6320 {
6321         static const char spclchars[] ALIGN1 = {
6322                 '=',
6323                 ':',
6324                 CTLQUOTEMARK,
6325                 CTLENDVAR,
6326                 CTLESC,
6327                 CTLVAR,
6328                 CTLBACKQ,
6329 #if ENABLE_FEATURE_SH_MATH
6330                 CTLENDARI,
6331 #endif
6332                 '\0'
6333         };
6334         const char *reject = spclchars;
6335         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6336         int inquotes;
6337         size_t length;
6338         int startloc;
6339
6340         if (!(flags & EXP_VARTILDE)) {
6341                 reject += 2;
6342         } else if (flags & EXP_VARTILDE2) {
6343                 reject++;
6344         }
6345         inquotes = 0;
6346         length = 0;
6347         if (flags & EXP_TILDE) {
6348                 char *q;
6349
6350                 flags &= ~EXP_TILDE;
6351  tilde:
6352                 q = p;
6353                 if (*q == '~')
6354                         p = exptilde(p, q, flags);
6355         }
6356  start:
6357         startloc = expdest - (char *)stackblock();
6358         for (;;) {
6359                 unsigned char c;
6360
6361                 length += strcspn(p + length, reject);
6362                 c = p[length];
6363                 if (c) {
6364                         if (!(c & 0x80)
6365                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6366                         ) {
6367                                 /* c == '=' || c == ':' || c == CTLENDARI */
6368                                 length++;
6369                         }
6370                 }
6371                 if (length > 0) {
6372                         int newloc;
6373                         expdest = stack_nputstr(p, length, expdest);
6374                         newloc = expdest - (char *)stackblock();
6375                         if (breakall && !inquotes && newloc > startloc) {
6376                                 recordregion(startloc, newloc, 0);
6377                         }
6378                         startloc = newloc;
6379                 }
6380                 p += length + 1;
6381                 length = 0;
6382
6383                 switch (c) {
6384                 case '\0':
6385                         goto breakloop;
6386                 case '=':
6387                         if (flags & EXP_VARTILDE2) {
6388                                 p--;
6389                                 continue;
6390                         }
6391                         flags |= EXP_VARTILDE2;
6392                         reject++;
6393                         /* fall through */
6394                 case ':':
6395                         /*
6396                          * sort of a hack - expand tildes in variable
6397                          * assignments (after the first '=' and after ':'s).
6398                          */
6399                         if (*--p == '~') {
6400                                 goto tilde;
6401                         }
6402                         continue;
6403                 }
6404
6405                 switch (c) {
6406                 case CTLENDVAR: /* ??? */
6407                         goto breakloop;
6408                 case CTLQUOTEMARK:
6409                         inquotes ^= EXP_QUOTED;
6410                         /* "$@" syntax adherence hack */
6411                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6412                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6413                                 goto start;
6414                         }
6415  addquote:
6416                         if (flags & QUOTES_ESC) {
6417                                 p--;
6418                                 length++;
6419                                 startloc++;
6420                         }
6421                         break;
6422                 case CTLESC:
6423                         startloc++;
6424                         length++;
6425
6426                         /*
6427                          * Quoted parameter expansion pattern: remove quote
6428                          * unless inside inner quotes or we have a literal
6429                          * backslash.
6430                          */
6431                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6432                             EXP_QPAT && *p != '\\')
6433                                 break;
6434
6435                         goto addquote;
6436                 case CTLVAR:
6437                         TRACE(("argstr: evalvar('%s')\n", p));
6438                         p = evalvar(p, flags | inquotes, var_str_list);
6439                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6440                         goto start;
6441                 case CTLBACKQ:
6442                         expbackq(argbackq->n, flags | inquotes);
6443                         argbackq = argbackq->next;
6444                         goto start;
6445 #if ENABLE_FEATURE_SH_MATH
6446                 case CTLENDARI:
6447                         p--;
6448                         expari(flags | inquotes);
6449                         goto start;
6450 #endif
6451                 }
6452         }
6453  breakloop: ;
6454 }
6455
6456 static char *
6457 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6458                 char *pattern, int quotes, int zero)
6459 {
6460         char *loc, *loc2;
6461         char c;
6462
6463         loc = startp;
6464         loc2 = rmesc;
6465         do {
6466                 int match;
6467                 const char *s = loc2;
6468
6469                 c = *loc2;
6470                 if (zero) {
6471                         *loc2 = '\0';
6472                         s = rmesc;
6473                 }
6474                 match = pmatch(pattern, s);
6475
6476                 *loc2 = c;
6477                 if (match)
6478                         return loc;
6479                 if (quotes && (unsigned char)*loc == CTLESC)
6480                         loc++;
6481                 loc++;
6482                 loc2++;
6483         } while (c);
6484         return NULL;
6485 }
6486
6487 static char *
6488 scanright(char *startp, char *rmesc, char *rmescend,
6489                 char *pattern, int quotes, int match_at_start)
6490 {
6491 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6492         int try2optimize = match_at_start;
6493 #endif
6494         int esc = 0;
6495         char *loc;
6496         char *loc2;
6497
6498         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6499          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6500          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6501          * Logic:
6502          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6503          * and on each iteration they go back two/one char until they reach the beginning.
6504          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6505          */
6506         /* TODO: document in what other circumstances we are called. */
6507
6508         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6509                 int match;
6510                 char c = *loc2;
6511                 const char *s = loc2;
6512                 if (match_at_start) {
6513                         *loc2 = '\0';
6514                         s = rmesc;
6515                 }
6516                 match = pmatch(pattern, s);
6517                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6518                 *loc2 = c;
6519                 if (match)
6520                         return loc;
6521 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6522                 if (try2optimize) {
6523                         /* Maybe we can optimize this:
6524                          * if pattern ends with unescaped *, we can avoid checking
6525                          * shorter strings: if "foo*" doesnt match "raw_value_of_v",
6526                          * it wont match truncated "raw_value_of_" strings too.
6527                          */
6528                         unsigned plen = strlen(pattern);
6529                         /* Does it end with "*"? */
6530                         if (plen != 0 && pattern[--plen] == '*') {
6531                                 /* "xxxx*" is not escaped */
6532                                 /* "xxx\*" is escaped */
6533                                 /* "xx\\*" is not escaped */
6534                                 /* "x\\\*" is escaped */
6535                                 int slashes = 0;
6536                                 while (plen != 0 && pattern[--plen] == '\\')
6537                                         slashes++;
6538                                 if (!(slashes & 1))
6539                                         break; /* ends with unescaped "*" */
6540                         }
6541                         try2optimize = 0;
6542                 }
6543 #endif
6544                 loc--;
6545                 if (quotes) {
6546                         if (--esc < 0) {
6547                                 esc = esclen(startp, loc);
6548                         }
6549                         if (esc % 2) {
6550                                 esc--;
6551                                 loc--;
6552                         }
6553                 }
6554         }
6555         return NULL;
6556 }
6557
6558 static void varunset(const char *, const char *, const char *, int) NORETURN;
6559 static void
6560 varunset(const char *end, const char *var, const char *umsg, int varflags)
6561 {
6562         const char *msg;
6563         const char *tail;
6564
6565         tail = nullstr;
6566         msg = "parameter not set";
6567         if (umsg) {
6568                 if ((unsigned char)*end == CTLENDVAR) {
6569                         if (varflags & VSNUL)
6570                                 tail = " or null";
6571                 } else {
6572                         msg = umsg;
6573                 }
6574         }
6575         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6576 }
6577
6578 static const char *
6579 subevalvar(char *p, char *varname, int strloc, int subtype,
6580                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6581 {
6582         struct nodelist *saveargbackq = argbackq;
6583         int quotes = flag & QUOTES_ESC;
6584         char *startp;
6585         char *loc;
6586         char *rmesc, *rmescend;
6587         char *str;
6588         IF_BASH_SUBSTR(int pos, len, orig_len;)
6589         int amount, resetloc;
6590         IF_BASH_PATTERN_SUBST(int workloc;)
6591         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6592         int zero;
6593         char *(*scan)(char*, char*, char*, char*, int, int);
6594
6595         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6596         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6597
6598         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6599                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6600                         var_str_list);
6601         STPUTC('\0', expdest);
6602         argbackq = saveargbackq;
6603         startp = (char *)stackblock() + startloc;
6604
6605         switch (subtype) {
6606         case VSASSIGN:
6607                 setvar0(varname, startp);
6608                 amount = startp - expdest;
6609                 STADJUST(amount, expdest);
6610                 return startp;
6611
6612         case VSQUESTION:
6613                 varunset(p, varname, startp, varflags);
6614                 /* NOTREACHED */
6615
6616 #if BASH_SUBSTR
6617         case VSSUBSTR:
6618 //TODO: support more general format ${v:EXPR:EXPR},
6619 // where EXPR follows $(()) rules
6620                 loc = str = stackblock() + strloc;
6621                 /* Read POS in ${var:POS:LEN} */
6622                 pos = atoi(loc); /* number(loc) errors out on "1:4" */
6623                 len = str - startp - 1;
6624
6625                 /* *loc != '\0', guaranteed by parser */
6626                 if (quotes) {
6627                         char *ptr;
6628
6629                         /* Adjust the length by the number of escapes */
6630                         for (ptr = startp; ptr < (str - 1); ptr++) {
6631                                 if ((unsigned char)*ptr == CTLESC) {
6632                                         len--;
6633                                         ptr++;
6634                                 }
6635                         }
6636                 }
6637                 orig_len = len;
6638
6639                 if (*loc++ == ':') {
6640                         /* ${var::LEN} */
6641                         len = number(loc);
6642                 } else {
6643                         /* Skip POS in ${var:POS:LEN} */
6644                         len = orig_len;
6645                         while (*loc && *loc != ':') {
6646                                 /* TODO?
6647                                  * bash complains on: var=qwe; echo ${var:1a:123}
6648                                 if (!isdigit(*loc))
6649                                         ash_msg_and_raise_error(msg_illnum, str);
6650                                  */
6651                                 loc++;
6652                         }
6653                         if (*loc++ == ':') {
6654                                 len = number(loc);
6655                         }
6656                 }
6657                 if (pos < 0) {
6658                         /* ${VAR:$((-n)):l} starts n chars from the end */
6659                         pos = orig_len + pos;
6660                 }
6661                 if ((unsigned)pos >= orig_len) {
6662                         /* apart from obvious ${VAR:999999:l},
6663                          * covers ${VAR:$((-9999999)):l} - result is ""
6664                          * (bash-compat)
6665                          */
6666                         pos = 0;
6667                         len = 0;
6668                 }
6669                 if (len > (orig_len - pos))
6670                         len = orig_len - pos;
6671
6672                 for (str = startp; pos; str++, pos--) {
6673                         if (quotes && (unsigned char)*str == CTLESC)
6674                                 str++;
6675                 }
6676                 for (loc = startp; len; len--) {
6677                         if (quotes && (unsigned char)*str == CTLESC)
6678                                 *loc++ = *str++;
6679                         *loc++ = *str++;
6680                 }
6681                 *loc = '\0';
6682                 amount = loc - expdest;
6683                 STADJUST(amount, expdest);
6684                 return loc;
6685 #endif /* BASH_SUBSTR */
6686         }
6687
6688         resetloc = expdest - (char *)stackblock();
6689
6690 #if BASH_PATTERN_SUBST
6691         /* We'll comeback here if we grow the stack while handling
6692          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6693          * stack will need rebasing, and we'll need to remove our work
6694          * areas each time
6695          */
6696  restart:
6697 #endif
6698
6699         amount = expdest - ((char *)stackblock() + resetloc);
6700         STADJUST(-amount, expdest);
6701         startp = (char *)stackblock() + startloc;
6702
6703         rmesc = startp;
6704         rmescend = (char *)stackblock() + strloc;
6705         if (quotes) {
6706                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6707                 if (rmesc != startp) {
6708                         rmescend = expdest;
6709                         startp = (char *)stackblock() + startloc;
6710                 }
6711         }
6712         rmescend--;
6713         str = (char *)stackblock() + strloc;
6714         /*
6715          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6716          * The result is a_\_z_c (not a\_\_z_c)!
6717          *
6718          * The search pattern and replace string treat backslashes differently!
6719          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6720          * and string.  It's only used on the first call.
6721          */
6722         preglob(str, IF_BASH_PATTERN_SUBST(
6723                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6724                         RMESCAPE_SLASH : ) 0);
6725
6726 #if BASH_PATTERN_SUBST
6727         workloc = expdest - (char *)stackblock();
6728         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6729                 char *idx, *end;
6730
6731                 if (!repl) {
6732                         repl = strchr(str, CTLESC);
6733                         if (repl)
6734                                 *repl++ = '\0';
6735                         else
6736                                 repl = nullstr;
6737                 }
6738                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6739
6740                 /* If there's no pattern to match, return the expansion unmolested */
6741                 if (str[0] == '\0')
6742                         return NULL;
6743
6744                 len = 0;
6745                 idx = startp;
6746                 end = str - 1;
6747                 while (idx < end) {
6748  try_to_match:
6749                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6750                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6751                         if (!loc) {
6752                                 /* No match, advance */
6753                                 char *restart_detect = stackblock();
6754  skip_matching:
6755                                 STPUTC(*idx, expdest);
6756                                 if (quotes && (unsigned char)*idx == CTLESC) {
6757                                         idx++;
6758                                         len++;
6759                                         STPUTC(*idx, expdest);
6760                                 }
6761                                 if (stackblock() != restart_detect)
6762                                         goto restart;
6763                                 idx++;
6764                                 len++;
6765                                 rmesc++;
6766                                 /* continue; - prone to quadratic behavior, smarter code: */
6767                                 if (idx >= end)
6768                                         break;
6769                                 if (str[0] == '*') {
6770                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6771                                          * it would never match "ong_string" etc, no point in trying.
6772                                          */
6773                                         goto skip_matching;
6774                                 }
6775                                 goto try_to_match;
6776                         }
6777
6778                         if (subtype == VSREPLACEALL) {
6779                                 while (idx < loc) {
6780                                         if (quotes && (unsigned char)*idx == CTLESC)
6781                                                 idx++;
6782                                         idx++;
6783                                         rmesc++;
6784                                 }
6785                         } else {
6786                                 idx = loc;
6787                         }
6788
6789                         //bb_error_msg("repl:'%s'", repl);
6790                         for (loc = (char*)repl; *loc; loc++) {
6791                                 char *restart_detect = stackblock();
6792                                 if (quotes && *loc == '\\') {
6793                                         STPUTC(CTLESC, expdest);
6794                                         len++;
6795                                 }
6796                                 STPUTC(*loc, expdest);
6797                                 if (stackblock() != restart_detect)
6798                                         goto restart;
6799                                 len++;
6800                         }
6801
6802                         if (subtype == VSREPLACE) {
6803                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6804                                 while (*idx) {
6805                                         char *restart_detect = stackblock();
6806                                         STPUTC(*idx, expdest);
6807                                         if (stackblock() != restart_detect)
6808                                                 goto restart;
6809                                         len++;
6810                                         idx++;
6811                                 }
6812                                 break;
6813                         }
6814                 }
6815
6816                 /* We've put the replaced text into a buffer at workloc, now
6817                  * move it to the right place and adjust the stack.
6818                  */
6819                 STPUTC('\0', expdest);
6820                 startp = (char *)stackblock() + startloc;
6821                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6822                 //bb_error_msg("startp:'%s'", startp);
6823                 amount = expdest - (startp + len);
6824                 STADJUST(-amount, expdest);
6825                 return startp;
6826         }
6827 #endif /* BASH_PATTERN_SUBST */
6828
6829         subtype -= VSTRIMRIGHT;
6830 #if DEBUG
6831         if (subtype < 0 || subtype > 7)
6832                 abort();
6833 #endif
6834         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6835         zero = subtype >> 1;
6836         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6837         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6838
6839         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6840         if (loc) {
6841                 if (zero) {
6842                         memmove(startp, loc, str - loc);
6843                         loc = startp + (str - loc) - 1;
6844                 }
6845                 *loc = '\0';
6846                 amount = loc - expdest;
6847                 STADJUST(amount, expdest);
6848         }
6849         return loc;
6850 }
6851
6852 /*
6853  * Add the value of a specialized variable to the stack string.
6854  * name parameter (examples):
6855  * ash -c 'echo $1'      name:'1='
6856  * ash -c 'echo $qwe'    name:'qwe='
6857  * ash -c 'echo $$'      name:'$='
6858  * ash -c 'echo ${$}'    name:'$='
6859  * ash -c 'echo ${$##q}' name:'$=q'
6860  * ash -c 'echo ${#$}'   name:'$='
6861  * note: examples with bad shell syntax:
6862  * ash -c 'echo ${#$1}'  name:'$=1'
6863  * ash -c 'echo ${#1#}'  name:'1=#'
6864  */
6865 static NOINLINE ssize_t
6866 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6867 {
6868         const char *p;
6869         int num;
6870         int i;
6871         ssize_t len = 0;
6872         int sep;
6873         int quoted = *quotedp;
6874         int subtype = varflags & VSTYPE;
6875         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6876         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6877         int syntax;
6878
6879         sep = (flags & EXP_FULL) << CHAR_BIT;
6880         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6881
6882         switch (*name) {
6883         case '$':
6884                 num = rootpid;
6885                 goto numvar;
6886         case '?':
6887                 num = exitstatus;
6888                 goto numvar;
6889         case '#':
6890                 num = shellparam.nparam;
6891                 goto numvar;
6892         case '!':
6893                 num = backgndpid;
6894                 if (num == 0)
6895                         return -1;
6896  numvar:
6897                 len = cvtnum(num);
6898                 goto check_1char_name;
6899         case '-':
6900                 expdest = makestrspace(NOPTS, expdest);
6901                 for (i = NOPTS - 1; i >= 0; i--) {
6902                         if (optlist[i]) {
6903                                 USTPUTC(optletters(i), expdest);
6904                                 len++;
6905                         }
6906                 }
6907  check_1char_name:
6908 #if 0
6909                 /* handles cases similar to ${#$1} */
6910                 if (name[2] != '\0')
6911                         raise_error_syntax("bad substitution");
6912 #endif
6913                 break;
6914         case '@':
6915                 if (quoted && sep)
6916                         goto param;
6917                 /* fall through */
6918         case '*': {
6919                 char **ap;
6920                 char sepc;
6921
6922                 if (quoted)
6923                         sep = 0;
6924                 sep |= ifsset() ? ifsval()[0] : ' ';
6925  param:
6926                 sepc = sep;
6927                 *quotedp = !sepc;
6928                 ap = shellparam.p;
6929                 if (!ap)
6930                         return -1;
6931                 while ((p = *ap++) != NULL) {
6932                         len += strtodest(p, syntax, quotes);
6933
6934                         if (*ap && sep) {
6935                                 len++;
6936                                 memtodest(&sepc, 1, syntax, quotes);
6937                         }
6938                 }
6939                 break;
6940         } /* case '*' */
6941         case '0':
6942         case '1':
6943         case '2':
6944         case '3':
6945         case '4':
6946         case '5':
6947         case '6':
6948         case '7':
6949         case '8':
6950         case '9':
6951                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6952                 if (num < 0 || num > shellparam.nparam)
6953                         return -1;
6954                 p = num ? shellparam.p[num - 1] : arg0;
6955                 goto value;
6956         default:
6957                 /* NB: name has form "VAR=..." */
6958
6959                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6960                  * which should be considered before we check variables. */
6961                 if (var_str_list) {
6962                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6963                         p = NULL;
6964                         do {
6965                                 char *str, *eq;
6966                                 str = var_str_list->text;
6967                                 eq = strchr(str, '=');
6968                                 if (!eq) /* stop at first non-assignment */
6969                                         break;
6970                                 eq++;
6971                                 if (name_len == (unsigned)(eq - str)
6972                                  && strncmp(str, name, name_len) == 0
6973                                 ) {
6974                                         p = eq;
6975                                         /* goto value; - WRONG! */
6976                                         /* think "A=1 A=2 B=$A" */
6977                                 }
6978                                 var_str_list = var_str_list->next;
6979                         } while (var_str_list);
6980                         if (p)
6981                                 goto value;
6982                 }
6983                 p = lookupvar(name);
6984  value:
6985                 if (!p)
6986                         return -1;
6987
6988                 len = strtodest(p, syntax, quotes);
6989 #if ENABLE_UNICODE_SUPPORT
6990                 if (subtype == VSLENGTH && len > 0) {
6991                         reinit_unicode_for_ash();
6992                         if (unicode_status == UNICODE_ON) {
6993                                 STADJUST(-len, expdest);
6994                                 discard = 0;
6995                                 len = unicode_strlen(p);
6996                         }
6997                 }
6998 #endif
6999                 break;
7000         }
7001
7002         if (discard)
7003                 STADJUST(-len, expdest);
7004         return len;
7005 }
7006
7007 /*
7008  * Expand a variable, and return a pointer to the next character in the
7009  * input string.
7010  */
7011 static char *
7012 evalvar(char *p, int flag, struct strlist *var_str_list)
7013 {
7014         char varflags;
7015         char subtype;
7016         int quoted;
7017         char easy;
7018         char *var;
7019         int patloc;
7020         int startloc;
7021         ssize_t varlen;
7022
7023         varflags = (unsigned char) *p++;
7024         subtype = varflags & VSTYPE;
7025
7026         if (!subtype)
7027                 raise_error_syntax("bad substitution");
7028
7029         quoted = flag & EXP_QUOTED;
7030         var = p;
7031         easy = (!quoted || (*var == '@' && shellparam.nparam));
7032         startloc = expdest - (char *)stackblock();
7033         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7034
7035  again:
7036         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7037         if (varflags & VSNUL)
7038                 varlen--;
7039
7040         if (subtype == VSPLUS) {
7041                 varlen = -1 - varlen;
7042                 goto vsplus;
7043         }
7044
7045         if (subtype == VSMINUS) {
7046  vsplus:
7047                 if (varlen < 0) {
7048                         argstr(
7049                                 p,
7050                                 flag | EXP_TILDE | EXP_WORD,
7051                                 var_str_list
7052                         );
7053                         goto end;
7054                 }
7055                 goto record;
7056         }
7057
7058         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7059                 if (varlen >= 0)
7060                         goto record;
7061
7062                 subevalvar(p, var, 0, subtype, startloc, varflags,
7063                            flag & ~QUOTES_ESC, var_str_list);
7064                 varflags &= ~VSNUL;
7065                 /*
7066                  * Remove any recorded regions beyond
7067                  * start of variable
7068                  */
7069                 removerecordregions(startloc);
7070                 goto again;
7071         }
7072
7073         if (varlen < 0 && uflag)
7074                 varunset(p, var, 0, 0);
7075
7076         if (subtype == VSLENGTH) {
7077                 cvtnum(varlen > 0 ? varlen : 0);
7078                 goto record;
7079         }
7080
7081         if (subtype == VSNORMAL) {
7082  record:
7083                 if (!easy)
7084                         goto end;
7085                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7086                 goto end;
7087         }
7088
7089 #if DEBUG
7090         switch (subtype) {
7091         case VSTRIMLEFT:
7092         case VSTRIMLEFTMAX:
7093         case VSTRIMRIGHT:
7094         case VSTRIMRIGHTMAX:
7095 #if BASH_SUBSTR
7096         case VSSUBSTR:
7097 #endif
7098 #if BASH_PATTERN_SUBST
7099         case VSREPLACE:
7100         case VSREPLACEALL:
7101 #endif
7102                 break;
7103         default:
7104                 abort();
7105         }
7106 #endif
7107
7108         if (varlen >= 0) {
7109                 /*
7110                  * Terminate the string and start recording the pattern
7111                  * right after it
7112                  */
7113                 STPUTC('\0', expdest);
7114                 patloc = expdest - (char *)stackblock();
7115                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7116                                 startloc, varflags, flag, var_str_list)) {
7117                         int amount = expdest - (
7118                                 (char *)stackblock() + patloc - 1
7119                         );
7120                         STADJUST(-amount, expdest);
7121                 }
7122                 /* Remove any recorded regions beyond start of variable */
7123                 removerecordregions(startloc);
7124                 goto record;
7125         }
7126
7127  end:
7128         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7129                 int nesting = 1;
7130                 for (;;) {
7131                         unsigned char c = *p++;
7132                         if (c == CTLESC)
7133                                 p++;
7134                         else if (c == CTLBACKQ) {
7135                                 if (varlen >= 0)
7136                                         argbackq = argbackq->next;
7137                         } else if (c == CTLVAR) {
7138                                 if ((*p++ & VSTYPE) != VSNORMAL)
7139                                         nesting++;
7140                         } else if (c == CTLENDVAR) {
7141                                 if (--nesting == 0)
7142                                         break;
7143                         }
7144                 }
7145         }
7146         return p;
7147 }
7148
7149 /*
7150  * Add a file name to the list.
7151  */
7152 static void
7153 addfname(const char *name)
7154 {
7155         struct strlist *sp;
7156
7157         sp = stzalloc(sizeof(*sp));
7158         sp->text = sstrdup(name);
7159         *exparg.lastp = sp;
7160         exparg.lastp = &sp->next;
7161 }
7162
7163 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7164 static int
7165 hasmeta(const char *p)
7166 {
7167         static const char chars[] ALIGN1 = {
7168                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7169         };
7170
7171         for (;;) {
7172                 p = strpbrk(p, chars);
7173                 if (!p)
7174                         break;
7175                 switch ((unsigned char) *p) {
7176                 case CTLQUOTEMARK:
7177                         for (;;) {
7178                                 p++;
7179                                 if (*p == CTLQUOTEMARK)
7180                                         break;
7181                                 if (*p == CTLESC)
7182                                         p++;
7183                                 if (*p == '\0') /* huh? */
7184                                         return 0;
7185                         }
7186                         break;
7187                 case '\\':
7188                 case CTLESC:
7189                         p++;
7190                         if (*p == '\0')
7191                                 return 0;
7192                         break;
7193                 case '[':
7194                         if (!strchr(p + 1, ']')) {
7195                                 /* It's not a properly closed [] pattern,
7196                                  * but other metas may follow. Continue checking.
7197                                  * my[file* _is_ globbed by bash
7198                                  * and matches filenames like "my[file1".
7199                                  */
7200                                 break;
7201                         }
7202                         /* fallthrough */
7203                 default:
7204                 /* case '*': */
7205                 /* case '?': */
7206                         return 1;
7207                 }
7208                 p++;
7209         }
7210
7211         return 0;
7212 }
7213
7214 /* If we want to use glob() from libc... */
7215 #if !ENABLE_ASH_INTERNAL_GLOB
7216
7217 /* Add the result of glob() to the list */
7218 static void
7219 addglob(const glob_t *pglob)
7220 {
7221         char **p = pglob->gl_pathv;
7222
7223         do {
7224                 addfname(*p);
7225         } while (*++p);
7226 }
7227 static void
7228 expandmeta(struct strlist *str /*, int flag*/)
7229 {
7230         /* TODO - EXP_REDIR */
7231
7232         while (str) {
7233                 char *p;
7234                 glob_t pglob;
7235                 int i;
7236
7237                 if (fflag)
7238                         goto nometa;
7239
7240                 if (!hasmeta(str->text))
7241                         goto nometa;
7242
7243                 INT_OFF;
7244                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7245 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7246 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7247 //
7248 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7249 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7250 // Which means you need to unescape the string, right? Not so fast:
7251 // if there _is_ a file named "file\?" (with backslash), it is returned
7252 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7253 // You DONT KNOW by looking at the result whether you need to unescape it.
7254 //
7255 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7256 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7257 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7258 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7259 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7260 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7261                 i = glob(p, 0, NULL, &pglob);
7262                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7263                 if (p != str->text)
7264                         free(p);
7265                 switch (i) {
7266                 case 0:
7267 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7268                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7269                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7270                                 goto nometa2;
7271 #endif
7272                         addglob(&pglob);
7273                         globfree(&pglob);
7274                         INT_ON;
7275                         break;
7276                 case GLOB_NOMATCH:
7277  //nometa2:
7278                         globfree(&pglob);
7279                         INT_ON;
7280  nometa:
7281                         *exparg.lastp = str;
7282                         rmescapes(str->text, 0);
7283                         exparg.lastp = &str->next;
7284                         break;
7285                 default:        /* GLOB_NOSPACE */
7286                         globfree(&pglob);
7287                         INT_ON;
7288                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7289                 }
7290                 str = str->next;
7291         }
7292 }
7293
7294 #else
7295 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7296
7297 /*
7298  * Do metacharacter (i.e. *, ?, [...]) expansion.
7299  */
7300 static void
7301 expmeta(char *expdir, char *enddir, char *name)
7302 {
7303         char *p;
7304         const char *cp;
7305         char *start;
7306         char *endname;
7307         int metaflag;
7308         struct stat statb;
7309         DIR *dirp;
7310         struct dirent *dp;
7311         int atend;
7312         int matchdot;
7313         int esc;
7314
7315         metaflag = 0;
7316         start = name;
7317         for (p = name; esc = 0, *p; p += esc + 1) {
7318                 if (*p == '*' || *p == '?')
7319                         metaflag = 1;
7320                 else if (*p == '[') {
7321                         char *q = p + 1;
7322                         if (*q == '!')
7323                                 q++;
7324                         for (;;) {
7325                                 if (*q == '\\')
7326                                         q++;
7327                                 if (*q == '/' || *q == '\0')
7328                                         break;
7329                                 if (*++q == ']') {
7330                                         metaflag = 1;
7331                                         break;
7332                                 }
7333                         }
7334                 } else {
7335                         if (*p == '\\')
7336                                 esc++;
7337                         if (p[esc] == '/') {
7338                                 if (metaflag)
7339                                         break;
7340                                 start = p + esc + 1;
7341                         }
7342                 }
7343         }
7344         if (metaflag == 0) {    /* we've reached the end of the file name */
7345                 if (enddir != expdir)
7346                         metaflag++;
7347                 p = name;
7348                 do {
7349                         if (*p == '\\')
7350                                 p++;
7351                         *enddir++ = *p;
7352                 } while (*p++);
7353                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7354                         addfname(expdir);
7355                 return;
7356         }
7357         endname = p;
7358         if (name < start) {
7359                 p = name;
7360                 do {
7361                         if (*p == '\\')
7362                                 p++;
7363                         *enddir++ = *p++;
7364                 } while (p < start);
7365         }
7366         if (enddir == expdir) {
7367                 cp = ".";
7368         } else if (enddir == expdir + 1 && *expdir == '/') {
7369                 cp = "/";
7370         } else {
7371                 cp = expdir;
7372                 enddir[-1] = '\0';
7373         }
7374         dirp = opendir(cp);
7375         if (dirp == NULL)
7376                 return;
7377         if (enddir != expdir)
7378                 enddir[-1] = '/';
7379         if (*endname == 0) {
7380                 atend = 1;
7381         } else {
7382                 atend = 0;
7383                 *endname = '\0';
7384                 endname += esc + 1;
7385         }
7386         matchdot = 0;
7387         p = start;
7388         if (*p == '\\')
7389                 p++;
7390         if (*p == '.')
7391                 matchdot++;
7392         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7393                 if (dp->d_name[0] == '.' && !matchdot)
7394                         continue;
7395                 if (pmatch(start, dp->d_name)) {
7396                         if (atend) {
7397                                 strcpy(enddir, dp->d_name);
7398                                 addfname(expdir);
7399                         } else {
7400                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7401                                         continue;
7402                                 p[-1] = '/';
7403                                 expmeta(expdir, p, endname);
7404                         }
7405                 }
7406         }
7407         closedir(dirp);
7408         if (!atend)
7409                 endname[-esc - 1] = esc ? '\\' : '/';
7410 }
7411
7412 static struct strlist *
7413 msort(struct strlist *list, int len)
7414 {
7415         struct strlist *p, *q = NULL;
7416         struct strlist **lpp;
7417         int half;
7418         int n;
7419
7420         if (len <= 1)
7421                 return list;
7422         half = len >> 1;
7423         p = list;
7424         for (n = half; --n >= 0;) {
7425                 q = p;
7426                 p = p->next;
7427         }
7428         q->next = NULL;                 /* terminate first half of list */
7429         q = msort(list, half);          /* sort first half of list */
7430         p = msort(p, len - half);               /* sort second half */
7431         lpp = &list;
7432         for (;;) {
7433 #if ENABLE_LOCALE_SUPPORT
7434                 if (strcoll(p->text, q->text) < 0)
7435 #else
7436                 if (strcmp(p->text, q->text) < 0)
7437 #endif
7438                                                 {
7439                         *lpp = p;
7440                         lpp = &p->next;
7441                         p = *lpp;
7442                         if (p == NULL) {
7443                                 *lpp = q;
7444                                 break;
7445                         }
7446                 } else {
7447                         *lpp = q;
7448                         lpp = &q->next;
7449                         q = *lpp;
7450                         if (q == NULL) {
7451                                 *lpp = p;
7452                                 break;
7453                         }
7454                 }
7455         }
7456         return list;
7457 }
7458
7459 /*
7460  * Sort the results of file name expansion.  It calculates the number of
7461  * strings to sort and then calls msort (short for merge sort) to do the
7462  * work.
7463  */
7464 static struct strlist *
7465 expsort(struct strlist *str)
7466 {
7467         int len;
7468         struct strlist *sp;
7469
7470         len = 0;
7471         for (sp = str; sp; sp = sp->next)
7472                 len++;
7473         return msort(str, len);
7474 }
7475
7476 static void
7477 expandmeta(struct strlist *str /*, int flag*/)
7478 {
7479         /* TODO - EXP_REDIR */
7480
7481         while (str) {
7482                 char *expdir;
7483                 struct strlist **savelastp;
7484                 struct strlist *sp;
7485                 char *p;
7486
7487                 if (fflag)
7488                         goto nometa;
7489                 if (!hasmeta(str->text))
7490                         goto nometa;
7491                 savelastp = exparg.lastp;
7492
7493                 INT_OFF;
7494                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7495                 {
7496                         int i = strlen(str->text);
7497 //BUGGY estimation of how long expanded name can be
7498                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7499                 }
7500                 expmeta(expdir, expdir, p);
7501                 free(expdir);
7502                 if (p != str->text)
7503                         free(p);
7504                 INT_ON;
7505                 if (exparg.lastp == savelastp) {
7506                         /*
7507                          * no matches
7508                          */
7509  nometa:
7510                         *exparg.lastp = str;
7511                         rmescapes(str->text, 0);
7512                         exparg.lastp = &str->next;
7513                 } else {
7514                         *exparg.lastp = NULL;
7515                         *savelastp = sp = expsort(*savelastp);
7516                         while (sp->next != NULL)
7517                                 sp = sp->next;
7518                         exparg.lastp = &sp->next;
7519                 }
7520                 str = str->next;
7521         }
7522 }
7523 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7524
7525 /*
7526  * Perform variable substitution and command substitution on an argument,
7527  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7528  * perform splitting and file name expansion.  When arglist is NULL, perform
7529  * here document expansion.
7530  */
7531 static void
7532 expandarg(union node *arg, struct arglist *arglist, int flag)
7533 {
7534         struct strlist *sp;
7535         char *p;
7536
7537         argbackq = arg->narg.backquote;
7538         STARTSTACKSTR(expdest);
7539         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7540         argstr(arg->narg.text, flag,
7541                         /* var_str_list: */ arglist ? arglist->list : NULL);
7542         p = _STPUTC('\0', expdest);
7543         expdest = p - 1;
7544         if (arglist == NULL) {
7545                 /* here document expanded */
7546                 goto out;
7547         }
7548         p = grabstackstr(p);
7549         TRACE(("expandarg: p:'%s'\n", p));
7550         exparg.lastp = &exparg.list;
7551         /*
7552          * TODO - EXP_REDIR
7553          */
7554         if (flag & EXP_FULL) {
7555                 ifsbreakup(p, &exparg);
7556                 *exparg.lastp = NULL;
7557                 exparg.lastp = &exparg.list;
7558                 expandmeta(exparg.list /*, flag*/);
7559         } else {
7560                 if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
7561                         rmescapes(p, 0);
7562                         TRACE(("expandarg: rmescapes:'%s'\n", p));
7563                 }
7564                 sp = stzalloc(sizeof(*sp));
7565                 sp->text = p;
7566                 *exparg.lastp = sp;
7567                 exparg.lastp = &sp->next;
7568         }
7569         *exparg.lastp = NULL;
7570         if (exparg.list) {
7571                 *arglist->lastp = exparg.list;
7572                 arglist->lastp = exparg.lastp;
7573         }
7574
7575  out:
7576         ifsfree();
7577 }
7578
7579 /*
7580  * Expand shell variables and backquotes inside a here document.
7581  */
7582 static void
7583 expandhere(union node *arg, int fd)
7584 {
7585         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7586         full_write(fd, stackblock(), expdest - (char *)stackblock());
7587 }
7588
7589 /*
7590  * Returns true if the pattern matches the string.
7591  */
7592 static int
7593 patmatch(char *pattern, const char *string)
7594 {
7595         return pmatch(preglob(pattern, 0), string);
7596 }
7597
7598 /*
7599  * See if a pattern matches in a case statement.
7600  */
7601 static int
7602 casematch(union node *pattern, char *val)
7603 {
7604         struct stackmark smark;
7605         int result;
7606
7607         setstackmark(&smark);
7608         argbackq = pattern->narg.backquote;
7609         STARTSTACKSTR(expdest);
7610         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7611                         /* var_str_list: */ NULL);
7612         STACKSTRNUL(expdest);
7613         ifsfree();
7614         result = patmatch(stackblock(), val);
7615         popstackmark(&smark);
7616         return result;
7617 }
7618
7619
7620 /* ============ find_command */
7621
7622 struct builtincmd {
7623         const char *name;
7624         int (*builtin)(int, char **) FAST_FUNC;
7625         /* unsigned flags; */
7626 };
7627 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7628 /* "regular" builtins always take precedence over commands,
7629  * regardless of PATH=....%builtin... position */
7630 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7631 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7632
7633 struct cmdentry {
7634         smallint cmdtype;       /* CMDxxx */
7635         union param {
7636                 int index;
7637                 /* index >= 0 for commands without path (slashes) */
7638                 /* (TODO: what exactly does the value mean? PATH position?) */
7639                 /* index == -1 for commands with slashes */
7640                 /* index == (-2 - applet_no) for NOFORK applets */
7641                 const struct builtincmd *cmd;
7642                 struct funcnode *func;
7643         } u;
7644 };
7645 /* values of cmdtype */
7646 #define CMDUNKNOWN      -1      /* no entry in table for command */
7647 #define CMDNORMAL       0       /* command is an executable program */
7648 #define CMDFUNCTION     1       /* command is a shell function */
7649 #define CMDBUILTIN      2       /* command is a shell builtin */
7650
7651 /* action to find_command() */
7652 #define DO_ERR          0x01    /* prints errors */
7653 #define DO_ABS          0x02    /* checks absolute paths */
7654 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7655 #define DO_ALTPATH      0x08    /* using alternate path */
7656 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7657
7658 static void find_command(char *, struct cmdentry *, int, const char *);
7659
7660
7661 /* ============ Hashing commands */
7662
7663 /*
7664  * When commands are first encountered, they are entered in a hash table.
7665  * This ensures that a full path search will not have to be done for them
7666  * on each invocation.
7667  *
7668  * We should investigate converting to a linear search, even though that
7669  * would make the command name "hash" a misnomer.
7670  */
7671
7672 struct tblentry {
7673         struct tblentry *next;  /* next entry in hash chain */
7674         union param param;      /* definition of builtin function */
7675         smallint cmdtype;       /* CMDxxx */
7676         char rehash;            /* if set, cd done since entry created */
7677         char cmdname[1];        /* name of command */
7678 };
7679
7680 static struct tblentry **cmdtable;
7681 #define INIT_G_cmdtable() do { \
7682         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7683 } while (0)
7684
7685 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7686
7687
7688 static void
7689 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7690 {
7691 #if ENABLE_FEATURE_SH_STANDALONE
7692         if (applet_no >= 0) {
7693                 if (APPLET_IS_NOEXEC(applet_no)) {
7694                         clearenv();
7695                         while (*envp)
7696                                 putenv(*envp++);
7697                         run_applet_no_and_exit(applet_no, argv);
7698                 }
7699                 /* re-exec ourselves with the new arguments */
7700                 execve(bb_busybox_exec_path, argv, envp);
7701                 /* If they called chroot or otherwise made the binary no longer
7702                  * executable, fall through */
7703         }
7704 #endif
7705
7706  repeat:
7707 #ifdef SYSV
7708         do {
7709                 execve(cmd, argv, envp);
7710         } while (errno == EINTR);
7711 #else
7712         execve(cmd, argv, envp);
7713 #endif
7714         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7715                 /* Run "cmd" as a shell script:
7716                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7717                  * "If the execve() function fails with ENOEXEC, the shell
7718                  * shall execute a command equivalent to having a shell invoked
7719                  * with the command name as its first operand,
7720                  * with any remaining arguments passed to the new shell"
7721                  *
7722                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7723                  * just call ourselves.
7724                  *
7725                  * Note that bash reads ~80 chars of the file, and if it sees
7726                  * a zero byte before it sees newline, it doesn't try to
7727                  * interpret it, but fails with "cannot execute binary file"
7728                  * message and exit code 126. For one, this prevents attempts
7729                  * to interpret foreign ELF binaries as shell scripts.
7730                  */
7731                 argv[0] = cmd;
7732                 cmd = (char*) bb_busybox_exec_path;
7733                 /* NB: this is only possible because all callers of shellexec()
7734                  * ensure that the argv[-1] slot exists!
7735                  */
7736                 argv--;
7737                 argv[0] = (char*) "ash";
7738                 goto repeat;
7739         }
7740 }
7741
7742 /*
7743  * Exec a program.  Never returns.  If you change this routine, you may
7744  * have to change the find_command routine as well.
7745  * argv[-1] must exist and be writable! See tryexec() for why.
7746  */
7747 static void shellexec(char **, const char *, int) NORETURN;
7748 static void
7749 shellexec(char **argv, const char *path, int idx)
7750 {
7751         char *cmdname;
7752         int e;
7753         char **envp;
7754         int exerrno;
7755         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7756
7757         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7758         if (strchr(argv[0], '/') != NULL
7759 #if ENABLE_FEATURE_SH_STANDALONE
7760          || (applet_no = find_applet_by_name(argv[0])) >= 0
7761 #endif
7762         ) {
7763                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7764                 if (applet_no >= 0) {
7765                         /* We tried execing ourself, but it didn't work.
7766                          * Maybe /proc/self/exe doesn't exist?
7767                          * Try $PATH search.
7768                          */
7769                         goto try_PATH;
7770                 }
7771                 e = errno;
7772         } else {
7773  try_PATH:
7774                 e = ENOENT;
7775                 while ((cmdname = path_advance(&path, argv[0])) != NULL) {
7776                         if (--idx < 0 && pathopt == NULL) {
7777                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7778                                 if (errno != ENOENT && errno != ENOTDIR)
7779                                         e = errno;
7780                         }
7781                         stunalloc(cmdname);
7782                 }
7783         }
7784
7785         /* Map to POSIX errors */
7786         switch (e) {
7787         case EACCES:
7788                 exerrno = 126;
7789                 break;
7790         case ENOENT:
7791                 exerrno = 127;
7792                 break;
7793         default:
7794                 exerrno = 2;
7795                 break;
7796         }
7797         exitstatus = exerrno;
7798         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7799                 argv[0], e, suppress_int));
7800         ash_msg_and_raise(EXEXIT, "%s: %s", argv[0], errmsg(e, "not found"));
7801         /* NOTREACHED */
7802 }
7803
7804 static void
7805 printentry(struct tblentry *cmdp)
7806 {
7807         int idx;
7808         const char *path;
7809         char *name;
7810
7811         idx = cmdp->param.index;
7812         path = pathval();
7813         do {
7814                 name = path_advance(&path, cmdp->cmdname);
7815                 stunalloc(name);
7816         } while (--idx >= 0);
7817         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7818 }
7819
7820 /*
7821  * Clear out command entries.  The argument specifies the first entry in
7822  * PATH which has changed.
7823  */
7824 static void
7825 clearcmdentry(int firstchange)
7826 {
7827         struct tblentry **tblp;
7828         struct tblentry **pp;
7829         struct tblentry *cmdp;
7830
7831         INT_OFF;
7832         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7833                 pp = tblp;
7834                 while ((cmdp = *pp) != NULL) {
7835                         if ((cmdp->cmdtype == CMDNORMAL &&
7836                              cmdp->param.index >= firstchange)
7837                          || (cmdp->cmdtype == CMDBUILTIN &&
7838                              builtinloc >= firstchange)
7839                         ) {
7840                                 *pp = cmdp->next;
7841                                 free(cmdp);
7842                         } else {
7843                                 pp = &cmdp->next;
7844                         }
7845                 }
7846         }
7847         INT_ON;
7848 }
7849
7850 /*
7851  * Locate a command in the command hash table.  If "add" is nonzero,
7852  * add the command to the table if it is not already present.  The
7853  * variable "lastcmdentry" is set to point to the address of the link
7854  * pointing to the entry, so that delete_cmd_entry can delete the
7855  * entry.
7856  *
7857  * Interrupts must be off if called with add != 0.
7858  */
7859 static struct tblentry **lastcmdentry;
7860
7861 static struct tblentry *
7862 cmdlookup(const char *name, int add)
7863 {
7864         unsigned int hashval;
7865         const char *p;
7866         struct tblentry *cmdp;
7867         struct tblentry **pp;
7868
7869         p = name;
7870         hashval = (unsigned char)*p << 4;
7871         while (*p)
7872                 hashval += (unsigned char)*p++;
7873         hashval &= 0x7FFF;
7874         pp = &cmdtable[hashval % CMDTABLESIZE];
7875         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7876                 if (strcmp(cmdp->cmdname, name) == 0)
7877                         break;
7878                 pp = &cmdp->next;
7879         }
7880         if (add && cmdp == NULL) {
7881                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7882                                 + strlen(name)
7883                                 /* + 1 - already done because
7884                                  * tblentry::cmdname is char[1] */);
7885                 /*cmdp->next = NULL; - ckzalloc did it */
7886                 cmdp->cmdtype = CMDUNKNOWN;
7887                 strcpy(cmdp->cmdname, name);
7888         }
7889         lastcmdentry = pp;
7890         return cmdp;
7891 }
7892
7893 /*
7894  * Delete the command entry returned on the last lookup.
7895  */
7896 static void
7897 delete_cmd_entry(void)
7898 {
7899         struct tblentry *cmdp;
7900
7901         INT_OFF;
7902         cmdp = *lastcmdentry;
7903         *lastcmdentry = cmdp->next;
7904         if (cmdp->cmdtype == CMDFUNCTION)
7905                 freefunc(cmdp->param.func);
7906         free(cmdp);
7907         INT_ON;
7908 }
7909
7910 /*
7911  * Add a new command entry, replacing any existing command entry for
7912  * the same name - except special builtins.
7913  */
7914 static void
7915 addcmdentry(char *name, struct cmdentry *entry)
7916 {
7917         struct tblentry *cmdp;
7918
7919         cmdp = cmdlookup(name, 1);
7920         if (cmdp->cmdtype == CMDFUNCTION) {
7921                 freefunc(cmdp->param.func);
7922         }
7923         cmdp->cmdtype = entry->cmdtype;
7924         cmdp->param = entry->u;
7925         cmdp->rehash = 0;
7926 }
7927
7928 static int FAST_FUNC
7929 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7930 {
7931         struct tblentry **pp;
7932         struct tblentry *cmdp;
7933         int c;
7934         struct cmdentry entry;
7935         char *name;
7936
7937         if (nextopt("r") != '\0') {
7938                 clearcmdentry(0);
7939                 return 0;
7940         }
7941
7942         if (*argptr == NULL) {
7943                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7944                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7945                                 if (cmdp->cmdtype == CMDNORMAL)
7946                                         printentry(cmdp);
7947                         }
7948                 }
7949                 return 0;
7950         }
7951
7952         c = 0;
7953         while ((name = *argptr) != NULL) {
7954                 cmdp = cmdlookup(name, 0);
7955                 if (cmdp != NULL
7956                  && (cmdp->cmdtype == CMDNORMAL
7957                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7958                 ) {
7959                         delete_cmd_entry();
7960                 }
7961                 find_command(name, &entry, DO_ERR, pathval());
7962                 if (entry.cmdtype == CMDUNKNOWN)
7963                         c = 1;
7964                 argptr++;
7965         }
7966         return c;
7967 }
7968
7969 /*
7970  * Called when a cd is done.  Marks all commands so the next time they
7971  * are executed they will be rehashed.
7972  */
7973 static void
7974 hashcd(void)
7975 {
7976         struct tblentry **pp;
7977         struct tblentry *cmdp;
7978
7979         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7980                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7981                         if (cmdp->cmdtype == CMDNORMAL
7982                          || (cmdp->cmdtype == CMDBUILTIN
7983                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7984                              && builtinloc > 0)
7985                         ) {
7986                                 cmdp->rehash = 1;
7987                         }
7988                 }
7989         }
7990 }
7991
7992 /*
7993  * Fix command hash table when PATH changed.
7994  * Called before PATH is changed.  The argument is the new value of PATH;
7995  * pathval() still returns the old value at this point.
7996  * Called with interrupts off.
7997  */
7998 static void FAST_FUNC
7999 changepath(const char *new)
8000 {
8001         const char *old;
8002         int firstchange;
8003         int idx;
8004         int idx_bltin;
8005
8006         old = pathval();
8007         firstchange = 9999;     /* assume no change */
8008         idx = 0;
8009         idx_bltin = -1;
8010         for (;;) {
8011                 if (*old != *new) {
8012                         firstchange = idx;
8013                         if ((*old == '\0' && *new == ':')
8014                          || (*old == ':' && *new == '\0')
8015                         ) {
8016                                 firstchange++;
8017                         }
8018                         old = new;      /* ignore subsequent differences */
8019                 }
8020                 if (*new == '\0')
8021                         break;
8022                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8023                         idx_bltin = idx;
8024                 if (*new == ':')
8025                         idx++;
8026                 new++;
8027                 old++;
8028         }
8029         if (builtinloc < 0 && idx_bltin >= 0)
8030                 builtinloc = idx_bltin;             /* zap builtins */
8031         if (builtinloc >= 0 && idx_bltin < 0)
8032                 firstchange = 0;
8033         clearcmdentry(firstchange);
8034         builtinloc = idx_bltin;
8035 }
8036 enum {
8037         TEOF,
8038         TNL,
8039         TREDIR,
8040         TWORD,
8041         TSEMI,
8042         TBACKGND,
8043         TAND,
8044         TOR,
8045         TPIPE,
8046         TLP,
8047         TRP,
8048         TENDCASE,
8049         TENDBQUOTE,
8050         TNOT,
8051         TCASE,
8052         TDO,
8053         TDONE,
8054         TELIF,
8055         TELSE,
8056         TESAC,
8057         TFI,
8058         TFOR,
8059 #if BASH_FUNCTION
8060         TFUNCTION,
8061 #endif
8062         TIF,
8063         TIN,
8064         TTHEN,
8065         TUNTIL,
8066         TWHILE,
8067         TBEGIN,
8068         TEND
8069 };
8070 typedef smallint token_id_t;
8071
8072 /* Nth bit indicates if token marks the end of a list */
8073 enum {
8074         tokendlist = 0
8075         /*  0 */ | (1u << TEOF)
8076         /*  1 */ | (0u << TNL)
8077         /*  2 */ | (0u << TREDIR)
8078         /*  3 */ | (0u << TWORD)
8079         /*  4 */ | (0u << TSEMI)
8080         /*  5 */ | (0u << TBACKGND)
8081         /*  6 */ | (0u << TAND)
8082         /*  7 */ | (0u << TOR)
8083         /*  8 */ | (0u << TPIPE)
8084         /*  9 */ | (0u << TLP)
8085         /* 10 */ | (1u << TRP)
8086         /* 11 */ | (1u << TENDCASE)
8087         /* 12 */ | (1u << TENDBQUOTE)
8088         /* 13 */ | (0u << TNOT)
8089         /* 14 */ | (0u << TCASE)
8090         /* 15 */ | (1u << TDO)
8091         /* 16 */ | (1u << TDONE)
8092         /* 17 */ | (1u << TELIF)
8093         /* 18 */ | (1u << TELSE)
8094         /* 19 */ | (1u << TESAC)
8095         /* 20 */ | (1u << TFI)
8096         /* 21 */ | (0u << TFOR)
8097 #if BASH_FUNCTION
8098         /* 22 */ | (0u << TFUNCTION)
8099 #endif
8100         /* 23 */ | (0u << TIF)
8101         /* 24 */ | (0u << TIN)
8102         /* 25 */ | (1u << TTHEN)
8103         /* 26 */ | (0u << TUNTIL)
8104         /* 27 */ | (0u << TWHILE)
8105         /* 28 */ | (0u << TBEGIN)
8106         /* 29 */ | (1u << TEND)
8107         , /* thus far 29 bits used */
8108 };
8109
8110 static const char *const tokname_array[] = {
8111         "end of file",
8112         "newline",
8113         "redirection",
8114         "word",
8115         ";",
8116         "&",
8117         "&&",
8118         "||",
8119         "|",
8120         "(",
8121         ")",
8122         ";;",
8123         "`",
8124 #define KWDOFFSET 13
8125         /* the following are keywords */
8126         "!",
8127         "case",
8128         "do",
8129         "done",
8130         "elif",
8131         "else",
8132         "esac",
8133         "fi",
8134         "for",
8135 #if BASH_FUNCTION
8136         "function",
8137 #endif
8138         "if",
8139         "in",
8140         "then",
8141         "until",
8142         "while",
8143         "{",
8144         "}",
8145 };
8146
8147 /* Wrapper around strcmp for qsort/bsearch/... */
8148 static int
8149 pstrcmp(const void *a, const void *b)
8150 {
8151         return strcmp((char*)a, *(char**)b);
8152 }
8153
8154 static const char *const *
8155 findkwd(const char *s)
8156 {
8157         return bsearch(s, tokname_array + KWDOFFSET,
8158                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8159                         sizeof(tokname_array[0]), pstrcmp);
8160 }
8161
8162 /*
8163  * Locate and print what a word is...
8164  */
8165 static int
8166 describe_command(char *command, const char *path, int describe_command_verbose)
8167 {
8168         struct cmdentry entry;
8169         struct tblentry *cmdp;
8170 #if ENABLE_ASH_ALIAS
8171         const struct alias *ap;
8172 #endif
8173
8174         path = path ? path : pathval();
8175
8176         if (describe_command_verbose) {
8177                 out1str(command);
8178         }
8179
8180         /* First look at the keywords */
8181         if (findkwd(command)) {
8182                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8183                 goto out;
8184         }
8185
8186 #if ENABLE_ASH_ALIAS
8187         /* Then look at the aliases */
8188         ap = lookupalias(command, 0);
8189         if (ap != NULL) {
8190                 if (!describe_command_verbose) {
8191                         out1str("alias ");
8192                         printalias(ap);
8193                         return 0;
8194                 }
8195                 out1fmt(" is an alias for %s", ap->val);
8196                 goto out;
8197         }
8198 #endif
8199         /* Then check if it is a tracked alias */
8200         cmdp = cmdlookup(command, 0);
8201         if (cmdp != NULL) {
8202                 entry.cmdtype = cmdp->cmdtype;
8203                 entry.u = cmdp->param;
8204         } else {
8205                 /* Finally use brute force */
8206                 find_command(command, &entry, DO_ABS, path);
8207         }
8208
8209         switch (entry.cmdtype) {
8210         case CMDNORMAL: {
8211                 int j = entry.u.index;
8212                 char *p;
8213                 if (j < 0) {
8214                         p = command;
8215                 } else {
8216                         do {
8217                                 p = path_advance(&path, command);
8218                                 stunalloc(p);
8219                         } while (--j >= 0);
8220                 }
8221                 if (describe_command_verbose) {
8222                         out1fmt(" is%s %s",
8223                                 (cmdp ? " a tracked alias for" : nullstr), p
8224                         );
8225                 } else {
8226                         out1str(p);
8227                 }
8228                 break;
8229         }
8230
8231         case CMDFUNCTION:
8232                 if (describe_command_verbose) {
8233                         out1str(" is a shell function");
8234                 } else {
8235                         out1str(command);
8236                 }
8237                 break;
8238
8239         case CMDBUILTIN:
8240                 if (describe_command_verbose) {
8241                         out1fmt(" is a %sshell builtin",
8242                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8243                                         "special " : nullstr
8244                         );
8245                 } else {
8246                         out1str(command);
8247                 }
8248                 break;
8249
8250         default:
8251                 if (describe_command_verbose) {
8252                         out1str(": not found\n");
8253                 }
8254                 return 127;
8255         }
8256  out:
8257         out1str("\n");
8258         return 0;
8259 }
8260
8261 static int FAST_FUNC
8262 typecmd(int argc UNUSED_PARAM, char **argv)
8263 {
8264         int i = 1;
8265         int err = 0;
8266         int verbose = 1;
8267
8268         /* type -p ... ? (we don't bother checking for 'p') */
8269         if (argv[1] && argv[1][0] == '-') {
8270                 i++;
8271                 verbose = 0;
8272         }
8273         while (argv[i]) {
8274                 err |= describe_command(argv[i++], NULL, verbose);
8275         }
8276         return err;
8277 }
8278
8279 #if ENABLE_ASH_CMDCMD
8280 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8281 static char **
8282 parse_command_args(char **argv, const char **path)
8283 {
8284         char *cp, c;
8285
8286         for (;;) {
8287                 cp = *++argv;
8288                 if (!cp)
8289                         return NULL;
8290                 if (*cp++ != '-')
8291                         break;
8292                 c = *cp++;
8293                 if (!c)
8294                         break;
8295                 if (c == '-' && !*cp) {
8296                         if (!*++argv)
8297                                 return NULL;
8298                         break;
8299                 }
8300                 do {
8301                         switch (c) {
8302                         case 'p':
8303                                 *path = bb_default_path;
8304                                 break;
8305                         default:
8306                                 /* run 'typecmd' for other options */
8307                                 return NULL;
8308                         }
8309                         c = *cp++;
8310                 } while (c);
8311         }
8312         return argv;
8313 }
8314
8315 static int FAST_FUNC
8316 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8317 {
8318         char *cmd;
8319         int c;
8320         enum {
8321                 VERIFY_BRIEF = 1,
8322                 VERIFY_VERBOSE = 2,
8323         } verify = 0;
8324         const char *path = NULL;
8325
8326         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8327          * never reaches this function.
8328          */
8329
8330         while ((c = nextopt("pvV")) != '\0')
8331                 if (c == 'V')
8332                         verify |= VERIFY_VERBOSE;
8333                 else if (c == 'v')
8334                         /*verify |= VERIFY_BRIEF*/;
8335 #if DEBUG
8336                 else if (c != 'p')
8337                         abort();
8338 #endif
8339                 else
8340                         path = bb_default_path;
8341
8342         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8343         cmd = *argptr;
8344         if (/*verify && */ cmd)
8345                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8346
8347         return 0;
8348 }
8349 #endif
8350
8351
8352 /*static int funcblocksize;     // size of structures in function */
8353 /*static int funcstringsize;    // size of strings in node */
8354 static void *funcblock;         /* block to allocate function from */
8355 static char *funcstring_end;    /* end of block to allocate strings from */
8356
8357 /* flags in argument to evaltree */
8358 #define EV_EXIT    01           /* exit after evaluating tree */
8359 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8360
8361 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8362         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8363         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8364         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8365         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8366         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8367         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8368         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8369         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8370         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8371         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8372         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8373         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8374         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8375         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8376         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8377         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8378         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8379 #if BASH_REDIR_OUTPUT
8380         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8381 #endif
8382         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8383         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8384         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8385         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8386         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8387         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8388         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8389         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8390         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8391 };
8392
8393 static int calcsize(int funcblocksize, union node *n);
8394
8395 static int
8396 sizenodelist(int funcblocksize, struct nodelist *lp)
8397 {
8398         while (lp) {
8399                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8400                 funcblocksize = calcsize(funcblocksize, lp->n);
8401                 lp = lp->next;
8402         }
8403         return funcblocksize;
8404 }
8405
8406 static int
8407 calcsize(int funcblocksize, union node *n)
8408 {
8409         if (n == NULL)
8410                 return funcblocksize;
8411         funcblocksize += nodesize[n->type];
8412         switch (n->type) {
8413         case NCMD:
8414                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8415                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8416                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8417                 break;
8418         case NPIPE:
8419                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8420                 break;
8421         case NREDIR:
8422         case NBACKGND:
8423         case NSUBSHELL:
8424                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8425                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8426                 break;
8427         case NAND:
8428         case NOR:
8429         case NSEMI:
8430         case NWHILE:
8431         case NUNTIL:
8432                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8433                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8434                 break;
8435         case NIF:
8436                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8437                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8438                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8439                 break;
8440         case NFOR:
8441                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8442                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8443                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8444                 break;
8445         case NCASE:
8446                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8447                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8448                 break;
8449         case NCLIST:
8450                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8451                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8452                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8453                 break;
8454         case NDEFUN:
8455         case NARG:
8456                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8457                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8458                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8459                 break;
8460         case NTO:
8461 #if BASH_REDIR_OUTPUT
8462         case NTO2:
8463 #endif
8464         case NCLOBBER:
8465         case NFROM:
8466         case NFROMTO:
8467         case NAPPEND:
8468                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8469                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8470                 break;
8471         case NTOFD:
8472         case NFROMFD:
8473                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8474                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8475         break;
8476         case NHERE:
8477         case NXHERE:
8478                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8479                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8480                 break;
8481         case NNOT:
8482                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8483                 break;
8484         };
8485         return funcblocksize;
8486 }
8487
8488 static char *
8489 nodeckstrdup(char *s)
8490 {
8491         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8492         return strcpy(funcstring_end, s);
8493 }
8494
8495 static union node *copynode(union node *);
8496
8497 static struct nodelist *
8498 copynodelist(struct nodelist *lp)
8499 {
8500         struct nodelist *start;
8501         struct nodelist **lpp;
8502
8503         lpp = &start;
8504         while (lp) {
8505                 *lpp = funcblock;
8506                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8507                 (*lpp)->n = copynode(lp->n);
8508                 lp = lp->next;
8509                 lpp = &(*lpp)->next;
8510         }
8511         *lpp = NULL;
8512         return start;
8513 }
8514
8515 static union node *
8516 copynode(union node *n)
8517 {
8518         union node *new;
8519
8520         if (n == NULL)
8521                 return NULL;
8522         new = funcblock;
8523         funcblock = (char *) funcblock + nodesize[n->type];
8524
8525         switch (n->type) {
8526         case NCMD:
8527                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8528                 new->ncmd.args = copynode(n->ncmd.args);
8529                 new->ncmd.assign = copynode(n->ncmd.assign);
8530                 break;
8531         case NPIPE:
8532                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8533                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8534                 break;
8535         case NREDIR:
8536         case NBACKGND:
8537         case NSUBSHELL:
8538                 new->nredir.redirect = copynode(n->nredir.redirect);
8539                 new->nredir.n = copynode(n->nredir.n);
8540                 break;
8541         case NAND:
8542         case NOR:
8543         case NSEMI:
8544         case NWHILE:
8545         case NUNTIL:
8546                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8547                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8548                 break;
8549         case NIF:
8550                 new->nif.elsepart = copynode(n->nif.elsepart);
8551                 new->nif.ifpart = copynode(n->nif.ifpart);
8552                 new->nif.test = copynode(n->nif.test);
8553                 break;
8554         case NFOR:
8555                 new->nfor.var = nodeckstrdup(n->nfor.var);
8556                 new->nfor.body = copynode(n->nfor.body);
8557                 new->nfor.args = copynode(n->nfor.args);
8558                 break;
8559         case NCASE:
8560                 new->ncase.cases = copynode(n->ncase.cases);
8561                 new->ncase.expr = copynode(n->ncase.expr);
8562                 break;
8563         case NCLIST:
8564                 new->nclist.body = copynode(n->nclist.body);
8565                 new->nclist.pattern = copynode(n->nclist.pattern);
8566                 new->nclist.next = copynode(n->nclist.next);
8567                 break;
8568         case NDEFUN:
8569         case NARG:
8570                 new->narg.backquote = copynodelist(n->narg.backquote);
8571                 new->narg.text = nodeckstrdup(n->narg.text);
8572                 new->narg.next = copynode(n->narg.next);
8573                 break;
8574         case NTO:
8575 #if BASH_REDIR_OUTPUT
8576         case NTO2:
8577 #endif
8578         case NCLOBBER:
8579         case NFROM:
8580         case NFROMTO:
8581         case NAPPEND:
8582                 new->nfile.fname = copynode(n->nfile.fname);
8583                 new->nfile.fd = n->nfile.fd;
8584                 new->nfile.next = copynode(n->nfile.next);
8585                 break;
8586         case NTOFD:
8587         case NFROMFD:
8588                 new->ndup.vname = copynode(n->ndup.vname);
8589                 new->ndup.dupfd = n->ndup.dupfd;
8590                 new->ndup.fd = n->ndup.fd;
8591                 new->ndup.next = copynode(n->ndup.next);
8592                 break;
8593         case NHERE:
8594         case NXHERE:
8595                 new->nhere.doc = copynode(n->nhere.doc);
8596                 new->nhere.fd = n->nhere.fd;
8597                 new->nhere.next = copynode(n->nhere.next);
8598                 break;
8599         case NNOT:
8600                 new->nnot.com = copynode(n->nnot.com);
8601                 break;
8602         };
8603         new->type = n->type;
8604         return new;
8605 }
8606
8607 /*
8608  * Make a copy of a parse tree.
8609  */
8610 static struct funcnode *
8611 copyfunc(union node *n)
8612 {
8613         struct funcnode *f;
8614         size_t blocksize;
8615
8616         /*funcstringsize = 0;*/
8617         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8618         f = ckzalloc(blocksize /* + funcstringsize */);
8619         funcblock = (char *) f + offsetof(struct funcnode, n);
8620         funcstring_end = (char *) f + blocksize;
8621         copynode(n);
8622         /* f->count = 0; - ckzalloc did it */
8623         return f;
8624 }
8625
8626 /*
8627  * Define a shell function.
8628  */
8629 static void
8630 defun(union node *func)
8631 {
8632         struct cmdentry entry;
8633
8634         INT_OFF;
8635         entry.cmdtype = CMDFUNCTION;
8636         entry.u.func = copyfunc(func);
8637         addcmdentry(func->narg.text, &entry);
8638         INT_ON;
8639 }
8640
8641 /* Reasons for skipping commands (see comment on breakcmd routine) */
8642 #define SKIPBREAK      (1 << 0)
8643 #define SKIPCONT       (1 << 1)
8644 #define SKIPFUNC       (1 << 2)
8645 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8646 static int skipcount;           /* number of levels to skip */
8647 static int funcnest;            /* depth of function calls */
8648 static int loopnest;            /* current loop nesting level */
8649
8650 /* Forward decl way out to parsing code - dotrap needs it */
8651 static int evalstring(char *s, int flags);
8652
8653 /* Called to execute a trap.
8654  * Single callsite - at the end of evaltree().
8655  * If we return non-zero, evaltree raises EXEXIT exception.
8656  *
8657  * Perhaps we should avoid entering new trap handlers
8658  * while we are executing a trap handler. [is it a TODO?]
8659  */
8660 static void
8661 dotrap(void)
8662 {
8663         uint8_t *g;
8664         int sig;
8665         uint8_t last_status;
8666
8667         if (!pending_sig)
8668                 return;
8669
8670         last_status = exitstatus;
8671         pending_sig = 0;
8672         barrier();
8673
8674         TRACE(("dotrap entered\n"));
8675         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8676                 char *p;
8677
8678                 if (!*g)
8679                         continue;
8680
8681                 if (evalskip) {
8682                         pending_sig = sig;
8683                         break;
8684                 }
8685
8686                 p = trap[sig];
8687                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8688                  * don't upset it by resetting gotsig[SIGINT-1] */
8689                 if (sig == SIGINT && !p)
8690                         continue;
8691
8692                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8693                 *g = 0;
8694                 if (!p)
8695                         continue;
8696                 evalstring(p, 0);
8697         }
8698         exitstatus = last_status;
8699         TRACE(("dotrap returns\n"));
8700 }
8701
8702 /* forward declarations - evaluation is fairly recursive business... */
8703 static int evalloop(union node *, int);
8704 static int evalfor(union node *, int);
8705 static int evalcase(union node *, int);
8706 static int evalsubshell(union node *, int);
8707 static void expredir(union node *);
8708 static int evalpipe(union node *, int);
8709 static int evalcommand(union node *, int);
8710 static int evalbltin(const struct builtincmd *, int, char **, int);
8711 static void prehash(union node *);
8712
8713 /*
8714  * Evaluate a parse tree.  The value is left in the global variable
8715  * exitstatus.
8716  */
8717 static int
8718 evaltree(union node *n, int flags)
8719 {
8720         int checkexit = 0;
8721         int (*evalfn)(union node *, int);
8722         int status = 0;
8723
8724         if (n == NULL) {
8725                 TRACE(("evaltree(NULL) called\n"));
8726                 goto out;
8727         }
8728         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8729
8730         dotrap();
8731
8732         switch (n->type) {
8733         default:
8734 #if DEBUG
8735                 out1fmt("Node type = %d\n", n->type);
8736                 fflush_all();
8737                 break;
8738 #endif
8739         case NNOT:
8740                 status = !evaltree(n->nnot.com, EV_TESTED);
8741                 goto setstatus;
8742         case NREDIR:
8743                 expredir(n->nredir.redirect);
8744                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8745                 if (!status) {
8746                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8747                 }
8748                 if (n->nredir.redirect)
8749                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8750                 goto setstatus;
8751         case NCMD:
8752                 evalfn = evalcommand;
8753  checkexit:
8754                 if (eflag && !(flags & EV_TESTED))
8755                         checkexit = ~0;
8756                 goto calleval;
8757         case NFOR:
8758                 evalfn = evalfor;
8759                 goto calleval;
8760         case NWHILE:
8761         case NUNTIL:
8762                 evalfn = evalloop;
8763                 goto calleval;
8764         case NSUBSHELL:
8765         case NBACKGND:
8766                 evalfn = evalsubshell;
8767                 goto checkexit;
8768         case NPIPE:
8769                 evalfn = evalpipe;
8770                 goto checkexit;
8771         case NCASE:
8772                 evalfn = evalcase;
8773                 goto calleval;
8774         case NAND:
8775         case NOR:
8776         case NSEMI: {
8777
8778 #if NAND + 1 != NOR
8779 #error NAND + 1 != NOR
8780 #endif
8781 #if NOR + 1 != NSEMI
8782 #error NOR + 1 != NSEMI
8783 #endif
8784                 unsigned is_or = n->type - NAND;
8785                 status = evaltree(
8786                         n->nbinary.ch1,
8787                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8788                 );
8789                 if ((!status) == is_or || evalskip)
8790                         break;
8791                 n = n->nbinary.ch2;
8792  evaln:
8793                 evalfn = evaltree;
8794  calleval:
8795                 status = evalfn(n, flags);
8796                 goto setstatus;
8797         }
8798         case NIF:
8799                 status = evaltree(n->nif.test, EV_TESTED);
8800                 if (evalskip)
8801                         break;
8802                 if (!status) {
8803                         n = n->nif.ifpart;
8804                         goto evaln;
8805                 }
8806                 if (n->nif.elsepart) {
8807                         n = n->nif.elsepart;
8808                         goto evaln;
8809                 }
8810                 status = 0;
8811                 goto setstatus;
8812         case NDEFUN:
8813                 defun(n);
8814                 /* Not necessary. To test it:
8815                  * "false; f() { qwerty; }; echo $?" should print 0.
8816                  */
8817                 /* status = 0; */
8818  setstatus:
8819                 exitstatus = status;
8820                 break;
8821         }
8822  out:
8823         /* Order of checks below is important:
8824          * signal handlers trigger before exit caused by "set -e".
8825          */
8826         dotrap();
8827
8828         if (checkexit & status)
8829                 raise_exception(EXEXIT);
8830         if (flags & EV_EXIT)
8831                 raise_exception(EXEXIT);
8832
8833         TRACE(("leaving evaltree (no interrupts)\n"));
8834         return exitstatus;
8835 }
8836
8837 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8838 static
8839 #endif
8840 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8841
8842 static int
8843 skiploop(void)
8844 {
8845         int skip = evalskip;
8846
8847         switch (skip) {
8848         case 0:
8849                 break;
8850         case SKIPBREAK:
8851         case SKIPCONT:
8852                 if (--skipcount <= 0) {
8853                         evalskip = 0;
8854                         break;
8855                 }
8856                 skip = SKIPBREAK;
8857                 break;
8858         }
8859         return skip;
8860 }
8861
8862 static int
8863 evalloop(union node *n, int flags)
8864 {
8865         int skip;
8866         int status;
8867
8868         loopnest++;
8869         status = 0;
8870         flags &= EV_TESTED;
8871         do {
8872                 int i;
8873
8874                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8875                 skip = skiploop();
8876                 if (skip == SKIPFUNC)
8877                         status = i;
8878                 if (skip)
8879                         continue;
8880                 if (n->type != NWHILE)
8881                         i = !i;
8882                 if (i != 0)
8883                         break;
8884                 status = evaltree(n->nbinary.ch2, flags);
8885                 skip = skiploop();
8886         } while (!(skip & ~SKIPCONT));
8887         loopnest--;
8888
8889         return status;
8890 }
8891
8892 static int
8893 evalfor(union node *n, int flags)
8894 {
8895         struct arglist arglist;
8896         union node *argp;
8897         struct strlist *sp;
8898         struct stackmark smark;
8899         int status = 0;
8900
8901         setstackmark(&smark);
8902         arglist.list = NULL;
8903         arglist.lastp = &arglist.list;
8904         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8905                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8906         }
8907         *arglist.lastp = NULL;
8908
8909         loopnest++;
8910         flags &= EV_TESTED;
8911         for (sp = arglist.list; sp; sp = sp->next) {
8912                 setvar0(n->nfor.var, sp->text);
8913                 status = evaltree(n->nfor.body, flags);
8914                 if (skiploop() & ~SKIPCONT)
8915                         break;
8916         }
8917         loopnest--;
8918         popstackmark(&smark);
8919
8920         return status;
8921 }
8922
8923 static int
8924 evalcase(union node *n, int flags)
8925 {
8926         union node *cp;
8927         union node *patp;
8928         struct arglist arglist;
8929         struct stackmark smark;
8930         int status = 0;
8931
8932         setstackmark(&smark);
8933         arglist.list = NULL;
8934         arglist.lastp = &arglist.list;
8935         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8936         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8937                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8938                         if (casematch(patp, arglist.list->text)) {
8939                                 /* Ensure body is non-empty as otherwise
8940                                  * EV_EXIT may prevent us from setting the
8941                                  * exit status.
8942                                  */
8943                                 if (evalskip == 0 && cp->nclist.body) {
8944                                         status = evaltree(cp->nclist.body, flags);
8945                                 }
8946                                 goto out;
8947                         }
8948                 }
8949         }
8950  out:
8951         popstackmark(&smark);
8952
8953         return status;
8954 }
8955
8956 /*
8957  * Kick off a subshell to evaluate a tree.
8958  */
8959 static int
8960 evalsubshell(union node *n, int flags)
8961 {
8962         struct job *jp;
8963         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8964         int status;
8965
8966         expredir(n->nredir.redirect);
8967         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8968                 goto nofork;
8969         INT_OFF;
8970         if (backgnd == FORK_FG)
8971                 get_tty_state();
8972         jp = makejob(/*n,*/ 1);
8973         if (forkshell(jp, n, backgnd) == 0) {
8974                 /* child */
8975                 INT_ON;
8976                 flags |= EV_EXIT;
8977                 if (backgnd)
8978                         flags &= ~EV_TESTED;
8979  nofork:
8980                 redirect(n->nredir.redirect, 0);
8981                 evaltreenr(n->nredir.n, flags);
8982                 /* never returns */
8983         }
8984         /* parent */
8985         status = 0;
8986         if (backgnd == FORK_FG)
8987                 status = waitforjob(jp);
8988         INT_ON;
8989         return status;
8990 }
8991
8992 /*
8993  * Compute the names of the files in a redirection list.
8994  */
8995 static void fixredir(union node *, const char *, int);
8996 static void
8997 expredir(union node *n)
8998 {
8999         union node *redir;
9000
9001         for (redir = n; redir; redir = redir->nfile.next) {
9002                 struct arglist fn;
9003
9004                 fn.list = NULL;
9005                 fn.lastp = &fn.list;
9006                 switch (redir->type) {
9007                 case NFROMTO:
9008                 case NFROM:
9009                 case NTO:
9010 #if BASH_REDIR_OUTPUT
9011                 case NTO2:
9012 #endif
9013                 case NCLOBBER:
9014                 case NAPPEND:
9015                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9016                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9017 #if BASH_REDIR_OUTPUT
9018  store_expfname:
9019 #endif
9020 #if 0
9021 // By the design of stack allocator, the loop of this kind:
9022 //      while true; do while true; do break; done </dev/null; done
9023 // will look like a memory leak: ash plans to free expfname's
9024 // of "/dev/null" as soon as it finishes running the loop
9025 // (in this case, never).
9026 // This "fix" is wrong:
9027                         if (redir->nfile.expfname)
9028                                 stunalloc(redir->nfile.expfname);
9029 // It results in corrupted state of stacked allocations.
9030 #endif
9031                         redir->nfile.expfname = fn.list->text;
9032                         break;
9033                 case NFROMFD:
9034                 case NTOFD: /* >& */
9035                         if (redir->ndup.vname) {
9036                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9037                                 if (fn.list == NULL)
9038                                         ash_msg_and_raise_error("redir error");
9039 #if BASH_REDIR_OUTPUT
9040 //FIXME: we used expandarg with different args!
9041                                 if (!isdigit_str9(fn.list->text)) {
9042                                         /* >&file, not >&fd */
9043                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9044                                                 ash_msg_and_raise_error("redir error");
9045                                         redir->type = NTO2;
9046                                         goto store_expfname;
9047                                 }
9048 #endif
9049                                 fixredir(redir, fn.list->text, 1);
9050                         }
9051                         break;
9052                 }
9053         }
9054 }
9055
9056 /*
9057  * Evaluate a pipeline.  All the processes in the pipeline are children
9058  * of the process creating the pipeline.  (This differs from some versions
9059  * of the shell, which make the last process in a pipeline the parent
9060  * of all the rest.)
9061  */
9062 static int
9063 evalpipe(union node *n, int flags)
9064 {
9065         struct job *jp;
9066         struct nodelist *lp;
9067         int pipelen;
9068         int prevfd;
9069         int pip[2];
9070         int status = 0;
9071
9072         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9073         pipelen = 0;
9074         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9075                 pipelen++;
9076         flags |= EV_EXIT;
9077         INT_OFF;
9078         if (n->npipe.pipe_backgnd == 0)
9079                 get_tty_state();
9080         jp = makejob(/*n,*/ pipelen);
9081         prevfd = -1;
9082         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9083                 prehash(lp->n);
9084                 pip[1] = -1;
9085                 if (lp->next) {
9086                         if (pipe(pip) < 0) {
9087                                 close(prevfd);
9088                                 ash_msg_and_raise_error("pipe call failed");
9089                         }
9090                 }
9091                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9092                         /* child */
9093                         INT_ON;
9094                         if (pip[1] >= 0) {
9095                                 close(pip[0]);
9096                         }
9097                         if (prevfd > 0) {
9098                                 dup2(prevfd, 0);
9099                                 close(prevfd);
9100                         }
9101                         if (pip[1] > 1) {
9102                                 dup2(pip[1], 1);
9103                                 close(pip[1]);
9104                         }
9105                         evaltreenr(lp->n, flags);
9106                         /* never returns */
9107                 }
9108                 /* parent */
9109                 if (prevfd >= 0)
9110                         close(prevfd);
9111                 prevfd = pip[0];
9112                 /* Don't want to trigger debugging */
9113                 if (pip[1] != -1)
9114                         close(pip[1]);
9115         }
9116         if (n->npipe.pipe_backgnd == 0) {
9117                 status = waitforjob(jp);
9118                 TRACE(("evalpipe:  job done exit status %d\n", status));
9119         }
9120         INT_ON;
9121
9122         return status;
9123 }
9124
9125 /*
9126  * Controls whether the shell is interactive or not.
9127  */
9128 static void
9129 setinteractive(int on)
9130 {
9131         static smallint is_interactive;
9132
9133         if (++on == is_interactive)
9134                 return;
9135         is_interactive = on;
9136         setsignal(SIGINT);
9137         setsignal(SIGQUIT);
9138         setsignal(SIGTERM);
9139 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9140         if (is_interactive > 1) {
9141                 /* Looks like they want an interactive shell */
9142                 static smallint did_banner;
9143
9144                 if (!did_banner) {
9145                         /* note: ash and hush share this string */
9146                         out1fmt("\n\n%s %s\n"
9147                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9148                                 "\n",
9149                                 bb_banner,
9150                                 "built-in shell (ash)"
9151                         );
9152                         did_banner = 1;
9153                 }
9154         }
9155 #endif
9156 }
9157
9158 static void
9159 optschanged(void)
9160 {
9161 #if DEBUG
9162         opentrace();
9163 #endif
9164         setinteractive(iflag);
9165         setjobctl(mflag);
9166 #if ENABLE_FEATURE_EDITING_VI
9167         if (viflag)
9168                 line_input_state->flags |= VI_MODE;
9169         else
9170                 line_input_state->flags &= ~VI_MODE;
9171 #else
9172         viflag = 0; /* forcibly keep the option off */
9173 #endif
9174 }
9175
9176 static struct localvar *localvars;
9177
9178 /*
9179  * Called after a function returns.
9180  * Interrupts must be off.
9181  */
9182 static void
9183 poplocalvars(void)
9184 {
9185         struct localvar *lvp;
9186         struct var *vp;
9187
9188         while ((lvp = localvars) != NULL) {
9189                 localvars = lvp->next;
9190                 vp = lvp->vp;
9191                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9192                 if (vp == NULL) {       /* $- saved */
9193                         memcpy(optlist, lvp->text, sizeof(optlist));
9194                         free((char*)lvp->text);
9195                         optschanged();
9196                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9197                         unsetvar(vp->var_text);
9198                 } else {
9199                         if (vp->var_func)
9200                                 vp->var_func(var_end(lvp->text));
9201                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9202                                 free((char*)vp->var_text);
9203                         vp->flags = lvp->flags;
9204                         vp->var_text = lvp->text;
9205                 }
9206                 free(lvp);
9207         }
9208 }
9209
9210 static int
9211 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9212 {
9213         volatile struct shparam saveparam;
9214         struct localvar *volatile savelocalvars;
9215         struct jmploc *volatile savehandler;
9216         struct jmploc jmploc;
9217         int e;
9218
9219         saveparam = shellparam;
9220         savelocalvars = localvars;
9221         savehandler = exception_handler;
9222         e = setjmp(jmploc.loc);
9223         if (e) {
9224                 goto funcdone;
9225         }
9226         INT_OFF;
9227         exception_handler = &jmploc;
9228         localvars = NULL;
9229         shellparam.malloced = 0;
9230         func->count++;
9231         funcnest++;
9232         INT_ON;
9233         shellparam.nparam = argc - 1;
9234         shellparam.p = argv + 1;
9235 #if ENABLE_ASH_GETOPTS
9236         shellparam.optind = 1;
9237         shellparam.optoff = -1;
9238 #endif
9239         evaltree(func->n.narg.next, flags & EV_TESTED);
9240  funcdone:
9241         INT_OFF;
9242         funcnest--;
9243         freefunc(func);
9244         poplocalvars();
9245         localvars = savelocalvars;
9246         freeparam(&shellparam);
9247         shellparam = saveparam;
9248         exception_handler = savehandler;
9249         INT_ON;
9250         evalskip &= ~SKIPFUNC;
9251         return e;
9252 }
9253
9254 /*
9255  * Make a variable a local variable.  When a variable is made local, it's
9256  * value and flags are saved in a localvar structure.  The saved values
9257  * will be restored when the shell function returns.  We handle the name
9258  * "-" as a special case: it makes changes to "set +-options" local
9259  * (options will be restored on return from the function).
9260  */
9261 static void
9262 mklocal(char *name)
9263 {
9264         struct localvar *lvp;
9265         struct var **vpp;
9266         struct var *vp;
9267         char *eq = strchr(name, '=');
9268
9269         INT_OFF;
9270         /* Cater for duplicate "local". Examples:
9271          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9272          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9273          */
9274         lvp = localvars;
9275         while (lvp) {
9276                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9277                         if (eq)
9278                                 setvareq(name, 0);
9279                         /* else:
9280                          * it's a duplicate "local VAR" declaration, do nothing
9281                          */
9282                         goto ret;
9283                 }
9284                 lvp = lvp->next;
9285         }
9286
9287         lvp = ckzalloc(sizeof(*lvp));
9288         if (LONE_DASH(name)) {
9289                 char *p;
9290                 p = ckmalloc(sizeof(optlist));
9291                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9292                 vp = NULL;
9293         } else {
9294                 vpp = hashvar(name);
9295                 vp = *findvar(vpp, name);
9296                 if (vp == NULL) {
9297                         /* variable did not exist yet */
9298                         if (eq)
9299                                 setvareq(name, VSTRFIXED);
9300                         else
9301                                 setvar(name, NULL, VSTRFIXED);
9302                         vp = *vpp;      /* the new variable */
9303                         lvp->flags = VUNSET;
9304                 } else {
9305                         lvp->text = vp->var_text;
9306                         lvp->flags = vp->flags;
9307                         /* make sure neither "struct var" nor string gets freed
9308                          * during (un)setting:
9309                          */
9310                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9311                         if (eq)
9312                                 setvareq(name, 0);
9313                         else
9314                                 /* "local VAR" unsets VAR: */
9315                                 setvar0(name, NULL);
9316                 }
9317         }
9318         lvp->vp = vp;
9319         lvp->next = localvars;
9320         localvars = lvp;
9321  ret:
9322         INT_ON;
9323 }
9324
9325 /*
9326  * The "local" command.
9327  */
9328 static int FAST_FUNC
9329 localcmd(int argc UNUSED_PARAM, char **argv)
9330 {
9331         char *name;
9332
9333         if (!funcnest)
9334                 ash_msg_and_raise_error("not in a function");
9335
9336         argv = argptr;
9337         while ((name = *argv++) != NULL) {
9338                 mklocal(name);
9339         }
9340         return 0;
9341 }
9342
9343 static int FAST_FUNC
9344 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9345 {
9346         return 1;
9347 }
9348
9349 static int FAST_FUNC
9350 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9351 {
9352         return 0;
9353 }
9354
9355 static int FAST_FUNC
9356 execcmd(int argc UNUSED_PARAM, char **argv)
9357 {
9358         if (argv[1]) {
9359                 iflag = 0;              /* exit on error */
9360                 mflag = 0;
9361                 optschanged();
9362                 /* We should set up signals for "exec CMD"
9363                  * the same way as for "CMD" without "exec".
9364                  * But optschanged->setinteractive->setsignal
9365                  * still thought we are a root shell. Therefore, for example,
9366                  * SIGQUIT is still set to IGN. Fix it:
9367                  */
9368                 shlvl++;
9369                 setsignal(SIGQUIT);
9370                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9371                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9372                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9373
9374                 shellexec(argv + 1, pathval(), 0);
9375                 /* NOTREACHED */
9376         }
9377         return 0;
9378 }
9379
9380 /*
9381  * The return command.
9382  */
9383 static int FAST_FUNC
9384 returncmd(int argc UNUSED_PARAM, char **argv)
9385 {
9386         /*
9387          * If called outside a function, do what ksh does;
9388          * skip the rest of the file.
9389          */
9390         evalskip = SKIPFUNC;
9391         return argv[1] ? number(argv[1]) : exitstatus;
9392 }
9393
9394 /* Forward declarations for builtintab[] */
9395 static int breakcmd(int, char **) FAST_FUNC;
9396 static int dotcmd(int, char **) FAST_FUNC;
9397 static int evalcmd(int, char **, int) FAST_FUNC;
9398 static int exitcmd(int, char **) FAST_FUNC;
9399 static int exportcmd(int, char **) FAST_FUNC;
9400 #if ENABLE_ASH_GETOPTS
9401 static int getoptscmd(int, char **) FAST_FUNC;
9402 #endif
9403 #if ENABLE_ASH_HELP
9404 static int helpcmd(int, char **) FAST_FUNC;
9405 #endif
9406 #if MAX_HISTORY
9407 static int historycmd(int, char **) FAST_FUNC;
9408 #endif
9409 #if ENABLE_FEATURE_SH_MATH
9410 static int letcmd(int, char **) FAST_FUNC;
9411 #endif
9412 static int readcmd(int, char **) FAST_FUNC;
9413 static int setcmd(int, char **) FAST_FUNC;
9414 static int shiftcmd(int, char **) FAST_FUNC;
9415 static int timescmd(int, char **) FAST_FUNC;
9416 static int trapcmd(int, char **) FAST_FUNC;
9417 static int umaskcmd(int, char **) FAST_FUNC;
9418 static int unsetcmd(int, char **) FAST_FUNC;
9419 static int ulimitcmd(int, char **) FAST_FUNC;
9420
9421 #define BUILTIN_NOSPEC          "0"
9422 #define BUILTIN_SPECIAL         "1"
9423 #define BUILTIN_REGULAR         "2"
9424 #define BUILTIN_SPEC_REG        "3"
9425 #define BUILTIN_ASSIGN          "4"
9426 #define BUILTIN_SPEC_ASSG       "5"
9427 #define BUILTIN_REG_ASSG        "6"
9428 #define BUILTIN_SPEC_REG_ASSG   "7"
9429
9430 /* Stubs for calling non-FAST_FUNC's */
9431 #if ENABLE_ASH_ECHO
9432 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9433 #endif
9434 #if ENABLE_ASH_PRINTF
9435 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9436 #endif
9437 #if ENABLE_ASH_TEST || BASH_TEST2
9438 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9439 #endif
9440
9441 /* Keep these in proper order since it is searched via bsearch() */
9442 static const struct builtincmd builtintab[] = {
9443         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9444         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9445 #if ENABLE_ASH_TEST
9446         { BUILTIN_REGULAR       "["       , testcmd    },
9447 #endif
9448 #if BASH_TEST2
9449         { BUILTIN_REGULAR       "[["      , testcmd    },
9450 #endif
9451 #if ENABLE_ASH_ALIAS
9452         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9453 #endif
9454 #if JOBS
9455         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9456 #endif
9457         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9458         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9459         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9460 #if ENABLE_ASH_CMDCMD
9461         { BUILTIN_REGULAR       "command" , commandcmd },
9462 #endif
9463         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9464 #if ENABLE_ASH_ECHO
9465         { BUILTIN_REGULAR       "echo"    , echocmd    },
9466 #endif
9467         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9468         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9469         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9470         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9471         { BUILTIN_REGULAR       "false"   , falsecmd   },
9472 #if JOBS
9473         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9474 #endif
9475 #if ENABLE_ASH_GETOPTS
9476         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9477 #endif
9478         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9479 #if ENABLE_ASH_HELP
9480         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9481 #endif
9482 #if MAX_HISTORY
9483         { BUILTIN_NOSPEC        "history" , historycmd },
9484 #endif
9485 #if JOBS
9486         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9487         { BUILTIN_REGULAR       "kill"    , killcmd    },
9488 #endif
9489 #if ENABLE_FEATURE_SH_MATH
9490         { BUILTIN_NOSPEC        "let"     , letcmd     },
9491 #endif
9492         { BUILTIN_ASSIGN        "local"   , localcmd   },
9493 #if ENABLE_ASH_PRINTF
9494         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9495 #endif
9496         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9497         { BUILTIN_REGULAR       "read"    , readcmd    },
9498         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9499         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9500         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9501         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9502 #if BASH_SOURCE
9503         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9504 #endif
9505 #if ENABLE_ASH_TEST
9506         { BUILTIN_REGULAR       "test"    , testcmd    },
9507 #endif
9508         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9509         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9510         { BUILTIN_REGULAR       "true"    , truecmd    },
9511         { BUILTIN_NOSPEC        "type"    , typecmd    },
9512         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9513         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9514 #if ENABLE_ASH_ALIAS
9515         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9516 #endif
9517         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9518         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9519 };
9520
9521 /* Should match the above table! */
9522 #define COMMANDCMD (builtintab + \
9523         /* . : */       2 + \
9524         /* [ */         1 * ENABLE_ASH_TEST + \
9525         /* [[ */        1 * BASH_TEST2 + \
9526         /* alias */     1 * ENABLE_ASH_ALIAS + \
9527         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9528         /* break cd cddir  */   3)
9529 #define EVALCMD (COMMANDCMD + \
9530         /* command */   1 * ENABLE_ASH_CMDCMD + \
9531         /* continue */  1 + \
9532         /* echo */      1 * ENABLE_ASH_ECHO + \
9533         0)
9534 #define EXECCMD (EVALCMD + \
9535         /* eval */      1)
9536
9537 /*
9538  * Search the table of builtin commands.
9539  */
9540 static int
9541 pstrcmp1(const void *a, const void *b)
9542 {
9543         return strcmp((char*)a, *(char**)b + 1);
9544 }
9545 static struct builtincmd *
9546 find_builtin(const char *name)
9547 {
9548         struct builtincmd *bp;
9549
9550         bp = bsearch(
9551                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9552                 pstrcmp1
9553         );
9554         return bp;
9555 }
9556
9557 /*
9558  * Execute a simple command.
9559  */
9560 static int
9561 isassignment(const char *p)
9562 {
9563         const char *q = endofname(p);
9564         if (p == q)
9565                 return 0;
9566         return *q == '=';
9567 }
9568 static int FAST_FUNC
9569 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9570 {
9571         /* Preserve exitstatus of a previous possible redirection
9572          * as POSIX mandates */
9573         return back_exitstatus;
9574 }
9575 static int
9576 evalcommand(union node *cmd, int flags)
9577 {
9578         static const struct builtincmd null_bltin = {
9579                 "\0\0", bltincmd /* why three NULs? */
9580         };
9581         struct stackmark smark;
9582         union node *argp;
9583         struct arglist arglist;
9584         struct arglist varlist;
9585         char **argv;
9586         int argc;
9587         const struct strlist *sp;
9588         struct cmdentry cmdentry;
9589         struct job *jp;
9590         char *lastarg;
9591         const char *path;
9592         int spclbltin;
9593         int status;
9594         char **nargv;
9595         struct builtincmd *bcmd;
9596         smallint cmd_is_exec;
9597         smallint pseudovarflag = 0;
9598
9599         /* First expand the arguments. */
9600         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9601         setstackmark(&smark);
9602         back_exitstatus = 0;
9603
9604         cmdentry.cmdtype = CMDBUILTIN;
9605         cmdentry.u.cmd = &null_bltin;
9606         varlist.lastp = &varlist.list;
9607         *varlist.lastp = NULL;
9608         arglist.lastp = &arglist.list;
9609         *arglist.lastp = NULL;
9610
9611         argc = 0;
9612         if (cmd->ncmd.args) {
9613                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9614                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9615         }
9616
9617         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9618                 struct strlist **spp;
9619
9620                 spp = arglist.lastp;
9621                 if (pseudovarflag && isassignment(argp->narg.text))
9622                         expandarg(argp, &arglist, EXP_VARTILDE);
9623                 else
9624                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9625
9626                 for (sp = *spp; sp; sp = sp->next)
9627                         argc++;
9628         }
9629
9630         /* Reserve one extra spot at the front for shellexec. */
9631         nargv = stalloc(sizeof(char *) * (argc + 2));
9632         argv = ++nargv;
9633         for (sp = arglist.list; sp; sp = sp->next) {
9634                 TRACE(("evalcommand arg: %s\n", sp->text));
9635                 *nargv++ = sp->text;
9636         }
9637         *nargv = NULL;
9638
9639         lastarg = NULL;
9640         if (iflag && funcnest == 0 && argc > 0)
9641                 lastarg = nargv[-1];
9642
9643         preverrout_fd = 2;
9644         expredir(cmd->ncmd.redirect);
9645         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9646
9647         path = vpath.var_text;
9648         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9649                 struct strlist **spp;
9650                 char *p;
9651
9652                 spp = varlist.lastp;
9653                 expandarg(argp, &varlist, EXP_VARTILDE);
9654
9655                 /*
9656                  * Modify the command lookup path, if a PATH= assignment
9657                  * is present
9658                  */
9659                 p = (*spp)->text;
9660                 if (varcmp(p, path) == 0)
9661                         path = p;
9662         }
9663
9664         /* Print the command if xflag is set. */
9665         if (xflag) {
9666                 int n;
9667                 const char *p = " %s" + 1;
9668
9669                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9670                 sp = varlist.list;
9671                 for (n = 0; n < 2; n++) {
9672                         while (sp) {
9673                                 fdprintf(preverrout_fd, p, sp->text);
9674                                 sp = sp->next;
9675                                 p = " %s";
9676                         }
9677                         sp = arglist.list;
9678                 }
9679                 safe_write(preverrout_fd, "\n", 1);
9680         }
9681
9682         cmd_is_exec = 0;
9683         spclbltin = -1;
9684
9685         /* Now locate the command. */
9686         if (argc) {
9687                 int cmd_flag = DO_ERR;
9688 #if ENABLE_ASH_CMDCMD
9689                 const char *oldpath = path + 5;
9690 #endif
9691                 path += 5;
9692                 for (;;) {
9693                         find_command(argv[0], &cmdentry, cmd_flag, path);
9694                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9695                                 flush_stdout_stderr();
9696                                 status = 127;
9697                                 goto bail;
9698                         }
9699
9700                         /* implement bltin and command here */
9701                         if (cmdentry.cmdtype != CMDBUILTIN)
9702                                 break;
9703                         if (spclbltin < 0)
9704                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9705                         if (cmdentry.u.cmd == EXECCMD)
9706                                 cmd_is_exec = 1;
9707 #if ENABLE_ASH_CMDCMD
9708                         if (cmdentry.u.cmd == COMMANDCMD) {
9709                                 path = oldpath;
9710                                 nargv = parse_command_args(argv, &path);
9711                                 if (!nargv)
9712                                         break;
9713                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9714                                  * nargv => "PROG". path is updated if -p.
9715                                  */
9716                                 argc -= nargv - argv;
9717                                 argv = nargv;
9718                                 cmd_flag |= DO_NOFUNC;
9719                         } else
9720 #endif
9721                                 break;
9722                 }
9723         }
9724
9725         if (status) {
9726  bail:
9727                 exitstatus = status;
9728
9729                 /* We have a redirection error. */
9730                 if (spclbltin > 0)
9731                         raise_exception(EXERROR);
9732
9733                 goto out;
9734         }
9735
9736         /* Execute the command. */
9737         switch (cmdentry.cmdtype) {
9738         default: {
9739
9740 #if ENABLE_FEATURE_SH_NOFORK
9741 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9742  *     around run_nofork_applet() call.
9743  * (2) Should this check also be done in forkshell()?
9744  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9745  */
9746                 /* find_command() encodes applet_no as (-2 - applet_no) */
9747                 int applet_no = (- cmdentry.u.index - 2);
9748                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9749                         listsetvar(varlist.list, VEXPORT|VSTACK);
9750                         /* run <applet>_main() */
9751                         status = run_nofork_applet(applet_no, argv);
9752                         break;
9753                 }
9754 #endif
9755                 /* Can we avoid forking off? For example, very last command
9756                  * in a script or a subshell does not need forking,
9757                  * we can just exec it.
9758                  */
9759                 if (!(flags & EV_EXIT) || may_have_traps) {
9760                         /* No, forking off a child is necessary */
9761                         INT_OFF;
9762                         get_tty_state();
9763                         jp = makejob(/*cmd,*/ 1);
9764                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9765                                 /* parent */
9766                                 status = waitforjob(jp);
9767                                 INT_ON;
9768                                 TRACE(("forked child exited with %d\n", status));
9769                                 break;
9770                         }
9771                         /* child */
9772                         FORCE_INT_ON;
9773                         /* fall through to exec'ing external program */
9774                 }
9775                 listsetvar(varlist.list, VEXPORT|VSTACK);
9776                 shellexec(argv, path, cmdentry.u.index);
9777                 /* NOTREACHED */
9778         } /* default */
9779         case CMDBUILTIN:
9780                 cmdenviron = varlist.list;
9781                 if (cmdenviron) {
9782                         struct strlist *list = cmdenviron;
9783                         int i = VNOSET;
9784                         if (spclbltin > 0 || argc == 0) {
9785                                 i = 0;
9786                                 if (cmd_is_exec && argc > 1)
9787                                         i = VEXPORT;
9788                         }
9789                         listsetvar(list, i);
9790                 }
9791                 /* Tight loop with builtins only:
9792                  * "while kill -0 $child; do true; done"
9793                  * will never exit even if $child died, unless we do this
9794                  * to reap the zombie and make kill detect that it's gone: */
9795                 dowait(DOWAIT_NONBLOCK, NULL);
9796
9797                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9798                         if (exception_type == EXERROR && spclbltin <= 0) {
9799                                 FORCE_INT_ON;
9800                                 goto readstatus;
9801                         }
9802  raise:
9803                         longjmp(exception_handler->loc, 1);
9804                 }
9805                 goto readstatus;
9806
9807         case CMDFUNCTION:
9808                 listsetvar(varlist.list, 0);
9809                 /* See above for the rationale */
9810                 dowait(DOWAIT_NONBLOCK, NULL);
9811                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9812                         goto raise;
9813  readstatus:
9814                 status = exitstatus;
9815                 break;
9816         } /* switch */
9817
9818  out:
9819         if (cmd->ncmd.redirect)
9820                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9821         if (lastarg) {
9822                 /* dsl: I think this is intended to be used to support
9823                  * '_' in 'vi' command mode during line editing...
9824                  * However I implemented that within libedit itself.
9825                  */
9826                 setvar0("_", lastarg);
9827         }
9828         popstackmark(&smark);
9829
9830         return status;
9831 }
9832
9833 static int
9834 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9835 {
9836         char *volatile savecmdname;
9837         struct jmploc *volatile savehandler;
9838         struct jmploc jmploc;
9839         int status;
9840         int i;
9841
9842         savecmdname = commandname;
9843         savehandler = exception_handler;
9844         i = setjmp(jmploc.loc);
9845         if (i)
9846                 goto cmddone;
9847         exception_handler = &jmploc;
9848         commandname = argv[0];
9849         argptr = argv + 1;
9850         optptr = NULL;                  /* initialize nextopt */
9851         if (cmd == EVALCMD)
9852                 status = evalcmd(argc, argv, flags);
9853         else
9854                 status = (*cmd->builtin)(argc, argv);
9855         flush_stdout_stderr();
9856         status |= ferror(stdout);
9857         exitstatus = status;
9858  cmddone:
9859         clearerr(stdout);
9860         commandname = savecmdname;
9861         exception_handler = savehandler;
9862
9863         return i;
9864 }
9865
9866 static int
9867 goodname(const char *p)
9868 {
9869         return endofname(p)[0] == '\0';
9870 }
9871
9872
9873 /*
9874  * Search for a command.  This is called before we fork so that the
9875  * location of the command will be available in the parent as well as
9876  * the child.  The check for "goodname" is an overly conservative
9877  * check that the name will not be subject to expansion.
9878  */
9879 static void
9880 prehash(union node *n)
9881 {
9882         struct cmdentry entry;
9883
9884         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9885                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9886 }
9887
9888
9889 /* ============ Builtin commands
9890  *
9891  * Builtin commands whose functions are closely tied to evaluation
9892  * are implemented here.
9893  */
9894
9895 /*
9896  * Handle break and continue commands.  Break, continue, and return are
9897  * all handled by setting the evalskip flag.  The evaluation routines
9898  * above all check this flag, and if it is set they start skipping
9899  * commands rather than executing them.  The variable skipcount is
9900  * the number of loops to break/continue, or the number of function
9901  * levels to return.  (The latter is always 1.)  It should probably
9902  * be an error to break out of more loops than exist, but it isn't
9903  * in the standard shell so we don't make it one here.
9904  */
9905 static int FAST_FUNC
9906 breakcmd(int argc UNUSED_PARAM, char **argv)
9907 {
9908         int n = argv[1] ? number(argv[1]) : 1;
9909
9910         if (n <= 0)
9911                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9912         if (n > loopnest)
9913                 n = loopnest;
9914         if (n > 0) {
9915                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9916                 skipcount = n;
9917         }
9918         return 0;
9919 }
9920
9921
9922 /*
9923  * This implements the input routines used by the parser.
9924  */
9925
9926 enum {
9927         INPUT_PUSH_FILE = 1,
9928         INPUT_NOFILE_OK = 2,
9929 };
9930
9931 static smallint checkkwd;
9932 /* values of checkkwd variable */
9933 #define CHKALIAS        0x1
9934 #define CHKKWD          0x2
9935 #define CHKNL           0x4
9936
9937 /*
9938  * Push a string back onto the input at this current parsefile level.
9939  * We handle aliases this way.
9940  */
9941 #if !ENABLE_ASH_ALIAS
9942 #define pushstring(s, ap) pushstring(s)
9943 #endif
9944 static void
9945 pushstring(char *s, struct alias *ap)
9946 {
9947         struct strpush *sp;
9948         int len;
9949
9950         len = strlen(s);
9951         INT_OFF;
9952         if (g_parsefile->strpush) {
9953                 sp = ckzalloc(sizeof(*sp));
9954                 sp->prev = g_parsefile->strpush;
9955         } else {
9956                 sp = &(g_parsefile->basestrpush);
9957         }
9958         g_parsefile->strpush = sp;
9959         sp->prev_string = g_parsefile->next_to_pgetc;
9960         sp->prev_left_in_line = g_parsefile->left_in_line;
9961         sp->unget = g_parsefile->unget;
9962         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9963 #if ENABLE_ASH_ALIAS
9964         sp->ap = ap;
9965         if (ap) {
9966                 ap->flag |= ALIASINUSE;
9967                 sp->string = s;
9968         }
9969 #endif
9970         g_parsefile->next_to_pgetc = s;
9971         g_parsefile->left_in_line = len;
9972         g_parsefile->unget = 0;
9973         INT_ON;
9974 }
9975
9976 static void
9977 popstring(void)
9978 {
9979         struct strpush *sp = g_parsefile->strpush;
9980
9981         INT_OFF;
9982 #if ENABLE_ASH_ALIAS
9983         if (sp->ap) {
9984                 if (g_parsefile->next_to_pgetc[-1] == ' '
9985                  || g_parsefile->next_to_pgetc[-1] == '\t'
9986                 ) {
9987                         checkkwd |= CHKALIAS;
9988                 }
9989                 if (sp->string != sp->ap->val) {
9990                         free(sp->string);
9991                 }
9992                 sp->ap->flag &= ~ALIASINUSE;
9993                 if (sp->ap->flag & ALIASDEAD) {
9994                         unalias(sp->ap->name);
9995                 }
9996         }
9997 #endif
9998         g_parsefile->next_to_pgetc = sp->prev_string;
9999         g_parsefile->left_in_line = sp->prev_left_in_line;
10000         g_parsefile->unget = sp->unget;
10001         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10002         g_parsefile->strpush = sp->prev;
10003         if (sp != &(g_parsefile->basestrpush))
10004                 free(sp);
10005         INT_ON;
10006 }
10007
10008 static int
10009 preadfd(void)
10010 {
10011         int nr;
10012         char *buf = g_parsefile->buf;
10013
10014         g_parsefile->next_to_pgetc = buf;
10015 #if ENABLE_FEATURE_EDITING
10016  retry:
10017         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10018                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10019         else {
10020                 int timeout = -1;
10021 # if ENABLE_ASH_IDLE_TIMEOUT
10022                 if (iflag) {
10023                         const char *tmout_var = lookupvar("TMOUT");
10024                         if (tmout_var) {
10025                                 timeout = atoi(tmout_var) * 1000;
10026                                 if (timeout <= 0)
10027                                         timeout = -1;
10028                         }
10029                 }
10030 # endif
10031 # if ENABLE_FEATURE_TAB_COMPLETION
10032                 line_input_state->path_lookup = pathval();
10033 # endif
10034                 reinit_unicode_for_ash();
10035                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10036                 if (nr == 0) {
10037                         /* ^C pressed, "convert" to SIGINT */
10038                         write(STDOUT_FILENO, "^C", 2);
10039                         if (trap[SIGINT]) {
10040                                 buf[0] = '\n';
10041                                 buf[1] = '\0';
10042                                 raise(SIGINT);
10043                                 return 1;
10044                         }
10045                         exitstatus = 128 + SIGINT;
10046                         bb_putchar('\n');
10047                         goto retry;
10048                 }
10049                 if (nr < 0) {
10050                         if (errno == 0) {
10051                                 /* Ctrl+D pressed */
10052                                 nr = 0;
10053                         }
10054 # if ENABLE_ASH_IDLE_TIMEOUT
10055                         else if (errno == EAGAIN && timeout > 0) {
10056                                 puts("\007timed out waiting for input: auto-logout");
10057                                 exitshell();
10058                         }
10059 # endif
10060                 }
10061         }
10062 #else
10063         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10064 #endif
10065
10066 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10067         if (nr < 0) {
10068                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10069                         int flags = fcntl(0, F_GETFL);
10070                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10071                                 flags &= ~O_NONBLOCK;
10072                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10073                                         out2str("sh: turning off NDELAY mode\n");
10074                                         goto retry;
10075                                 }
10076                         }
10077                 }
10078         }
10079 #endif
10080         return nr;
10081 }
10082
10083 /*
10084  * Refill the input buffer and return the next input character:
10085  *
10086  * 1) If a string was pushed back on the input, pop it;
10087  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10088  *    or we are reading from a string so we can't refill the buffer,
10089  *    return EOF.
10090  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10091  * 4) Process input up to the next newline, deleting nul characters.
10092  */
10093 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10094 #define pgetc_debug(...) ((void)0)
10095 static int pgetc(void);
10096 static int
10097 preadbuffer(void)
10098 {
10099         char *q;
10100         int more;
10101
10102         if (g_parsefile->strpush) {
10103 #if ENABLE_ASH_ALIAS
10104                 if (g_parsefile->left_in_line == -1
10105                  && g_parsefile->strpush->ap
10106                  && g_parsefile->next_to_pgetc[-1] != ' '
10107                  && g_parsefile->next_to_pgetc[-1] != '\t'
10108                 ) {
10109                         pgetc_debug("preadbuffer PEOA");
10110                         return PEOA;
10111                 }
10112 #endif
10113                 popstring();
10114                 return pgetc();
10115         }
10116         /* on both branches above g_parsefile->left_in_line < 0.
10117          * "pgetc" needs refilling.
10118          */
10119
10120         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10121          * pungetc() may increment it a few times.
10122          * Assuming it won't increment it to less than -90.
10123          */
10124         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10125                 pgetc_debug("preadbuffer PEOF1");
10126                 /* even in failure keep left_in_line and next_to_pgetc
10127                  * in lock step, for correct multi-layer pungetc.
10128                  * left_in_line was decremented before preadbuffer(),
10129                  * must inc next_to_pgetc: */
10130                 g_parsefile->next_to_pgetc++;
10131                 return PEOF;
10132         }
10133
10134         more = g_parsefile->left_in_buffer;
10135         if (more <= 0) {
10136                 flush_stdout_stderr();
10137  again:
10138                 more = preadfd();
10139                 if (more <= 0) {
10140                         /* don't try reading again */
10141                         g_parsefile->left_in_line = -99;
10142                         pgetc_debug("preadbuffer PEOF2");
10143                         g_parsefile->next_to_pgetc++;
10144                         return PEOF;
10145                 }
10146         }
10147
10148         /* Find out where's the end of line.
10149          * Set g_parsefile->left_in_line
10150          * and g_parsefile->left_in_buffer acordingly.
10151          * NUL chars are deleted.
10152          */
10153         q = g_parsefile->next_to_pgetc;
10154         for (;;) {
10155                 char c;
10156
10157                 more--;
10158
10159                 c = *q;
10160                 if (c == '\0') {
10161                         memmove(q, q + 1, more);
10162                 } else {
10163                         q++;
10164                         if (c == '\n') {
10165                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10166                                 break;
10167                         }
10168                 }
10169
10170                 if (more <= 0) {
10171                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10172                         if (g_parsefile->left_in_line < 0)
10173                                 goto again;
10174                         break;
10175                 }
10176         }
10177         g_parsefile->left_in_buffer = more;
10178
10179         if (vflag) {
10180                 char save = *q;
10181                 *q = '\0';
10182                 out2str(g_parsefile->next_to_pgetc);
10183                 *q = save;
10184         }
10185
10186         pgetc_debug("preadbuffer at %d:%p'%s'",
10187                         g_parsefile->left_in_line,
10188                         g_parsefile->next_to_pgetc,
10189                         g_parsefile->next_to_pgetc);
10190         return (unsigned char)*g_parsefile->next_to_pgetc++;
10191 }
10192
10193 static void
10194 nlprompt(void)
10195 {
10196         g_parsefile->linno++;
10197         setprompt_if(doprompt, 2);
10198 }
10199 static void
10200 nlnoprompt(void)
10201 {
10202         g_parsefile->linno++;
10203         needprompt = doprompt;
10204 }
10205
10206 static int
10207 pgetc(void)
10208 {
10209         int c;
10210
10211         pgetc_debug("pgetc at %d:%p'%s'",
10212                         g_parsefile->left_in_line,
10213                         g_parsefile->next_to_pgetc,
10214                         g_parsefile->next_to_pgetc);
10215         if (g_parsefile->unget)
10216                 return g_parsefile->lastc[--g_parsefile->unget];
10217
10218         if (--g_parsefile->left_in_line >= 0)
10219                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10220         else
10221                 c = preadbuffer();
10222
10223         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10224         g_parsefile->lastc[0] = c;
10225
10226         return c;
10227 }
10228
10229 #if ENABLE_ASH_ALIAS
10230 static int
10231 pgetc_without_PEOA(void)
10232 {
10233         int c;
10234         do {
10235                 pgetc_debug("pgetc at %d:%p'%s'",
10236                                 g_parsefile->left_in_line,
10237                                 g_parsefile->next_to_pgetc,
10238                                 g_parsefile->next_to_pgetc);
10239                 c = pgetc();
10240         } while (c == PEOA);
10241         return c;
10242 }
10243 #else
10244 # define pgetc_without_PEOA() pgetc()
10245 #endif
10246
10247 /*
10248  * Read a line from the script.
10249  */
10250 static char *
10251 pfgets(char *line, int len)
10252 {
10253         char *p = line;
10254         int nleft = len;
10255         int c;
10256
10257         while (--nleft > 0) {
10258                 c = pgetc_without_PEOA();
10259                 if (c == PEOF) {
10260                         if (p == line)
10261                                 return NULL;
10262                         break;
10263                 }
10264                 *p++ = c;
10265                 if (c == '\n')
10266                         break;
10267         }
10268         *p = '\0';
10269         return line;
10270 }
10271
10272 /*
10273  * Undo a call to pgetc.  Only two characters may be pushed back.
10274  * PEOF may be pushed back.
10275  */
10276 static void
10277 pungetc(void)
10278 {
10279         g_parsefile->unget++;
10280 }
10281
10282 /* This one eats backslash+newline */
10283 static int
10284 pgetc_eatbnl(void)
10285 {
10286         int c;
10287
10288         while ((c = pgetc()) == '\\') {
10289                 if (pgetc() != '\n') {
10290                         pungetc();
10291                         break;
10292                 }
10293
10294                 nlprompt();
10295         }
10296
10297         return c;
10298 }
10299
10300 /*
10301  * To handle the "." command, a stack of input files is used.  Pushfile
10302  * adds a new entry to the stack and popfile restores the previous level.
10303  */
10304 static void
10305 pushfile(void)
10306 {
10307         struct parsefile *pf;
10308
10309         pf = ckzalloc(sizeof(*pf));
10310         pf->prev = g_parsefile;
10311         pf->pf_fd = -1;
10312         /*pf->strpush = NULL; - ckzalloc did it */
10313         /*pf->basestrpush.prev = NULL;*/
10314         /*pf->unget = 0;*/
10315         g_parsefile = pf;
10316 }
10317
10318 static void
10319 popfile(void)
10320 {
10321         struct parsefile *pf = g_parsefile;
10322
10323         if (pf == &basepf)
10324                 return;
10325
10326         INT_OFF;
10327         if (pf->pf_fd >= 0)
10328                 close(pf->pf_fd);
10329         free(pf->buf);
10330         while (pf->strpush)
10331                 popstring();
10332         g_parsefile = pf->prev;
10333         free(pf);
10334         INT_ON;
10335 }
10336
10337 /*
10338  * Return to top level.
10339  */
10340 static void
10341 popallfiles(void)
10342 {
10343         while (g_parsefile != &basepf)
10344                 popfile();
10345 }
10346
10347 /*
10348  * Close the file(s) that the shell is reading commands from.  Called
10349  * after a fork is done.
10350  */
10351 static void
10352 closescript(void)
10353 {
10354         popallfiles();
10355         if (g_parsefile->pf_fd > 0) {
10356                 close(g_parsefile->pf_fd);
10357                 g_parsefile->pf_fd = 0;
10358         }
10359 }
10360
10361 /*
10362  * Like setinputfile, but takes an open file descriptor.  Call this with
10363  * interrupts off.
10364  */
10365 static void
10366 setinputfd(int fd, int push)
10367 {
10368         if (push) {
10369                 pushfile();
10370                 g_parsefile->buf = NULL;
10371         }
10372         g_parsefile->pf_fd = fd;
10373         if (g_parsefile->buf == NULL)
10374                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10375         g_parsefile->left_in_buffer = 0;
10376         g_parsefile->left_in_line = 0;
10377         g_parsefile->linno = 1;
10378 }
10379
10380 /*
10381  * Set the input to take input from a file.  If push is set, push the
10382  * old input onto the stack first.
10383  */
10384 static int
10385 setinputfile(const char *fname, int flags)
10386 {
10387         int fd;
10388
10389         INT_OFF;
10390         fd = open(fname, O_RDONLY);
10391         if (fd < 0) {
10392                 if (flags & INPUT_NOFILE_OK)
10393                         goto out;
10394                 exitstatus = 127;
10395                 ash_msg_and_raise_error("can't open '%s'", fname);
10396         }
10397         if (fd < 10)
10398                 fd = savefd(fd);
10399         else
10400                 close_on_exec_on(fd);
10401         setinputfd(fd, flags & INPUT_PUSH_FILE);
10402  out:
10403         INT_ON;
10404         return fd;
10405 }
10406
10407 /*
10408  * Like setinputfile, but takes input from a string.
10409  */
10410 static void
10411 setinputstring(char *string)
10412 {
10413         INT_OFF;
10414         pushfile();
10415         g_parsefile->next_to_pgetc = string;
10416         g_parsefile->left_in_line = strlen(string);
10417         g_parsefile->buf = NULL;
10418         g_parsefile->linno = 1;
10419         INT_ON;
10420 }
10421
10422
10423 /*
10424  * Routines to check for mail.
10425  */
10426
10427 #if ENABLE_ASH_MAIL
10428
10429 /* Hash of mtimes of mailboxes */
10430 static unsigned mailtime_hash;
10431 /* Set if MAIL or MAILPATH is changed. */
10432 static smallint mail_var_path_changed;
10433
10434 /*
10435  * Print appropriate message(s) if mail has arrived.
10436  * If mail_var_path_changed is set,
10437  * then the value of MAIL has mail_var_path_changed,
10438  * so we just update the values.
10439  */
10440 static void
10441 chkmail(void)
10442 {
10443         const char *mpath;
10444         char *p;
10445         char *q;
10446         unsigned new_hash;
10447         struct stackmark smark;
10448         struct stat statb;
10449
10450         setstackmark(&smark);
10451         mpath = mpathset() ? mpathval() : mailval();
10452         new_hash = 0;
10453         for (;;) {
10454                 p = path_advance(&mpath, nullstr);
10455                 if (p == NULL)
10456                         break;
10457                 if (*p == '\0')
10458                         continue;
10459                 for (q = p; *q; q++)
10460                         continue;
10461 #if DEBUG
10462                 if (q[-1] != '/')
10463                         abort();
10464 #endif
10465                 q[-1] = '\0';                   /* delete trailing '/' */
10466                 if (stat(p, &statb) < 0) {
10467                         continue;
10468                 }
10469                 /* Very simplistic "hash": just a sum of all mtimes */
10470                 new_hash += (unsigned)statb.st_mtime;
10471         }
10472         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10473                 if (mailtime_hash != 0)
10474                         out2str("you have mail\n");
10475                 mailtime_hash = new_hash;
10476         }
10477         mail_var_path_changed = 0;
10478         popstackmark(&smark);
10479 }
10480
10481 static void FAST_FUNC
10482 changemail(const char *val UNUSED_PARAM)
10483 {
10484         mail_var_path_changed = 1;
10485 }
10486
10487 #endif /* ASH_MAIL */
10488
10489
10490 /* ============ ??? */
10491
10492 /*
10493  * Set the shell parameters.
10494  */
10495 static void
10496 setparam(char **argv)
10497 {
10498         char **newparam;
10499         char **ap;
10500         int nparam;
10501
10502         for (nparam = 0; argv[nparam]; nparam++)
10503                 continue;
10504         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10505         while (*argv) {
10506                 *ap++ = ckstrdup(*argv++);
10507         }
10508         *ap = NULL;
10509         freeparam(&shellparam);
10510         shellparam.malloced = 1;
10511         shellparam.nparam = nparam;
10512         shellparam.p = newparam;
10513 #if ENABLE_ASH_GETOPTS
10514         shellparam.optind = 1;
10515         shellparam.optoff = -1;
10516 #endif
10517 }
10518
10519 /*
10520  * Process shell options.  The global variable argptr contains a pointer
10521  * to the argument list; we advance it past the options.
10522  *
10523  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10524  * For a non-interactive shell, an error condition encountered
10525  * by a special built-in ... shall cause the shell to write a diagnostic message
10526  * to standard error and exit as shown in the following table:
10527  * Error                                           Special Built-In
10528  * ...
10529  * Utility syntax error (option or operand error)  Shall exit
10530  * ...
10531  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10532  * we see that bash does not do that (set "finishes" with error code 1 instead,
10533  * and shell continues), and people rely on this behavior!
10534  * Testcase:
10535  * set -o barfoo 2>/dev/null
10536  * echo $?
10537  *
10538  * Oh well. Let's mimic that.
10539  */
10540 static int
10541 plus_minus_o(char *name, int val)
10542 {
10543         int i;
10544
10545         if (name) {
10546                 for (i = 0; i < NOPTS; i++) {
10547                         if (strcmp(name, optnames(i)) == 0) {
10548                                 optlist[i] = val;
10549                                 return 0;
10550                         }
10551                 }
10552                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10553                 return 1;
10554         }
10555         for (i = 0; i < NOPTS; i++) {
10556                 if (val) {
10557                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10558                 } else {
10559                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10560                 }
10561         }
10562         return 0;
10563 }
10564 static void
10565 setoption(int flag, int val)
10566 {
10567         int i;
10568
10569         for (i = 0; i < NOPTS; i++) {
10570                 if (optletters(i) == flag) {
10571                         optlist[i] = val;
10572                         return;
10573                 }
10574         }
10575         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10576         /* NOTREACHED */
10577 }
10578 static int
10579 options(int cmdline)
10580 {
10581         char *p;
10582         int val;
10583         int c;
10584
10585         if (cmdline)
10586                 minusc = NULL;
10587         while ((p = *argptr) != NULL) {
10588                 c = *p++;
10589                 if (c != '-' && c != '+')
10590                         break;
10591                 argptr++;
10592                 val = 0; /* val = 0 if c == '+' */
10593                 if (c == '-') {
10594                         val = 1;
10595                         if (p[0] == '\0' || LONE_DASH(p)) {
10596                                 if (!cmdline) {
10597                                         /* "-" means turn off -x and -v */
10598                                         if (p[0] == '\0')
10599                                                 xflag = vflag = 0;
10600                                         /* "--" means reset params */
10601                                         else if (*argptr == NULL)
10602                                                 setparam(argptr);
10603                                 }
10604                                 break;    /* "-" or "--" terminates options */
10605                         }
10606                 }
10607                 /* first char was + or - */
10608                 while ((c = *p++) != '\0') {
10609                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10610                         if (c == 'c' && cmdline) {
10611                                 minusc = p;     /* command is after shell args */
10612                         } else if (c == 'o') {
10613                                 if (plus_minus_o(*argptr, val)) {
10614                                         /* it already printed err message */
10615                                         return 1; /* error */
10616                                 }
10617                                 if (*argptr)
10618                                         argptr++;
10619                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10620                                 isloginsh = 1;
10621                         /* bash does not accept +-login, we also won't */
10622                         } else if (cmdline && val && (c == '-')) { /* long options */
10623                                 if (strcmp(p, "login") == 0)
10624                                         isloginsh = 1;
10625                                 break;
10626                         } else {
10627                                 setoption(c, val);
10628                         }
10629                 }
10630         }
10631         return 0;
10632 }
10633
10634 /*
10635  * The shift builtin command.
10636  */
10637 static int FAST_FUNC
10638 shiftcmd(int argc UNUSED_PARAM, char **argv)
10639 {
10640         int n;
10641         char **ap1, **ap2;
10642
10643         n = 1;
10644         if (argv[1])
10645                 n = number(argv[1]);
10646         if (n > shellparam.nparam)
10647                 n = 0; /* bash compat, was = shellparam.nparam; */
10648         INT_OFF;
10649         shellparam.nparam -= n;
10650         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10651                 if (shellparam.malloced)
10652                         free(*ap1);
10653         }
10654         ap2 = shellparam.p;
10655         while ((*ap2++ = *ap1++) != NULL)
10656                 continue;
10657 #if ENABLE_ASH_GETOPTS
10658         shellparam.optind = 1;
10659         shellparam.optoff = -1;
10660 #endif
10661         INT_ON;
10662         return 0;
10663 }
10664
10665 /*
10666  * POSIX requires that 'set' (but not export or readonly) output the
10667  * variables in lexicographic order - by the locale's collating order (sigh).
10668  * Maybe we could keep them in an ordered balanced binary tree
10669  * instead of hashed lists.
10670  * For now just roll 'em through qsort for printing...
10671  */
10672 static int
10673 showvars(const char *sep_prefix, int on, int off)
10674 {
10675         const char *sep;
10676         char **ep, **epend;
10677
10678         ep = listvars(on, off, &epend);
10679         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10680
10681         sep = *sep_prefix ? " " : sep_prefix;
10682
10683         for (; ep < epend; ep++) {
10684                 const char *p;
10685                 const char *q;
10686
10687                 p = strchrnul(*ep, '=');
10688                 q = nullstr;
10689                 if (*p)
10690                         q = single_quote(++p);
10691                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10692         }
10693         return 0;
10694 }
10695
10696 /*
10697  * The set command builtin.
10698  */
10699 static int FAST_FUNC
10700 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10701 {
10702         int retval;
10703
10704         if (!argv[1])
10705                 return showvars(nullstr, 0, VUNSET);
10706
10707         INT_OFF;
10708         retval = options(/*cmdline:*/ 0);
10709         if (retval == 0) { /* if no parse error... */
10710                 optschanged();
10711                 if (*argptr != NULL) {
10712                         setparam(argptr);
10713                 }
10714         }
10715         INT_ON;
10716         return retval;
10717 }
10718
10719 #if ENABLE_ASH_RANDOM_SUPPORT
10720 static void FAST_FUNC
10721 change_random(const char *value)
10722 {
10723         uint32_t t;
10724
10725         if (value == NULL) {
10726                 /* "get", generate */
10727                 t = next_random(&random_gen);
10728                 /* set without recursion */
10729                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10730                 vrandom.flags &= ~VNOFUNC;
10731         } else {
10732                 /* set/reset */
10733                 t = strtoul(value, NULL, 10);
10734                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10735         }
10736 }
10737 #endif
10738
10739 #if ENABLE_ASH_GETOPTS
10740 static int
10741 getopts(char *optstr, char *optvar, char **optfirst)
10742 {
10743         char *p, *q;
10744         char c = '?';
10745         int done = 0;
10746         char sbuf[2];
10747         char **optnext;
10748         int ind = shellparam.optind;
10749         int off = shellparam.optoff;
10750
10751         sbuf[1] = '\0';
10752
10753         shellparam.optind = -1;
10754         optnext = optfirst + ind - 1;
10755
10756         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10757                 p = NULL;
10758         else
10759                 p = optnext[-1] + off;
10760         if (p == NULL || *p == '\0') {
10761                 /* Current word is done, advance */
10762                 p = *optnext;
10763                 if (p == NULL || *p != '-' || *++p == '\0') {
10764  atend:
10765                         p = NULL;
10766                         done = 1;
10767                         goto out;
10768                 }
10769                 optnext++;
10770                 if (LONE_DASH(p))        /* check for "--" */
10771                         goto atend;
10772         }
10773
10774         c = *p++;
10775         for (q = optstr; *q != c;) {
10776                 if (*q == '\0') {
10777                         if (optstr[0] == ':') {
10778                                 sbuf[0] = c;
10779                                 /*sbuf[1] = '\0'; - already is */
10780                                 setvar0("OPTARG", sbuf);
10781                         } else {
10782                                 fprintf(stderr, "Illegal option -%c\n", c);
10783                                 unsetvar("OPTARG");
10784                         }
10785                         c = '?';
10786                         goto out;
10787                 }
10788                 if (*++q == ':')
10789                         q++;
10790         }
10791
10792         if (*++q == ':') {
10793                 if (*p == '\0' && (p = *optnext) == NULL) {
10794                         if (optstr[0] == ':') {
10795                                 sbuf[0] = c;
10796                                 /*sbuf[1] = '\0'; - already is */
10797                                 setvar0("OPTARG", sbuf);
10798                                 c = ':';
10799                         } else {
10800                                 fprintf(stderr, "No arg for -%c option\n", c);
10801                                 unsetvar("OPTARG");
10802                                 c = '?';
10803                         }
10804                         goto out;
10805                 }
10806
10807                 if (p == *optnext)
10808                         optnext++;
10809                 setvar0("OPTARG", p);
10810                 p = NULL;
10811         } else
10812                 setvar0("OPTARG", nullstr);
10813  out:
10814         ind = optnext - optfirst + 1;
10815         setvar("OPTIND", itoa(ind), VNOFUNC);
10816         sbuf[0] = c;
10817         /*sbuf[1] = '\0'; - already is */
10818         setvar0(optvar, sbuf);
10819
10820         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10821         shellparam.optind = ind;
10822
10823         return done;
10824 }
10825
10826 /*
10827  * The getopts builtin.  Shellparam.optnext points to the next argument
10828  * to be processed.  Shellparam.optptr points to the next character to
10829  * be processed in the current argument.  If shellparam.optnext is NULL,
10830  * then it's the first time getopts has been called.
10831  */
10832 static int FAST_FUNC
10833 getoptscmd(int argc, char **argv)
10834 {
10835         char **optbase;
10836
10837         if (argc < 3)
10838                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10839         if (argc == 3) {
10840                 optbase = shellparam.p;
10841                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10842                         shellparam.optind = 1;
10843                         shellparam.optoff = -1;
10844                 }
10845         } else {
10846                 optbase = &argv[3];
10847                 if ((unsigned)shellparam.optind > argc - 2) {
10848                         shellparam.optind = 1;
10849                         shellparam.optoff = -1;
10850                 }
10851         }
10852
10853         return getopts(argv[1], argv[2], optbase);
10854 }
10855 #endif /* ASH_GETOPTS */
10856
10857
10858 /* ============ Shell parser */
10859
10860 struct heredoc {
10861         struct heredoc *next;   /* next here document in list */
10862         union node *here;       /* redirection node */
10863         char *eofmark;          /* string indicating end of input */
10864         smallint striptabs;     /* if set, strip leading tabs */
10865 };
10866
10867 static smallint tokpushback;           /* last token pushed back */
10868 static smallint quoteflag;             /* set if (part of) last token was quoted */
10869 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10870 static struct heredoc *heredoclist;    /* list of here documents to read */
10871 static char *wordtext;                 /* text of last word returned by readtoken */
10872 static struct nodelist *backquotelist;
10873 static union node *redirnode;
10874 static struct heredoc *heredoc;
10875
10876 static const char *
10877 tokname(char *buf, int tok)
10878 {
10879         if (tok < TSEMI)
10880                 return tokname_array[tok];
10881         sprintf(buf, "\"%s\"", tokname_array[tok]);
10882         return buf;
10883 }
10884
10885 /* raise_error_unexpected_syntax:
10886  * Called when an unexpected token is read during the parse.  The argument
10887  * is the token that is expected, or -1 if more than one type of token can
10888  * occur at this point.
10889  */
10890 static void raise_error_unexpected_syntax(int) NORETURN;
10891 static void
10892 raise_error_unexpected_syntax(int token)
10893 {
10894         char msg[64];
10895         char buf[16];
10896         int l;
10897
10898         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10899         if (token >= 0)
10900                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10901         raise_error_syntax(msg);
10902         /* NOTREACHED */
10903 }
10904
10905 #define EOFMARKLEN 79
10906
10907 /* parsing is heavily cross-recursive, need these forward decls */
10908 static union node *andor(void);
10909 static union node *pipeline(void);
10910 static union node *parse_command(void);
10911 static void parseheredoc(void);
10912 static int peektoken(void);
10913 static int readtoken(void);
10914
10915 static union node *
10916 list(int nlflag)
10917 {
10918         union node *n1, *n2, *n3;
10919         int tok;
10920
10921         n1 = NULL;
10922         for (;;) {
10923                 switch (peektoken()) {
10924                 case TNL:
10925                         if (!(nlflag & 1))
10926                                 break;
10927                         parseheredoc();
10928                         return n1;
10929
10930                 case TEOF:
10931                         if (!n1 && (nlflag & 1))
10932                                 n1 = NODE_EOF;
10933                         parseheredoc();
10934                         return n1;
10935                 }
10936
10937                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10938                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10939                         return n1;
10940                 nlflag |= 2;
10941
10942                 n2 = andor();
10943                 tok = readtoken();
10944                 if (tok == TBACKGND) {
10945                         if (n2->type == NPIPE) {
10946                                 n2->npipe.pipe_backgnd = 1;
10947                         } else {
10948                                 if (n2->type != NREDIR) {
10949                                         n3 = stzalloc(sizeof(struct nredir));
10950                                         n3->nredir.n = n2;
10951                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10952                                         n2 = n3;
10953                                 }
10954                                 n2->type = NBACKGND;
10955                         }
10956                 }
10957                 if (n1 == NULL) {
10958                         n1 = n2;
10959                 } else {
10960                         n3 = stzalloc(sizeof(struct nbinary));
10961                         n3->type = NSEMI;
10962                         n3->nbinary.ch1 = n1;
10963                         n3->nbinary.ch2 = n2;
10964                         n1 = n3;
10965                 }
10966                 switch (tok) {
10967                 case TNL:
10968                 case TEOF:
10969                         tokpushback = 1;
10970                         /* fall through */
10971                 case TBACKGND:
10972                 case TSEMI:
10973                         break;
10974                 default:
10975                         if ((nlflag & 1))
10976                                 raise_error_unexpected_syntax(-1);
10977                         tokpushback = 1;
10978                         return n1;
10979                 }
10980         }
10981 }
10982
10983 static union node *
10984 andor(void)
10985 {
10986         union node *n1, *n2, *n3;
10987         int t;
10988
10989         n1 = pipeline();
10990         for (;;) {
10991                 t = readtoken();
10992                 if (t == TAND) {
10993                         t = NAND;
10994                 } else if (t == TOR) {
10995                         t = NOR;
10996                 } else {
10997                         tokpushback = 1;
10998                         return n1;
10999                 }
11000                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11001                 n2 = pipeline();
11002                 n3 = stzalloc(sizeof(struct nbinary));
11003                 n3->type = t;
11004                 n3->nbinary.ch1 = n1;
11005                 n3->nbinary.ch2 = n2;
11006                 n1 = n3;
11007         }
11008 }
11009
11010 static union node *
11011 pipeline(void)
11012 {
11013         union node *n1, *n2, *pipenode;
11014         struct nodelist *lp, *prev;
11015         int negate;
11016
11017         negate = 0;
11018         TRACE(("pipeline: entered\n"));
11019         if (readtoken() == TNOT) {
11020                 negate = !negate;
11021                 checkkwd = CHKKWD | CHKALIAS;
11022         } else
11023                 tokpushback = 1;
11024         n1 = parse_command();
11025         if (readtoken() == TPIPE) {
11026                 pipenode = stzalloc(sizeof(struct npipe));
11027                 pipenode->type = NPIPE;
11028                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11029                 lp = stzalloc(sizeof(struct nodelist));
11030                 pipenode->npipe.cmdlist = lp;
11031                 lp->n = n1;
11032                 do {
11033                         prev = lp;
11034                         lp = stzalloc(sizeof(struct nodelist));
11035                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11036                         lp->n = parse_command();
11037                         prev->next = lp;
11038                 } while (readtoken() == TPIPE);
11039                 lp->next = NULL;
11040                 n1 = pipenode;
11041         }
11042         tokpushback = 1;
11043         if (negate) {
11044                 n2 = stzalloc(sizeof(struct nnot));
11045                 n2->type = NNOT;
11046                 n2->nnot.com = n1;
11047                 return n2;
11048         }
11049         return n1;
11050 }
11051
11052 static union node *
11053 makename(void)
11054 {
11055         union node *n;
11056
11057         n = stzalloc(sizeof(struct narg));
11058         n->type = NARG;
11059         /*n->narg.next = NULL; - stzalloc did it */
11060         n->narg.text = wordtext;
11061         n->narg.backquote = backquotelist;
11062         return n;
11063 }
11064
11065 static void
11066 fixredir(union node *n, const char *text, int err)
11067 {
11068         int fd;
11069
11070         TRACE(("Fix redir %s %d\n", text, err));
11071         if (!err)
11072                 n->ndup.vname = NULL;
11073
11074         fd = bb_strtou(text, NULL, 10);
11075         if (!errno && fd >= 0)
11076                 n->ndup.dupfd = fd;
11077         else if (LONE_DASH(text))
11078                 n->ndup.dupfd = -1;
11079         else {
11080                 if (err)
11081                         raise_error_syntax("bad fd number");
11082                 n->ndup.vname = makename();
11083         }
11084 }
11085
11086 /*
11087  * Returns true if the text contains nothing to expand (no dollar signs
11088  * or backquotes).
11089  */
11090 static int
11091 noexpand(const char *text)
11092 {
11093         unsigned char c;
11094
11095         while ((c = *text++) != '\0') {
11096                 if (c == CTLQUOTEMARK)
11097                         continue;
11098                 if (c == CTLESC)
11099                         text++;
11100                 else if (SIT(c, BASESYNTAX) == CCTL)
11101                         return 0;
11102         }
11103         return 1;
11104 }
11105
11106 static void
11107 parsefname(void)
11108 {
11109         union node *n = redirnode;
11110
11111         if (readtoken() != TWORD)
11112                 raise_error_unexpected_syntax(-1);
11113         if (n->type == NHERE) {
11114                 struct heredoc *here = heredoc;
11115                 struct heredoc *p;
11116                 int i;
11117
11118                 if (quoteflag == 0)
11119                         n->type = NXHERE;
11120                 TRACE(("Here document %d\n", n->type));
11121                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11122                         raise_error_syntax("illegal eof marker for << redirection");
11123                 rmescapes(wordtext, 0);
11124                 here->eofmark = wordtext;
11125                 here->next = NULL;
11126                 if (heredoclist == NULL)
11127                         heredoclist = here;
11128                 else {
11129                         for (p = heredoclist; p->next; p = p->next)
11130                                 continue;
11131                         p->next = here;
11132                 }
11133         } else if (n->type == NTOFD || n->type == NFROMFD) {
11134                 fixredir(n, wordtext, 0);
11135         } else {
11136                 n->nfile.fname = makename();
11137         }
11138 }
11139
11140 static union node *
11141 simplecmd(void)
11142 {
11143         union node *args, **app;
11144         union node *n = NULL;
11145         union node *vars, **vpp;
11146         union node **rpp, *redir;
11147         int savecheckkwd;
11148 #if BASH_TEST2
11149         smallint double_brackets_flag = 0;
11150 #endif
11151         IF_BASH_FUNCTION(smallint function_flag = 0;)
11152
11153         args = NULL;
11154         app = &args;
11155         vars = NULL;
11156         vpp = &vars;
11157         redir = NULL;
11158         rpp = &redir;
11159
11160         savecheckkwd = CHKALIAS;
11161         for (;;) {
11162                 int t;
11163                 checkkwd = savecheckkwd;
11164                 t = readtoken();
11165                 switch (t) {
11166 #if BASH_FUNCTION
11167                 case TFUNCTION:
11168                         if (peektoken() != TWORD)
11169                                 raise_error_unexpected_syntax(TWORD);
11170                         function_flag = 1;
11171                         break;
11172 #endif
11173 #if BASH_TEST2
11174                 case TAND: /* "&&" */
11175                 case TOR: /* "||" */
11176                         if (!double_brackets_flag) {
11177                                 tokpushback = 1;
11178                                 goto out;
11179                         }
11180                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11181 #endif
11182                 case TWORD:
11183                         n = stzalloc(sizeof(struct narg));
11184                         n->type = NARG;
11185                         /*n->narg.next = NULL; - stzalloc did it */
11186                         n->narg.text = wordtext;
11187 #if BASH_TEST2
11188                         if (strcmp("[[", wordtext) == 0)
11189                                 double_brackets_flag = 1;
11190                         else if (strcmp("]]", wordtext) == 0)
11191                                 double_brackets_flag = 0;
11192 #endif
11193                         n->narg.backquote = backquotelist;
11194                         if (savecheckkwd && isassignment(wordtext)) {
11195                                 *vpp = n;
11196                                 vpp = &n->narg.next;
11197                         } else {
11198                                 *app = n;
11199                                 app = &n->narg.next;
11200                                 savecheckkwd = 0;
11201                         }
11202 #if BASH_FUNCTION
11203                         if (function_flag) {
11204                                 checkkwd = CHKNL | CHKKWD;
11205                                 switch (peektoken()) {
11206                                 case TBEGIN:
11207                                 case TIF:
11208                                 case TCASE:
11209                                 case TUNTIL:
11210                                 case TWHILE:
11211                                 case TFOR:
11212                                         goto do_func;
11213                                 case TLP:
11214                                         function_flag = 0;
11215                                         break;
11216                                 case TWORD:
11217                                         if (strcmp("[[", wordtext) == 0)
11218                                                 goto do_func;
11219                                         /* fall through */
11220                                 default:
11221                                         raise_error_unexpected_syntax(-1);
11222                                 }
11223                         }
11224 #endif
11225                         break;
11226                 case TREDIR:
11227                         *rpp = n = redirnode;
11228                         rpp = &n->nfile.next;
11229                         parsefname();   /* read name of redirection file */
11230                         break;
11231                 case TLP:
11232  IF_BASH_FUNCTION(do_func:)
11233                         if (args && app == &args->narg.next
11234                          && !vars && !redir
11235                         ) {
11236                                 struct builtincmd *bcmd;
11237                                 const char *name;
11238
11239                                 /* We have a function */
11240                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11241                                         raise_error_unexpected_syntax(TRP);
11242                                 name = n->narg.text;
11243                                 if (!goodname(name)
11244                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11245                                 ) {
11246                                         raise_error_syntax("bad function name");
11247                                 }
11248                                 n->type = NDEFUN;
11249                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11250                                 n->narg.next = parse_command();
11251                                 return n;
11252                         }
11253                         IF_BASH_FUNCTION(function_flag = 0;)
11254                         /* fall through */
11255                 default:
11256                         tokpushback = 1;
11257                         goto out;
11258                 }
11259         }
11260  out:
11261         *app = NULL;
11262         *vpp = NULL;
11263         *rpp = NULL;
11264         n = stzalloc(sizeof(struct ncmd));
11265         n->type = NCMD;
11266         n->ncmd.args = args;
11267         n->ncmd.assign = vars;
11268         n->ncmd.redirect = redir;
11269         return n;
11270 }
11271
11272 static union node *
11273 parse_command(void)
11274 {
11275         union node *n1, *n2;
11276         union node *ap, **app;
11277         union node *cp, **cpp;
11278         union node *redir, **rpp;
11279         union node **rpp2;
11280         int t;
11281
11282         redir = NULL;
11283         rpp2 = &redir;
11284
11285         switch (readtoken()) {
11286         default:
11287                 raise_error_unexpected_syntax(-1);
11288                 /* NOTREACHED */
11289         case TIF:
11290                 n1 = stzalloc(sizeof(struct nif));
11291                 n1->type = NIF;
11292                 n1->nif.test = list(0);
11293                 if (readtoken() != TTHEN)
11294                         raise_error_unexpected_syntax(TTHEN);
11295                 n1->nif.ifpart = list(0);
11296                 n2 = n1;
11297                 while (readtoken() == TELIF) {
11298                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11299                         n2 = n2->nif.elsepart;
11300                         n2->type = NIF;
11301                         n2->nif.test = list(0);
11302                         if (readtoken() != TTHEN)
11303                                 raise_error_unexpected_syntax(TTHEN);
11304                         n2->nif.ifpart = list(0);
11305                 }
11306                 if (lasttoken == TELSE)
11307                         n2->nif.elsepart = list(0);
11308                 else {
11309                         n2->nif.elsepart = NULL;
11310                         tokpushback = 1;
11311                 }
11312                 t = TFI;
11313                 break;
11314         case TWHILE:
11315         case TUNTIL: {
11316                 int got;
11317                 n1 = stzalloc(sizeof(struct nbinary));
11318                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11319                 n1->nbinary.ch1 = list(0);
11320                 got = readtoken();
11321                 if (got != TDO) {
11322                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11323                                         got == TWORD ? wordtext : ""));
11324                         raise_error_unexpected_syntax(TDO);
11325                 }
11326                 n1->nbinary.ch2 = list(0);
11327                 t = TDONE;
11328                 break;
11329         }
11330         case TFOR:
11331                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11332                         raise_error_syntax("bad for loop variable");
11333                 n1 = stzalloc(sizeof(struct nfor));
11334                 n1->type = NFOR;
11335                 n1->nfor.var = wordtext;
11336                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11337                 if (readtoken() == TIN) {
11338                         app = &ap;
11339                         while (readtoken() == TWORD) {
11340                                 n2 = stzalloc(sizeof(struct narg));
11341                                 n2->type = NARG;
11342                                 /*n2->narg.next = NULL; - stzalloc did it */
11343                                 n2->narg.text = wordtext;
11344                                 n2->narg.backquote = backquotelist;
11345                                 *app = n2;
11346                                 app = &n2->narg.next;
11347                         }
11348                         *app = NULL;
11349                         n1->nfor.args = ap;
11350                         if (lasttoken != TNL && lasttoken != TSEMI)
11351                                 raise_error_unexpected_syntax(-1);
11352                 } else {
11353                         n2 = stzalloc(sizeof(struct narg));
11354                         n2->type = NARG;
11355                         /*n2->narg.next = NULL; - stzalloc did it */
11356                         n2->narg.text = (char *)dolatstr;
11357                         /*n2->narg.backquote = NULL;*/
11358                         n1->nfor.args = n2;
11359                         /*
11360                          * Newline or semicolon here is optional (but note
11361                          * that the original Bourne shell only allowed NL).
11362                          */
11363                         if (lasttoken != TSEMI)
11364                                 tokpushback = 1;
11365                 }
11366                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11367                 if (readtoken() != TDO)
11368                         raise_error_unexpected_syntax(TDO);
11369                 n1->nfor.body = list(0);
11370                 t = TDONE;
11371                 break;
11372         case TCASE:
11373                 n1 = stzalloc(sizeof(struct ncase));
11374                 n1->type = NCASE;
11375                 if (readtoken() != TWORD)
11376                         raise_error_unexpected_syntax(TWORD);
11377                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11378                 n2->type = NARG;
11379                 /*n2->narg.next = NULL; - stzalloc did it */
11380                 n2->narg.text = wordtext;
11381                 n2->narg.backquote = backquotelist;
11382                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11383                 if (readtoken() != TIN)
11384                         raise_error_unexpected_syntax(TIN);
11385                 cpp = &n1->ncase.cases;
11386  next_case:
11387                 checkkwd = CHKNL | CHKKWD;
11388                 t = readtoken();
11389                 while (t != TESAC) {
11390                         if (lasttoken == TLP)
11391                                 readtoken();
11392                         *cpp = cp = stzalloc(sizeof(struct nclist));
11393                         cp->type = NCLIST;
11394                         app = &cp->nclist.pattern;
11395                         for (;;) {
11396                                 *app = ap = stzalloc(sizeof(struct narg));
11397                                 ap->type = NARG;
11398                                 /*ap->narg.next = NULL; - stzalloc did it */
11399                                 ap->narg.text = wordtext;
11400                                 ap->narg.backquote = backquotelist;
11401                                 if (readtoken() != TPIPE)
11402                                         break;
11403                                 app = &ap->narg.next;
11404                                 readtoken();
11405                         }
11406                         //ap->narg.next = NULL;
11407                         if (lasttoken != TRP)
11408                                 raise_error_unexpected_syntax(TRP);
11409                         cp->nclist.body = list(2);
11410
11411                         cpp = &cp->nclist.next;
11412
11413                         checkkwd = CHKNL | CHKKWD;
11414                         t = readtoken();
11415                         if (t != TESAC) {
11416                                 if (t != TENDCASE)
11417                                         raise_error_unexpected_syntax(TENDCASE);
11418                                 goto next_case;
11419                         }
11420                 }
11421                 *cpp = NULL;
11422                 goto redir;
11423         case TLP:
11424                 n1 = stzalloc(sizeof(struct nredir));
11425                 n1->type = NSUBSHELL;
11426                 n1->nredir.n = list(0);
11427                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11428                 t = TRP;
11429                 break;
11430         case TBEGIN:
11431                 n1 = list(0);
11432                 t = TEND;
11433                 break;
11434         IF_BASH_FUNCTION(case TFUNCTION:)
11435         case TWORD:
11436         case TREDIR:
11437                 tokpushback = 1;
11438                 return simplecmd();
11439         }
11440
11441         if (readtoken() != t)
11442                 raise_error_unexpected_syntax(t);
11443
11444  redir:
11445         /* Now check for redirection which may follow command */
11446         checkkwd = CHKKWD | CHKALIAS;
11447         rpp = rpp2;
11448         while (readtoken() == TREDIR) {
11449                 *rpp = n2 = redirnode;
11450                 rpp = &n2->nfile.next;
11451                 parsefname();
11452         }
11453         tokpushback = 1;
11454         *rpp = NULL;
11455         if (redir) {
11456                 if (n1->type != NSUBSHELL) {
11457                         n2 = stzalloc(sizeof(struct nredir));
11458                         n2->type = NREDIR;
11459                         n2->nredir.n = n1;
11460                         n1 = n2;
11461                 }
11462                 n1->nredir.redirect = redir;
11463         }
11464         return n1;
11465 }
11466
11467 #if BASH_DOLLAR_SQUOTE
11468 static int
11469 decode_dollar_squote(void)
11470 {
11471         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11472         int c, cnt;
11473         char *p;
11474         char buf[4];
11475
11476         c = pgetc();
11477         p = strchr(C_escapes, c);
11478         if (p) {
11479                 buf[0] = c;
11480                 p = buf;
11481                 cnt = 3;
11482                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11483                         do {
11484                                 c = pgetc();
11485                                 *++p = c;
11486                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11487                         pungetc();
11488                 } else if (c == 'x') { /* \xHH */
11489                         do {
11490                                 c = pgetc();
11491                                 *++p = c;
11492                         } while (isxdigit(c) && --cnt);
11493                         pungetc();
11494                         if (cnt == 3) { /* \x but next char is "bad" */
11495                                 c = 'x';
11496                                 goto unrecognized;
11497                         }
11498                 } else { /* simple seq like \\ or \t */
11499                         p++;
11500                 }
11501                 *p = '\0';
11502                 p = buf;
11503                 c = bb_process_escape_sequence((void*)&p);
11504         } else { /* unrecognized "\z": print both chars unless ' or " */
11505                 if (c != '\'' && c != '"') {
11506  unrecognized:
11507                         c |= 0x100; /* "please encode \, then me" */
11508                 }
11509         }
11510         return c;
11511 }
11512 #endif
11513
11514 /*
11515  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11516  * is not NULL, read a here document.  In the latter case, eofmark is the
11517  * word which marks the end of the document and striptabs is true if
11518  * leading tabs should be stripped from the document.  The argument c
11519  * is the first character of the input token or document.
11520  *
11521  * Because C does not have internal subroutines, I have simulated them
11522  * using goto's to implement the subroutine linkage.  The following macros
11523  * will run code that appears at the end of readtoken1.
11524  */
11525 #define CHECKEND()      {goto checkend; checkend_return:;}
11526 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11527 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11528 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11529 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11530 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11531 static int
11532 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11533 {
11534         /* NB: syntax parameter fits into smallint */
11535         /* c parameter is an unsigned char or PEOF or PEOA */
11536         char *out;
11537         size_t len;
11538         char line[EOFMARKLEN + 1];
11539         struct nodelist *bqlist;
11540         smallint quotef;
11541         smallint dblquote;
11542         smallint oldstyle;
11543         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11544 #if ENABLE_ASH_EXPAND_PRMT
11545         smallint pssyntax;   /* we are expanding a prompt string */
11546 #endif
11547         int varnest;         /* levels of variables expansion */
11548         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11549         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11550         int dqvarnest;       /* levels of variables expansion within double quotes */
11551
11552         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11553
11554         startlinno = g_parsefile->linno;
11555         bqlist = NULL;
11556         quotef = 0;
11557         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11558 #if ENABLE_ASH_EXPAND_PRMT
11559         pssyntax = (syntax == PSSYNTAX);
11560         if (pssyntax)
11561                 syntax = DQSYNTAX;
11562 #endif
11563         dblquote = (syntax == DQSYNTAX);
11564         varnest = 0;
11565         IF_FEATURE_SH_MATH(arinest = 0;)
11566         IF_FEATURE_SH_MATH(parenlevel = 0;)
11567         dqvarnest = 0;
11568
11569         STARTSTACKSTR(out);
11570  loop:
11571         /* For each line, until end of word */
11572         CHECKEND();     /* set c to PEOF if at end of here document */
11573         for (;;) {      /* until end of line or end of word */
11574                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11575                 switch (SIT(c, syntax)) {
11576                 case CNL:       /* '\n' */
11577                         if (syntax == BASESYNTAX)
11578                                 goto endword;   /* exit outer loop */
11579                         USTPUTC(c, out);
11580                         nlprompt();
11581                         c = pgetc();
11582                         goto loop;              /* continue outer loop */
11583                 case CWORD:
11584                         USTPUTC(c, out);
11585                         break;
11586                 case CCTL:
11587 #if BASH_DOLLAR_SQUOTE
11588                         if (c == '\\' && bash_dollar_squote) {
11589                                 c = decode_dollar_squote();
11590                                 if (c == '\0') {
11591                                         /* skip $'\000', $'\x00' (like bash) */
11592                                         break;
11593                                 }
11594                                 if (c & 0x100) {
11595                                         /* Unknown escape. Encode as '\z' */
11596                                         c = (unsigned char)c;
11597                                         if (eofmark == NULL || dblquote)
11598                                                 USTPUTC(CTLESC, out);
11599                                         USTPUTC('\\', out);
11600                                 }
11601                         }
11602 #endif
11603                         if (eofmark == NULL || dblquote)
11604                                 USTPUTC(CTLESC, out);
11605                         USTPUTC(c, out);
11606                         break;
11607                 case CBACK:     /* backslash */
11608                         c = pgetc_without_PEOA();
11609                         if (c == PEOF) {
11610                                 USTPUTC(CTLESC, out);
11611                                 USTPUTC('\\', out);
11612                                 pungetc();
11613                         } else if (c == '\n') {
11614                                 nlprompt();
11615                         } else {
11616 #if ENABLE_ASH_EXPAND_PRMT
11617                                 if (c == '$' && pssyntax) {
11618                                         USTPUTC(CTLESC, out);
11619                                         USTPUTC('\\', out);
11620                                 }
11621 #endif
11622                                 /* Backslash is retained if we are in "str" and next char isn't special */
11623                                 if (dblquote
11624                                  && c != '\\'
11625                                  && c != '`'
11626                                  && c != '$'
11627                                  && (c != '"' || eofmark != NULL)
11628                                 ) {
11629                                         USTPUTC('\\', out);
11630                                 }
11631                                 USTPUTC(CTLESC, out);
11632                                 USTPUTC(c, out);
11633                                 quotef = 1;
11634                         }
11635                         break;
11636                 case CSQUOTE:
11637                         syntax = SQSYNTAX;
11638  quotemark:
11639                         if (eofmark == NULL) {
11640                                 USTPUTC(CTLQUOTEMARK, out);
11641                         }
11642                         break;
11643                 case CDQUOTE:
11644                         syntax = DQSYNTAX;
11645                         dblquote = 1;
11646                         goto quotemark;
11647                 case CENDQUOTE:
11648                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11649                         if (eofmark != NULL && varnest == 0) {
11650                                 USTPUTC(c, out);
11651                         } else {
11652                                 if (dqvarnest == 0) {
11653                                         syntax = BASESYNTAX;
11654                                         dblquote = 0;
11655                                 }
11656                                 quotef = 1;
11657                                 goto quotemark;
11658                         }
11659                         break;
11660                 case CVAR:      /* '$' */
11661                         PARSESUB();             /* parse substitution */
11662                         break;
11663                 case CENDVAR:   /* '}' */
11664                         if (varnest > 0) {
11665                                 varnest--;
11666                                 if (dqvarnest > 0) {
11667                                         dqvarnest--;
11668                                 }
11669                                 c = CTLENDVAR;
11670                         }
11671                         USTPUTC(c, out);
11672                         break;
11673 #if ENABLE_FEATURE_SH_MATH
11674                 case CLP:       /* '(' in arithmetic */
11675                         parenlevel++;
11676                         USTPUTC(c, out);
11677                         break;
11678                 case CRP:       /* ')' in arithmetic */
11679                         if (parenlevel > 0) {
11680                                 parenlevel--;
11681                         } else {
11682                                 if (pgetc_eatbnl() == ')') {
11683                                         c = CTLENDARI;
11684                                         if (--arinest == 0) {
11685                                                 syntax = prevsyntax;
11686                                         }
11687                                 } else {
11688                                         /*
11689                                          * unbalanced parens
11690                                          * (don't 2nd guess - no error)
11691                                          */
11692                                         pungetc();
11693                                 }
11694                         }
11695                         USTPUTC(c, out);
11696                         break;
11697 #endif
11698                 case CBQUOTE:   /* '`' */
11699                         PARSEBACKQOLD();
11700                         break;
11701                 case CENDFILE:
11702                         goto endword;           /* exit outer loop */
11703                 case CIGN:
11704                         break;
11705                 default:
11706                         if (varnest == 0) {
11707 #if BASH_REDIR_OUTPUT
11708                                 if (c == '&') {
11709 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11710                                         if (pgetc() == '>')
11711                                                 c = 0x100 + '>'; /* flag &> */
11712                                         pungetc();
11713                                 }
11714 #endif
11715                                 goto endword;   /* exit outer loop */
11716                         }
11717                         IF_ASH_ALIAS(if (c != PEOA))
11718                                 USTPUTC(c, out);
11719                 }
11720                 c = pgetc();
11721         } /* for (;;) */
11722  endword:
11723
11724 #if ENABLE_FEATURE_SH_MATH
11725         if (syntax == ARISYNTAX)
11726                 raise_error_syntax("missing '))'");
11727 #endif
11728         if (syntax != BASESYNTAX && eofmark == NULL)
11729                 raise_error_syntax("unterminated quoted string");
11730         if (varnest != 0) {
11731                 startlinno = g_parsefile->linno;
11732                 /* { */
11733                 raise_error_syntax("missing '}'");
11734         }
11735         USTPUTC('\0', out);
11736         len = out - (char *)stackblock();
11737         out = stackblock();
11738         if (eofmark == NULL) {
11739                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11740                  && quotef == 0
11741                 ) {
11742                         if (isdigit_str9(out)) {
11743                                 PARSEREDIR(); /* passed as params: out, c */
11744                                 lasttoken = TREDIR;
11745                                 return lasttoken;
11746                         }
11747                         /* else: non-number X seen, interpret it
11748                          * as "NNNX>file" = "NNNX >file" */
11749                 }
11750                 pungetc();
11751         }
11752         quoteflag = quotef;
11753         backquotelist = bqlist;
11754         grabstackblock(len);
11755         wordtext = out;
11756         lasttoken = TWORD;
11757         return lasttoken;
11758 /* end of readtoken routine */
11759
11760 /*
11761  * Check to see whether we are at the end of the here document.  When this
11762  * is called, c is set to the first character of the next input line.  If
11763  * we are at the end of the here document, this routine sets the c to PEOF.
11764  */
11765 checkend: {
11766         if (eofmark) {
11767 #if ENABLE_ASH_ALIAS
11768                 if (c == PEOA)
11769                         c = pgetc_without_PEOA();
11770 #endif
11771                 if (striptabs) {
11772                         while (c == '\t') {
11773                                 c = pgetc_without_PEOA();
11774                         }
11775                 }
11776                 if (c == *eofmark) {
11777                         if (pfgets(line, sizeof(line)) != NULL) {
11778                                 char *p, *q;
11779                                 int cc;
11780
11781                                 p = line;
11782                                 for (q = eofmark + 1;; p++, q++) {
11783                                         cc = *p;
11784                                         if (cc == '\n')
11785                                                 cc = 0;
11786                                         if (!*q || cc != *q)
11787                                                 break;
11788                                 }
11789                                 if (cc == *q) {
11790                                         c = PEOF;
11791                                         nlnoprompt();
11792                                 } else {
11793                                         pushstring(line, NULL);
11794                                 }
11795                         }
11796                 }
11797         }
11798         goto checkend_return;
11799 }
11800
11801 /*
11802  * Parse a redirection operator.  The variable "out" points to a string
11803  * specifying the fd to be redirected.  The variable "c" contains the
11804  * first character of the redirection operator.
11805  */
11806 parseredir: {
11807         /* out is already checked to be a valid number or "" */
11808         int fd = (*out == '\0' ? -1 : atoi(out));
11809         union node *np;
11810
11811         np = stzalloc(sizeof(struct nfile));
11812         if (c == '>') {
11813                 np->nfile.fd = 1;
11814                 c = pgetc();
11815                 if (c == '>')
11816                         np->type = NAPPEND;
11817                 else if (c == '|')
11818                         np->type = NCLOBBER;
11819                 else if (c == '&')
11820                         np->type = NTOFD;
11821                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11822                 else {
11823                         np->type = NTO;
11824                         pungetc();
11825                 }
11826         }
11827 #if BASH_REDIR_OUTPUT
11828         else if (c == 0x100 + '>') { /* this flags &> redirection */
11829                 np->nfile.fd = 1;
11830                 pgetc(); /* this is '>', no need to check */
11831                 np->type = NTO2;
11832         }
11833 #endif
11834         else { /* c == '<' */
11835                 /*np->nfile.fd = 0; - stzalloc did it */
11836                 c = pgetc();
11837                 switch (c) {
11838                 case '<':
11839                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11840                                 np = stzalloc(sizeof(struct nhere));
11841                                 /*np->nfile.fd = 0; - stzalloc did it */
11842                         }
11843                         np->type = NHERE;
11844                         heredoc = stzalloc(sizeof(struct heredoc));
11845                         heredoc->here = np;
11846                         c = pgetc();
11847                         if (c == '-') {
11848                                 heredoc->striptabs = 1;
11849                         } else {
11850                                 /*heredoc->striptabs = 0; - stzalloc did it */
11851                                 pungetc();
11852                         }
11853                         break;
11854
11855                 case '&':
11856                         np->type = NFROMFD;
11857                         break;
11858
11859                 case '>':
11860                         np->type = NFROMTO;
11861                         break;
11862
11863                 default:
11864                         np->type = NFROM;
11865                         pungetc();
11866                         break;
11867                 }
11868         }
11869         if (fd >= 0)
11870                 np->nfile.fd = fd;
11871         redirnode = np;
11872         goto parseredir_return;
11873 }
11874
11875 /*
11876  * Parse a substitution.  At this point, we have read the dollar sign
11877  * and nothing else.
11878  */
11879
11880 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11881  * (assuming ascii char codes, as the original implementation did) */
11882 #define is_special(c) \
11883         (((unsigned)(c) - 33 < 32) \
11884                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11885 parsesub: {
11886         unsigned char subtype;
11887         int typeloc;
11888
11889         c = pgetc_eatbnl();
11890         if (c > 255 /* PEOA or PEOF */
11891          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11892         ) {
11893 #if BASH_DOLLAR_SQUOTE
11894                 if (syntax != DQSYNTAX && c == '\'')
11895                         bash_dollar_squote = 1;
11896                 else
11897 #endif
11898                         USTPUTC('$', out);
11899                 pungetc();
11900         } else if (c == '(') {
11901                 /* $(command) or $((arith)) */
11902                 if (pgetc_eatbnl() == '(') {
11903 #if ENABLE_FEATURE_SH_MATH
11904                         PARSEARITH();
11905 #else
11906                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11907 #endif
11908                 } else {
11909                         pungetc();
11910                         PARSEBACKQNEW();
11911                 }
11912         } else {
11913                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11914                 USTPUTC(CTLVAR, out);
11915                 typeloc = out - (char *)stackblock();
11916                 STADJUST(1, out);
11917                 subtype = VSNORMAL;
11918                 if (c == '{') {
11919                         c = pgetc_eatbnl();
11920                         subtype = 0;
11921                 }
11922  varname:
11923                 if (is_name(c)) {
11924                         /* $[{[#]]NAME[}] */
11925                         do {
11926                                 STPUTC(c, out);
11927                                 c = pgetc_eatbnl();
11928                         } while (is_in_name(c));
11929                 } else if (isdigit(c)) {
11930                         /* $[{[#]]NUM[}] */
11931                         do {
11932                                 STPUTC(c, out);
11933                                 c = pgetc_eatbnl();
11934                         } while (isdigit(c));
11935                 } else if (is_special(c)) {
11936                         /* $[{[#]]<specialchar>[}] */
11937                         int cc = c;
11938
11939                         c = pgetc_eatbnl();
11940                         if (!subtype && cc == '#') {
11941                                 subtype = VSLENGTH;
11942                                 if (c == '_' || isalnum(c))
11943                                         goto varname;
11944                                 cc = c;
11945                                 c = pgetc_eatbnl();
11946                                 if (cc == '}' || c != '}') {
11947                                         pungetc();
11948                                         subtype = 0;
11949                                         c = cc;
11950                                         cc = '#';
11951                                 }
11952                         }
11953                         USTPUTC(cc, out);
11954                 } else {
11955                         goto badsub;
11956                 }
11957                 if (c != '}' && subtype == VSLENGTH) {
11958                         /* ${#VAR didn't end with } */
11959                         goto badsub;
11960                 }
11961
11962                 if (subtype == 0) {
11963                         static const char types[] ALIGN1 = "}-+?=";
11964                         /* ${VAR...} but not $VAR or ${#VAR} */
11965                         /* c == first char after VAR */
11966                         switch (c) {
11967                         case ':':
11968                                 c = pgetc_eatbnl();
11969 #if BASH_SUBSTR
11970                                 /* This check is only needed to not misinterpret
11971                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11972                                  * constructs.
11973                                  */
11974                                 if (!strchr(types, c)) {
11975                                         subtype = VSSUBSTR;
11976                                         pungetc();
11977                                         break; /* "goto badsub" is bigger (!) */
11978                                 }
11979 #endif
11980                                 subtype = VSNUL;
11981                                 /*FALLTHROUGH*/
11982                         default: {
11983                                 const char *p = strchr(types, c);
11984                                 if (p == NULL)
11985                                         break;
11986                                 subtype |= p - types + VSNORMAL;
11987                                 break;
11988                         }
11989                         case '%':
11990                         case '#': {
11991                                 int cc = c;
11992                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11993                                 c = pgetc_eatbnl();
11994                                 if (c != cc)
11995                                         goto badsub;
11996                                 subtype++;
11997                                 break;
11998                         }
11999 #if BASH_PATTERN_SUBST
12000                         case '/':
12001                                 /* ${v/[/]pattern/repl} */
12002 //TODO: encode pattern and repl separately.
12003 // Currently ${v/$var_with_slash/repl} is horribly broken
12004                                 subtype = VSREPLACE;
12005                                 c = pgetc_eatbnl();
12006                                 if (c != '/')
12007                                         goto badsub;
12008                                 subtype++; /* VSREPLACEALL */
12009                                 break;
12010 #endif
12011                         }
12012                 } else {
12013  badsub:
12014                         pungetc();
12015                 }
12016                 ((unsigned char *)stackblock())[typeloc] = subtype;
12017                 if (subtype != VSNORMAL) {
12018                         varnest++;
12019                         if (dblquote)
12020                                 dqvarnest++;
12021                 }
12022                 STPUTC('=', out);
12023         }
12024         goto parsesub_return;
12025 }
12026
12027 /*
12028  * Called to parse command substitutions.  Newstyle is set if the command
12029  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12030  * list of commands (passed by reference), and savelen is the number of
12031  * characters on the top of the stack which must be preserved.
12032  */
12033 parsebackq: {
12034         struct nodelist **nlpp;
12035         union node *n;
12036         char *str;
12037         size_t savelen;
12038         smallint saveprompt = 0;
12039
12040         str = NULL;
12041         savelen = out - (char *)stackblock();
12042         if (savelen > 0) {
12043                 /*
12044                  * FIXME: this can allocate very large block on stack and SEGV.
12045                  * Example:
12046                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12047                  * allocates 100kb for every command subst. With about
12048                  * a hundred command substitutions stack overflows.
12049                  * With larger prepended string, SEGV happens sooner.
12050                  */
12051                 str = alloca(savelen);
12052                 memcpy(str, stackblock(), savelen);
12053         }
12054
12055         if (oldstyle) {
12056                 /* We must read until the closing backquote, giving special
12057                  * treatment to some slashes, and then push the string and
12058                  * reread it as input, interpreting it normally.
12059                  */
12060                 char *pout;
12061                 size_t psavelen;
12062                 char *pstr;
12063
12064                 STARTSTACKSTR(pout);
12065                 for (;;) {
12066                         int pc;
12067
12068                         setprompt_if(needprompt, 2);
12069                         pc = pgetc();
12070                         switch (pc) {
12071                         case '`':
12072                                 goto done;
12073
12074                         case '\\':
12075                                 pc = pgetc();
12076                                 if (pc == '\n') {
12077                                         nlprompt();
12078                                         /*
12079                                          * If eating a newline, avoid putting
12080                                          * the newline into the new character
12081                                          * stream (via the STPUTC after the
12082                                          * switch).
12083                                          */
12084                                         continue;
12085                                 }
12086                                 if (pc != '\\' && pc != '`' && pc != '$'
12087                                  && (!dblquote || pc != '"')
12088                                 ) {
12089                                         STPUTC('\\', pout);
12090                                 }
12091                                 if (pc <= 255 /* not PEOA or PEOF */) {
12092                                         break;
12093                                 }
12094                                 /* fall through */
12095
12096                         case PEOF:
12097                         IF_ASH_ALIAS(case PEOA:)
12098                                 startlinno = g_parsefile->linno;
12099                                 raise_error_syntax("EOF in backquote substitution");
12100
12101                         case '\n':
12102                                 nlnoprompt();
12103                                 break;
12104
12105                         default:
12106                                 break;
12107                         }
12108                         STPUTC(pc, pout);
12109                 }
12110  done:
12111                 STPUTC('\0', pout);
12112                 psavelen = pout - (char *)stackblock();
12113                 if (psavelen > 0) {
12114                         pstr = grabstackstr(pout);
12115                         setinputstring(pstr);
12116                 }
12117         }
12118         nlpp = &bqlist;
12119         while (*nlpp)
12120                 nlpp = &(*nlpp)->next;
12121         *nlpp = stzalloc(sizeof(**nlpp));
12122         /* (*nlpp)->next = NULL; - stzalloc did it */
12123
12124         if (oldstyle) {
12125                 saveprompt = doprompt;
12126                 doprompt = 0;
12127         }
12128
12129         n = list(2);
12130
12131         if (oldstyle)
12132                 doprompt = saveprompt;
12133         else if (readtoken() != TRP)
12134                 raise_error_unexpected_syntax(TRP);
12135
12136         (*nlpp)->n = n;
12137         if (oldstyle) {
12138                 /*
12139                  * Start reading from old file again, ignoring any pushed back
12140                  * tokens left from the backquote parsing
12141                  */
12142                 popfile();
12143                 tokpushback = 0;
12144         }
12145         while (stackblocksize() <= savelen)
12146                 growstackblock();
12147         STARTSTACKSTR(out);
12148         if (str) {
12149                 memcpy(out, str, savelen);
12150                 STADJUST(savelen, out);
12151         }
12152         USTPUTC(CTLBACKQ, out);
12153         if (oldstyle)
12154                 goto parsebackq_oldreturn;
12155         goto parsebackq_newreturn;
12156 }
12157
12158 #if ENABLE_FEATURE_SH_MATH
12159 /*
12160  * Parse an arithmetic expansion (indicate start of one and set state)
12161  */
12162 parsearith: {
12163         if (++arinest == 1) {
12164                 prevsyntax = syntax;
12165                 syntax = ARISYNTAX;
12166         }
12167         USTPUTC(CTLARI, out);
12168         goto parsearith_return;
12169 }
12170 #endif
12171 } /* end of readtoken */
12172
12173 /*
12174  * Read the next input token.
12175  * If the token is a word, we set backquotelist to the list of cmds in
12176  *      backquotes.  We set quoteflag to true if any part of the word was
12177  *      quoted.
12178  * If the token is TREDIR, then we set redirnode to a structure containing
12179  *      the redirection.
12180  * In all cases, the variable startlinno is set to the number of the line
12181  *      on which the token starts.
12182  *
12183  * [Change comment:  here documents and internal procedures]
12184  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12185  *  word parsing code into a separate routine.  In this case, readtoken
12186  *  doesn't need to have any internal procedures, but parseword does.
12187  *  We could also make parseoperator in essence the main routine, and
12188  *  have parseword (readtoken1?) handle both words and redirection.]
12189  */
12190 #define NEW_xxreadtoken
12191 #ifdef NEW_xxreadtoken
12192 /* singles must be first! */
12193 static const char xxreadtoken_chars[7] ALIGN1 = {
12194         '\n', '(', ')', /* singles */
12195         '&', '|', ';',  /* doubles */
12196         0
12197 };
12198
12199 #define xxreadtoken_singles 3
12200 #define xxreadtoken_doubles 3
12201
12202 static const char xxreadtoken_tokens[] ALIGN1 = {
12203         TNL, TLP, TRP,          /* only single occurrence allowed */
12204         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12205         TEOF,                   /* corresponds to trailing nul */
12206         TAND, TOR, TENDCASE     /* if double occurrence */
12207 };
12208
12209 static int
12210 xxreadtoken(void)
12211 {
12212         int c;
12213
12214         if (tokpushback) {
12215                 tokpushback = 0;
12216                 return lasttoken;
12217         }
12218         setprompt_if(needprompt, 2);
12219         startlinno = g_parsefile->linno;
12220         for (;;) {                      /* until token or start of word found */
12221                 c = pgetc();
12222                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12223                         continue;
12224
12225                 if (c == '#') {
12226                         while ((c = pgetc()) != '\n' && c != PEOF)
12227                                 continue;
12228                         pungetc();
12229                 } else if (c == '\\') {
12230                         if (pgetc() != '\n') {
12231                                 pungetc();
12232                                 break; /* return readtoken1(...) */
12233                         }
12234                         nlprompt();
12235                 } else {
12236                         const char *p;
12237
12238                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12239                         if (c != PEOF) {
12240                                 if (c == '\n') {
12241                                         nlnoprompt();
12242                                 }
12243
12244                                 p = strchr(xxreadtoken_chars, c);
12245                                 if (p == NULL)
12246                                         break; /* return readtoken1(...) */
12247
12248                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12249                                         int cc = pgetc();
12250                                         if (cc == c) {    /* double occurrence? */
12251                                                 p += xxreadtoken_doubles + 1;
12252                                         } else {
12253                                                 pungetc();
12254 #if BASH_REDIR_OUTPUT
12255                                                 if (c == '&' && cc == '>') /* &> */
12256                                                         break; /* return readtoken1(...) */
12257 #endif
12258                                         }
12259                                 }
12260                         }
12261                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12262                         return lasttoken;
12263                 }
12264         } /* for (;;) */
12265
12266         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12267 }
12268 #else /* old xxreadtoken */
12269 #define RETURN(token)   return lasttoken = token
12270 static int
12271 xxreadtoken(void)
12272 {
12273         int c;
12274
12275         if (tokpushback) {
12276                 tokpushback = 0;
12277                 return lasttoken;
12278         }
12279         setprompt_if(needprompt, 2);
12280         startlinno = g_parsefile->linno;
12281         for (;;) {      /* until token or start of word found */
12282                 c = pgetc();
12283                 switch (c) {
12284                 case ' ': case '\t':
12285                 IF_ASH_ALIAS(case PEOA:)
12286                         continue;
12287                 case '#':
12288                         while ((c = pgetc()) != '\n' && c != PEOF)
12289                                 continue;
12290                         pungetc();
12291                         continue;
12292                 case '\\':
12293                         if (pgetc() == '\n') {
12294                                 nlprompt();
12295                                 continue;
12296                         }
12297                         pungetc();
12298                         goto breakloop;
12299                 case '\n':
12300                         nlnoprompt();
12301                         RETURN(TNL);
12302                 case PEOF:
12303                         RETURN(TEOF);
12304                 case '&':
12305                         if (pgetc() == '&')
12306                                 RETURN(TAND);
12307                         pungetc();
12308                         RETURN(TBACKGND);
12309                 case '|':
12310                         if (pgetc() == '|')
12311                                 RETURN(TOR);
12312                         pungetc();
12313                         RETURN(TPIPE);
12314                 case ';':
12315                         if (pgetc() == ';')
12316                                 RETURN(TENDCASE);
12317                         pungetc();
12318                         RETURN(TSEMI);
12319                 case '(':
12320                         RETURN(TLP);
12321                 case ')':
12322                         RETURN(TRP);
12323                 default:
12324                         goto breakloop;
12325                 }
12326         }
12327  breakloop:
12328         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12329 #undef RETURN
12330 }
12331 #endif /* old xxreadtoken */
12332
12333 static int
12334 readtoken(void)
12335 {
12336         int t;
12337         int kwd = checkkwd;
12338 #if DEBUG
12339         smallint alreadyseen = tokpushback;
12340 #endif
12341
12342 #if ENABLE_ASH_ALIAS
12343  top:
12344 #endif
12345
12346         t = xxreadtoken();
12347
12348         /*
12349          * eat newlines
12350          */
12351         if (kwd & CHKNL) {
12352                 while (t == TNL) {
12353                         parseheredoc();
12354                         t = xxreadtoken();
12355                 }
12356         }
12357
12358         if (t != TWORD || quoteflag) {
12359                 goto out;
12360         }
12361
12362         /*
12363          * check for keywords
12364          */
12365         if (kwd & CHKKWD) {
12366                 const char *const *pp;
12367
12368                 pp = findkwd(wordtext);
12369                 if (pp) {
12370                         lasttoken = t = pp - tokname_array;
12371                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12372                         goto out;
12373                 }
12374         }
12375
12376         if (checkkwd & CHKALIAS) {
12377 #if ENABLE_ASH_ALIAS
12378                 struct alias *ap;
12379                 ap = lookupalias(wordtext, 1);
12380                 if (ap != NULL) {
12381                         if (*ap->val) {
12382                                 pushstring(ap->val, ap);
12383                         }
12384                         goto top;
12385                 }
12386 #endif
12387         }
12388  out:
12389         checkkwd = 0;
12390 #if DEBUG
12391         if (!alreadyseen)
12392                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12393         else
12394                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12395 #endif
12396         return t;
12397 }
12398
12399 static int
12400 peektoken(void)
12401 {
12402         int t;
12403
12404         t = readtoken();
12405         tokpushback = 1;
12406         return t;
12407 }
12408
12409 /*
12410  * Read and parse a command.  Returns NODE_EOF on end of file.
12411  * (NULL is a valid parse tree indicating a blank line.)
12412  */
12413 static union node *
12414 parsecmd(int interact)
12415 {
12416         tokpushback = 0;
12417         checkkwd = 0;
12418         heredoclist = 0;
12419         doprompt = interact;
12420         setprompt_if(doprompt, doprompt);
12421         needprompt = 0;
12422         return list(1);
12423 }
12424
12425 /*
12426  * Input any here documents.
12427  */
12428 static void
12429 parseheredoc(void)
12430 {
12431         struct heredoc *here;
12432         union node *n;
12433
12434         here = heredoclist;
12435         heredoclist = NULL;
12436
12437         while (here) {
12438                 setprompt_if(needprompt, 2);
12439                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12440                                 here->eofmark, here->striptabs);
12441                 n = stzalloc(sizeof(struct narg));
12442                 n->narg.type = NARG;
12443                 /*n->narg.next = NULL; - stzalloc did it */
12444                 n->narg.text = wordtext;
12445                 n->narg.backquote = backquotelist;
12446                 here->here->nhere.doc = n;
12447                 here = here->next;
12448         }
12449 }
12450
12451
12452 /*
12453  * called by editline -- any expansions to the prompt should be added here.
12454  */
12455 #if ENABLE_ASH_EXPAND_PRMT
12456 static const char *
12457 expandstr(const char *ps)
12458 {
12459         union node n;
12460         int saveprompt;
12461
12462         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12463          * and token processing _can_ alter it (delete NULs etc). */
12464         setinputstring((char *)ps);
12465
12466         saveprompt = doprompt;
12467         doprompt = 0;
12468         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12469         doprompt = saveprompt;
12470
12471         popfile();
12472
12473         n.narg.type = NARG;
12474         n.narg.next = NULL;
12475         n.narg.text = wordtext;
12476         n.narg.backquote = backquotelist;
12477
12478         expandarg(&n, NULL, EXP_QUOTED);
12479         return stackblock();
12480 }
12481 #endif
12482
12483 /*
12484  * Execute a command or commands contained in a string.
12485  */
12486 static int
12487 evalstring(char *s, int flags)
12488 {
12489         struct jmploc *volatile savehandler;
12490         struct jmploc jmploc;
12491         int ex;
12492
12493         union node *n;
12494         struct stackmark smark;
12495         int status;
12496
12497         s = sstrdup(s);
12498         setinputstring(s);
12499         setstackmark(&smark);
12500
12501         status = 0;
12502         /* On exception inside execution loop, we must popfile().
12503          * Try interactively:
12504          *      readonly a=a
12505          *      command eval "a=b"  # throws "is read only" error
12506          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12507          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12508          */
12509         savehandler = exception_handler;
12510         ex = setjmp(jmploc.loc);
12511         if (ex)
12512                 goto out;
12513         exception_handler = &jmploc;
12514
12515         while ((n = parsecmd(0)) != NODE_EOF) {
12516                 int i;
12517
12518                 i = evaltree(n, flags);
12519                 if (n)
12520                         status = i;
12521                 popstackmark(&smark);
12522                 if (evalskip)
12523                         break;
12524         }
12525  out:
12526         popstackmark(&smark);
12527         popfile();
12528         stunalloc(s);
12529
12530         exception_handler = savehandler;
12531         if (ex)
12532                 longjmp(exception_handler->loc, ex);
12533
12534         return status;
12535 }
12536
12537 /*
12538  * The eval command.
12539  */
12540 static int FAST_FUNC
12541 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12542 {
12543         char *p;
12544         char *concat;
12545
12546         if (argv[1]) {
12547                 p = argv[1];
12548                 argv += 2;
12549                 if (argv[0]) {
12550                         STARTSTACKSTR(concat);
12551                         for (;;) {
12552                                 concat = stack_putstr(p, concat);
12553                                 p = *argv++;
12554                                 if (p == NULL)
12555                                         break;
12556                                 STPUTC(' ', concat);
12557                         }
12558                         STPUTC('\0', concat);
12559                         p = grabstackstr(concat);
12560                 }
12561                 return evalstring(p, flags & EV_TESTED);
12562         }
12563         return 0;
12564 }
12565
12566 /*
12567  * Read and execute commands.
12568  * "Top" is nonzero for the top level command loop;
12569  * it turns on prompting if the shell is interactive.
12570  */
12571 static int
12572 cmdloop(int top)
12573 {
12574         union node *n;
12575         struct stackmark smark;
12576         int inter;
12577         int status = 0;
12578         int numeof = 0;
12579
12580         TRACE(("cmdloop(%d) called\n", top));
12581         for (;;) {
12582                 int skip;
12583
12584                 setstackmark(&smark);
12585 #if JOBS
12586                 if (doing_jobctl)
12587                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12588 #endif
12589                 inter = 0;
12590                 if (iflag && top) {
12591                         inter++;
12592                         chkmail();
12593                 }
12594                 n = parsecmd(inter);
12595 #if DEBUG
12596                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12597                         showtree(n);
12598 #endif
12599                 if (n == NODE_EOF) {
12600                         if (!top || numeof >= 50)
12601                                 break;
12602                         if (!stoppedjobs()) {
12603                                 if (!Iflag)
12604                                         break;
12605                                 out2str("\nUse \"exit\" to leave shell.\n");
12606                         }
12607                         numeof++;
12608                 } else if (nflag == 0) {
12609                         int i;
12610
12611                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12612                         job_warning >>= 1;
12613                         numeof = 0;
12614                         i = evaltree(n, 0);
12615                         if (n)
12616                                 status = i;
12617                 }
12618                 popstackmark(&smark);
12619                 skip = evalskip;
12620
12621                 if (skip) {
12622                         evalskip &= ~SKIPFUNC;
12623                         break;
12624                 }
12625         }
12626         return status;
12627 }
12628
12629 /*
12630  * Take commands from a file.  To be compatible we should do a path
12631  * search for the file, which is necessary to find sub-commands.
12632  */
12633 static char *
12634 find_dot_file(char *name)
12635 {
12636         char *fullname;
12637         const char *path = pathval();
12638         struct stat statb;
12639
12640         /* don't try this for absolute or relative paths */
12641         if (strchr(name, '/'))
12642                 return name;
12643
12644         while ((fullname = path_advance(&path, name)) != NULL) {
12645                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12646                         /*
12647                          * Don't bother freeing here, since it will
12648                          * be freed by the caller.
12649                          */
12650                         return fullname;
12651                 }
12652                 if (fullname != name)
12653                         stunalloc(fullname);
12654         }
12655
12656         /* not found in the PATH */
12657         ash_msg_and_raise_error("%s: not found", name);
12658         /* NOTREACHED */
12659 }
12660
12661 static int FAST_FUNC
12662 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12663 {
12664         /* "false; . empty_file; echo $?" should print 0, not 1: */
12665         int status = 0;
12666         char *fullname;
12667         char **argv;
12668         char *args_need_save;
12669         struct strlist *sp;
12670         volatile struct shparam saveparam;
12671
12672         for (sp = cmdenviron; sp; sp = sp->next)
12673                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12674
12675         nextopt(nullstr); /* handle possible "--" */
12676         argv = argptr;
12677
12678         if (!argv[0]) {
12679                 /* bash says: "bash: .: filename argument required" */
12680                 return 2; /* bash compat */
12681         }
12682
12683         /* This aborts if file isn't found, which is POSIXly correct.
12684          * bash returns exitcode 1 instead.
12685          */
12686         fullname = find_dot_file(argv[0]);
12687         argv++;
12688         args_need_save = argv[0];
12689         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12690                 int argc;
12691                 saveparam = shellparam;
12692                 shellparam.malloced = 0;
12693                 argc = 1;
12694                 while (argv[argc])
12695                         argc++;
12696                 shellparam.nparam = argc;
12697                 shellparam.p = argv;
12698         };
12699
12700         /* This aborts if file can't be opened, which is POSIXly correct.
12701          * bash returns exitcode 1 instead.
12702          */
12703         setinputfile(fullname, INPUT_PUSH_FILE);
12704         commandname = fullname;
12705         status = cmdloop(0);
12706         popfile();
12707
12708         if (args_need_save) {
12709                 freeparam(&shellparam);
12710                 shellparam = saveparam;
12711         };
12712
12713         return status;
12714 }
12715
12716 static int FAST_FUNC
12717 exitcmd(int argc UNUSED_PARAM, char **argv)
12718 {
12719         if (stoppedjobs())
12720                 return 0;
12721         if (argv[1])
12722                 exitstatus = number(argv[1]);
12723         raise_exception(EXEXIT);
12724         /* NOTREACHED */
12725 }
12726
12727 /*
12728  * Read a file containing shell functions.
12729  */
12730 static void
12731 readcmdfile(char *name)
12732 {
12733         setinputfile(name, INPUT_PUSH_FILE);
12734         cmdloop(0);
12735         popfile();
12736 }
12737
12738
12739 /* ============ find_command inplementation */
12740
12741 /*
12742  * Resolve a command name.  If you change this routine, you may have to
12743  * change the shellexec routine as well.
12744  */
12745 static void
12746 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12747 {
12748         struct tblentry *cmdp;
12749         int idx;
12750         int prev;
12751         char *fullname;
12752         struct stat statb;
12753         int e;
12754         int updatetbl;
12755         struct builtincmd *bcmd;
12756
12757         /* If name contains a slash, don't use PATH or hash table */
12758         if (strchr(name, '/') != NULL) {
12759                 entry->u.index = -1;
12760                 if (act & DO_ABS) {
12761                         while (stat(name, &statb) < 0) {
12762 #ifdef SYSV
12763                                 if (errno == EINTR)
12764                                         continue;
12765 #endif
12766                                 entry->cmdtype = CMDUNKNOWN;
12767                                 return;
12768                         }
12769                 }
12770                 entry->cmdtype = CMDNORMAL;
12771                 return;
12772         }
12773
12774 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12775
12776         updatetbl = (path == pathval());
12777         if (!updatetbl) {
12778                 act |= DO_ALTPATH;
12779                 if (strstr(path, "%builtin") != NULL)
12780                         act |= DO_ALTBLTIN;
12781         }
12782
12783         /* If name is in the table, check answer will be ok */
12784         cmdp = cmdlookup(name, 0);
12785         if (cmdp != NULL) {
12786                 int bit;
12787
12788                 switch (cmdp->cmdtype) {
12789                 default:
12790 #if DEBUG
12791                         abort();
12792 #endif
12793                 case CMDNORMAL:
12794                         bit = DO_ALTPATH;
12795                         break;
12796                 case CMDFUNCTION:
12797                         bit = DO_NOFUNC;
12798                         break;
12799                 case CMDBUILTIN:
12800                         bit = DO_ALTBLTIN;
12801                         break;
12802                 }
12803                 if (act & bit) {
12804                         updatetbl = 0;
12805                         cmdp = NULL;
12806                 } else if (cmdp->rehash == 0)
12807                         /* if not invalidated by cd, we're done */
12808                         goto success;
12809         }
12810
12811         /* If %builtin not in path, check for builtin next */
12812         bcmd = find_builtin(name);
12813         if (bcmd) {
12814                 if (IS_BUILTIN_REGULAR(bcmd))
12815                         goto builtin_success;
12816                 if (act & DO_ALTPATH) {
12817                         if (!(act & DO_ALTBLTIN))
12818                                 goto builtin_success;
12819                 } else if (builtinloc <= 0) {
12820                         goto builtin_success;
12821                 }
12822         }
12823
12824 #if ENABLE_FEATURE_SH_STANDALONE
12825         {
12826                 int applet_no = find_applet_by_name(name);
12827                 if (applet_no >= 0) {
12828                         entry->cmdtype = CMDNORMAL;
12829                         entry->u.index = -2 - applet_no;
12830                         return;
12831                 }
12832         }
12833 #endif
12834
12835         /* We have to search path. */
12836         prev = -1;              /* where to start */
12837         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12838                 if (cmdp->cmdtype == CMDBUILTIN)
12839                         prev = builtinloc;
12840                 else
12841                         prev = cmdp->param.index;
12842         }
12843
12844         e = ENOENT;
12845         idx = -1;
12846  loop:
12847         while ((fullname = path_advance(&path, name)) != NULL) {
12848                 stunalloc(fullname);
12849                 /* NB: code below will still use fullname
12850                  * despite it being "unallocated" */
12851                 idx++;
12852                 if (pathopt) {
12853                         if (prefix(pathopt, "builtin")) {
12854                                 if (bcmd)
12855                                         goto builtin_success;
12856                                 continue;
12857                         }
12858                         if ((act & DO_NOFUNC)
12859                          || !prefix(pathopt, "func")
12860                         ) {     /* ignore unimplemented options */
12861                                 continue;
12862                         }
12863                 }
12864                 /* if rehash, don't redo absolute path names */
12865                 if (fullname[0] == '/' && idx <= prev) {
12866                         if (idx < prev)
12867                                 continue;
12868                         TRACE(("searchexec \"%s\": no change\n", name));
12869                         goto success;
12870                 }
12871                 while (stat(fullname, &statb) < 0) {
12872 #ifdef SYSV
12873                         if (errno == EINTR)
12874                                 continue;
12875 #endif
12876                         if (errno != ENOENT && errno != ENOTDIR)
12877                                 e = errno;
12878                         goto loop;
12879                 }
12880                 e = EACCES;     /* if we fail, this will be the error */
12881                 if (!S_ISREG(statb.st_mode))
12882                         continue;
12883                 if (pathopt) {          /* this is a %func directory */
12884                         stalloc(strlen(fullname) + 1);
12885                         /* NB: stalloc will return space pointed by fullname
12886                          * (because we don't have any intervening allocations
12887                          * between stunalloc above and this stalloc) */
12888                         readcmdfile(fullname);
12889                         cmdp = cmdlookup(name, 0);
12890                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12891                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12892                         stunalloc(fullname);
12893                         goto success;
12894                 }
12895                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12896                 if (!updatetbl) {
12897                         entry->cmdtype = CMDNORMAL;
12898                         entry->u.index = idx;
12899                         return;
12900                 }
12901                 INT_OFF;
12902                 cmdp = cmdlookup(name, 1);
12903                 cmdp->cmdtype = CMDNORMAL;
12904                 cmdp->param.index = idx;
12905                 INT_ON;
12906                 goto success;
12907         }
12908
12909         /* We failed.  If there was an entry for this command, delete it */
12910         if (cmdp && updatetbl)
12911                 delete_cmd_entry();
12912         if (act & DO_ERR)
12913                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12914         entry->cmdtype = CMDUNKNOWN;
12915         return;
12916
12917  builtin_success:
12918         if (!updatetbl) {
12919                 entry->cmdtype = CMDBUILTIN;
12920                 entry->u.cmd = bcmd;
12921                 return;
12922         }
12923         INT_OFF;
12924         cmdp = cmdlookup(name, 1);
12925         cmdp->cmdtype = CMDBUILTIN;
12926         cmdp->param.cmd = bcmd;
12927         INT_ON;
12928  success:
12929         cmdp->rehash = 0;
12930         entry->cmdtype = cmdp->cmdtype;
12931         entry->u = cmdp->param;
12932 }
12933
12934
12935 /*
12936  * The trap builtin.
12937  */
12938 static int FAST_FUNC
12939 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12940 {
12941         char *action;
12942         char **ap;
12943         int signo, exitcode;
12944
12945         nextopt(nullstr);
12946         ap = argptr;
12947         if (!*ap) {
12948                 for (signo = 0; signo < NSIG; signo++) {
12949                         char *tr = trap_ptr[signo];
12950                         if (tr) {
12951                                 /* note: bash adds "SIG", but only if invoked
12952                                  * as "bash". If called as "sh", or if set -o posix,
12953                                  * then it prints short signal names.
12954                                  * We are printing short names: */
12955                                 out1fmt("trap -- %s %s\n",
12956                                                 single_quote(tr),
12957                                                 get_signame(signo));
12958                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12959                  * In this case, we will exit very soon, no need to free(). */
12960                                 /* if (trap_ptr != trap && tp[0]) */
12961                                 /*      free(tr); */
12962                         }
12963                 }
12964                 /*
12965                 if (trap_ptr != trap) {
12966                         free(trap_ptr);
12967                         trap_ptr = trap;
12968                 }
12969                 */
12970                 return 0;
12971         }
12972
12973         action = NULL;
12974         if (ap[1])
12975                 action = *ap++;
12976         exitcode = 0;
12977         while (*ap) {
12978                 signo = get_signum(*ap);
12979                 if (signo < 0) {
12980                         /* Mimic bash message exactly */
12981                         ash_msg("%s: invalid signal specification", *ap);
12982                         exitcode = 1;
12983                         goto next;
12984                 }
12985                 INT_OFF;
12986                 if (action) {
12987                         if (LONE_DASH(action))
12988                                 action = NULL;
12989                         else {
12990                                 if (action[0]) /* not NULL and not "" and not "-" */
12991                                         may_have_traps = 1;
12992                                 action = ckstrdup(action);
12993                         }
12994                 }
12995                 free(trap[signo]);
12996                 trap[signo] = action;
12997                 if (signo != 0)
12998                         setsignal(signo);
12999                 INT_ON;
13000  next:
13001                 ap++;
13002         }
13003         return exitcode;
13004 }
13005
13006
13007 /* ============ Builtins */
13008
13009 #if ENABLE_ASH_HELP
13010 static int FAST_FUNC
13011 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13012 {
13013         unsigned col;
13014         unsigned i;
13015
13016         out1fmt(
13017                 "Built-in commands:\n"
13018                 "------------------\n");
13019         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13020                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13021                                         builtintab[i].name + 1);
13022                 if (col > 60) {
13023                         out1fmt("\n");
13024                         col = 0;
13025                 }
13026         }
13027 # if ENABLE_FEATURE_SH_STANDALONE
13028         {
13029                 const char *a = applet_names;
13030                 while (*a) {
13031                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13032                         if (col > 60) {
13033                                 out1fmt("\n");
13034                                 col = 0;
13035                         }
13036                         while (*a++ != '\0')
13037                                 continue;
13038                 }
13039         }
13040 # endif
13041         newline_and_flush(stdout);
13042         return EXIT_SUCCESS;
13043 }
13044 #endif
13045
13046 #if MAX_HISTORY
13047 static int FAST_FUNC
13048 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13049 {
13050         show_history(line_input_state);
13051         return EXIT_SUCCESS;
13052 }
13053 #endif
13054
13055 /*
13056  * The export and readonly commands.
13057  */
13058 static int FAST_FUNC
13059 exportcmd(int argc UNUSED_PARAM, char **argv)
13060 {
13061         struct var *vp;
13062         char *name;
13063         const char *p;
13064         char **aptr;
13065         char opt;
13066         int flag;
13067         int flag_off;
13068
13069         /* "readonly" in bash accepts, but ignores -n.
13070          * We do the same: it saves a conditional in nextopt's param.
13071          */
13072         flag_off = 0;
13073         while ((opt = nextopt("np")) != '\0') {
13074                 if (opt == 'n')
13075                         flag_off = VEXPORT;
13076         }
13077         flag = VEXPORT;
13078         if (argv[0][0] == 'r') {
13079                 flag = VREADONLY;
13080                 flag_off = 0; /* readonly ignores -n */
13081         }
13082         flag_off = ~flag_off;
13083
13084         /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
13085         {
13086                 aptr = argptr;
13087                 name = *aptr;
13088                 if (name) {
13089                         do {
13090                                 p = strchr(name, '=');
13091                                 if (p != NULL) {
13092                                         p++;
13093                                 } else {
13094                                         vp = *findvar(hashvar(name), name);
13095                                         if (vp) {
13096                                                 vp->flags = ((vp->flags | flag) & flag_off);
13097                                                 continue;
13098                                         }
13099                                 }
13100                                 setvar(name, p, (flag & flag_off));
13101                         } while ((name = *++aptr) != NULL);
13102                         return 0;
13103                 }
13104         }
13105
13106         /* No arguments. Show the list of exported or readonly vars.
13107          * -n is ignored.
13108          */
13109         showvars(argv[0], flag, 0);
13110         return 0;
13111 }
13112
13113 /*
13114  * Delete a function if it exists.
13115  */
13116 static void
13117 unsetfunc(const char *name)
13118 {
13119         struct tblentry *cmdp;
13120
13121         cmdp = cmdlookup(name, 0);
13122         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13123                 delete_cmd_entry();
13124 }
13125
13126 /*
13127  * The unset builtin command.  We unset the function before we unset the
13128  * variable to allow a function to be unset when there is a readonly variable
13129  * with the same name.
13130  */
13131 static int FAST_FUNC
13132 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13133 {
13134         char **ap;
13135         int i;
13136         int flag = 0;
13137         int ret = 0;
13138
13139         while ((i = nextopt("vf")) != 0) {
13140                 flag = i;
13141         }
13142
13143         for (ap = argptr; *ap; ap++) {
13144                 if (flag != 'f') {
13145                         i = unsetvar(*ap);
13146                         ret |= i;
13147                         if (!(i & 2))
13148                                 continue;
13149                 }
13150                 if (flag != 'v')
13151                         unsetfunc(*ap);
13152         }
13153         return ret & 1;
13154 }
13155
13156 static const unsigned char timescmd_str[] ALIGN1 = {
13157         ' ',  offsetof(struct tms, tms_utime),
13158         '\n', offsetof(struct tms, tms_stime),
13159         ' ',  offsetof(struct tms, tms_cutime),
13160         '\n', offsetof(struct tms, tms_cstime),
13161         0
13162 };
13163 static int FAST_FUNC
13164 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13165 {
13166         unsigned long clk_tck, s, t;
13167         const unsigned char *p;
13168         struct tms buf;
13169
13170         clk_tck = bb_clk_tck();
13171         times(&buf);
13172
13173         p = timescmd_str;
13174         do {
13175                 t = *(clock_t *)(((char *) &buf) + p[1]);
13176                 s = t / clk_tck;
13177                 t = t % clk_tck;
13178                 out1fmt("%lum%lu.%03lus%c",
13179                         s / 60, s % 60,
13180                         (t * 1000) / clk_tck,
13181                         p[0]);
13182                 p += 2;
13183         } while (*p);
13184
13185         return 0;
13186 }
13187
13188 #if ENABLE_FEATURE_SH_MATH
13189 /*
13190  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13191  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13192  *
13193  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13194  */
13195 static int FAST_FUNC
13196 letcmd(int argc UNUSED_PARAM, char **argv)
13197 {
13198         arith_t i;
13199
13200         argv++;
13201         if (!*argv)
13202                 ash_msg_and_raise_error("expression expected");
13203         do {
13204                 i = ash_arith(*argv);
13205         } while (*++argv);
13206
13207         return !i;
13208 }
13209 #endif
13210
13211 /*
13212  * The read builtin. Options:
13213  *      -r              Do not interpret '\' specially
13214  *      -s              Turn off echo (tty only)
13215  *      -n NCHARS       Read NCHARS max
13216  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13217  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13218  *      -u FD           Read from given FD instead of fd 0
13219  * This uses unbuffered input, which may be avoidable in some cases.
13220  * TODO: bash also has:
13221  *      -a ARRAY        Read into array[0],[1],etc
13222  *      -d DELIM        End on DELIM char, not newline
13223  *      -e              Use line editing (tty only)
13224  */
13225 static int FAST_FUNC
13226 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13227 {
13228         char *opt_n = NULL;
13229         char *opt_p = NULL;
13230         char *opt_t = NULL;
13231         char *opt_u = NULL;
13232         int read_flags = 0;
13233         const char *r;
13234         int i;
13235
13236         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13237                 switch (i) {
13238                 case 'p':
13239                         opt_p = optionarg;
13240                         break;
13241                 case 'n':
13242                         opt_n = optionarg;
13243                         break;
13244                 case 's':
13245                         read_flags |= BUILTIN_READ_SILENT;
13246                         break;
13247                 case 't':
13248                         opt_t = optionarg;
13249                         break;
13250                 case 'r':
13251                         read_flags |= BUILTIN_READ_RAW;
13252                         break;
13253                 case 'u':
13254                         opt_u = optionarg;
13255                         break;
13256                 default:
13257                         break;
13258                 }
13259         }
13260
13261         /* "read -s" needs to save/restore termios, can't allow ^C
13262          * to jump out of it.
13263          */
13264         INT_OFF;
13265         r = shell_builtin_read(setvar0,
13266                 argptr,
13267                 bltinlookup("IFS"), /* can be NULL */
13268                 read_flags,
13269                 opt_n,
13270                 opt_p,
13271                 opt_t,
13272                 opt_u
13273         );
13274         INT_ON;
13275
13276         if ((uintptr_t)r > 1)
13277                 ash_msg_and_raise_error(r);
13278
13279         return (uintptr_t)r;
13280 }
13281
13282 static int FAST_FUNC
13283 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13284 {
13285         static const char permuser[3] ALIGN1 = "ogu";
13286
13287         mode_t mask;
13288         int symbolic_mode = 0;
13289
13290         while (nextopt("S") != '\0') {
13291                 symbolic_mode = 1;
13292         }
13293
13294         INT_OFF;
13295         mask = umask(0);
13296         umask(mask);
13297         INT_ON;
13298
13299         if (*argptr == NULL) {
13300                 if (symbolic_mode) {
13301                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13302                         char *p = buf;
13303                         int i;
13304
13305                         i = 2;
13306                         for (;;) {
13307                                 *p++ = ',';
13308                                 *p++ = permuser[i];
13309                                 *p++ = '=';
13310                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13311                                 if (!(mask & 0400)) *p++ = 'r';
13312                                 if (!(mask & 0200)) *p++ = 'w';
13313                                 if (!(mask & 0100)) *p++ = 'x';
13314                                 mask <<= 3;
13315                                 if (--i < 0)
13316                                         break;
13317                         }
13318                         *p = '\0';
13319                         puts(buf + 1);
13320                 } else {
13321                         out1fmt("%04o\n", mask);
13322                 }
13323         } else {
13324                 char *modestr = *argptr;
13325                 /* numeric umasks are taken as-is */
13326                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13327                 if (!isdigit(modestr[0]))
13328                         mask ^= 0777;
13329                 mask = bb_parse_mode(modestr, mask);
13330                 if ((unsigned)mask > 0777) {
13331                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13332                 }
13333                 if (!isdigit(modestr[0]))
13334                         mask ^= 0777;
13335                 umask(mask);
13336         }
13337         return 0;
13338 }
13339
13340 static int FAST_FUNC
13341 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13342 {
13343         return shell_builtin_ulimit(argv);
13344 }
13345
13346 /* ============ main() and helpers */
13347
13348 /*
13349  * Called to exit the shell.
13350  */
13351 static void
13352 exitshell(void)
13353 {
13354         struct jmploc loc;
13355         char *p;
13356         int status;
13357
13358 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13359         save_history(line_input_state);
13360 #endif
13361         status = exitstatus;
13362         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13363         if (setjmp(loc.loc)) {
13364                 if (exception_type == EXEXIT)
13365                         status = exitstatus;
13366                 goto out;
13367         }
13368         exception_handler = &loc;
13369         p = trap[0];
13370         if (p) {
13371                 trap[0] = NULL;
13372                 evalskip = 0;
13373                 evalstring(p, 0);
13374                 /*free(p); - we'll exit soon */
13375         }
13376  out:
13377         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13378          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13379          */
13380         setjobctl(0);
13381         flush_stdout_stderr();
13382         _exit(status);
13383         /* NOTREACHED */
13384 }
13385
13386 static void
13387 init(void)
13388 {
13389         /* we will never free this */
13390         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13391
13392         sigmode[SIGCHLD - 1] = S_DFL;
13393         setsignal(SIGCHLD);
13394
13395         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13396          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13397          */
13398         signal(SIGHUP, SIG_DFL);
13399
13400         {
13401                 char **envp;
13402                 const char *p;
13403                 struct stat st1, st2;
13404
13405                 initvar();
13406                 for (envp = environ; envp && *envp; envp++) {
13407                         p = endofname(*envp);
13408                         if (p != *envp && *p == '=') {
13409                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13410                         }
13411                 }
13412
13413                 setvareq((char*)defoptindvar, VTEXTFIXED);
13414
13415                 setvar0("PPID", utoa(getppid()));
13416 #if BASH_SHLVL_VAR
13417                 p = lookupvar("SHLVL");
13418                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13419 #endif
13420 #if BASH_HOSTNAME_VAR
13421                 if (!lookupvar("HOSTNAME")) {
13422                         struct utsname uts;
13423                         uname(&uts);
13424                         setvar0("HOSTNAME", uts.nodename);
13425                 }
13426 #endif
13427                 p = lookupvar("PWD");
13428                 if (p) {
13429                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13430                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13431                         ) {
13432                                 p = NULL;
13433                         }
13434                 }
13435                 setpwd(p, 0);
13436         }
13437 }
13438
13439
13440 //usage:#define ash_trivial_usage
13441 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13442 //usage:#define ash_full_usage "\n\n"
13443 //usage:        "Unix shell interpreter"
13444
13445 /*
13446  * Process the shell command line arguments.
13447  */
13448 static void
13449 procargs(char **argv)
13450 {
13451         int i;
13452         const char *xminusc;
13453         char **xargv;
13454
13455         xargv = argv;
13456         arg0 = xargv[0];
13457         /* if (xargv[0]) - mmm, this is always true! */
13458                 xargv++;
13459         for (i = 0; i < NOPTS; i++)
13460                 optlist[i] = 2;
13461         argptr = xargv;
13462         if (options(/*cmdline:*/ 1)) {
13463                 /* it already printed err message */
13464                 raise_exception(EXERROR);
13465         }
13466         xargv = argptr;
13467         xminusc = minusc;
13468         if (*xargv == NULL) {
13469                 if (xminusc)
13470                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13471                 sflag = 1;
13472         }
13473         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13474                 iflag = 1;
13475         if (mflag == 2)
13476                 mflag = iflag;
13477         for (i = 0; i < NOPTS; i++)
13478                 if (optlist[i] == 2)
13479                         optlist[i] = 0;
13480 #if DEBUG == 2
13481         debug = 1;
13482 #endif
13483         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13484         if (xminusc) {
13485                 minusc = *xargv++;
13486                 if (*xargv)
13487                         goto setarg0;
13488         } else if (!sflag) {
13489                 setinputfile(*xargv, 0);
13490  setarg0:
13491                 arg0 = *xargv++;
13492                 commandname = arg0;
13493         }
13494
13495         shellparam.p = xargv;
13496 #if ENABLE_ASH_GETOPTS
13497         shellparam.optind = 1;
13498         shellparam.optoff = -1;
13499 #endif
13500         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13501         while (*xargv) {
13502                 shellparam.nparam++;
13503                 xargv++;
13504         }
13505         optschanged();
13506 }
13507
13508 /*
13509  * Read /etc/profile, ~/.profile, $ENV.
13510  */
13511 static void
13512 read_profile(const char *name)
13513 {
13514         name = expandstr(name);
13515         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13516                 return;
13517         cmdloop(0);
13518         popfile();
13519 }
13520
13521 /*
13522  * This routine is called when an error or an interrupt occurs in an
13523  * interactive shell and control is returned to the main command loop.
13524  * (In dash, this function is auto-generated by build machinery).
13525  */
13526 static void
13527 reset(void)
13528 {
13529         /* from eval.c: */
13530         evalskip = 0;
13531         loopnest = 0;
13532
13533         /* from expand.c: */
13534         ifsfree();
13535
13536         /* from input.c: */
13537         g_parsefile->left_in_buffer = 0;
13538         g_parsefile->left_in_line = 0;      /* clear input buffer */
13539         popallfiles();
13540
13541         /* from redir.c: */
13542         while (redirlist)
13543                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13544 }
13545
13546 #if PROFILE
13547 static short profile_buf[16384];
13548 extern int etext();
13549 #endif
13550
13551 /*
13552  * Main routine.  We initialize things, parse the arguments, execute
13553  * profiles if we're a login shell, and then call cmdloop to execute
13554  * commands.  The setjmp call sets up the location to jump to when an
13555  * exception occurs.  When an exception occurs the variable "state"
13556  * is used to figure out how far we had gotten.
13557  */
13558 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13559 int ash_main(int argc UNUSED_PARAM, char **argv)
13560 {
13561         volatile smallint state;
13562         struct jmploc jmploc;
13563         struct stackmark smark;
13564
13565         /* Initialize global data */
13566         INIT_G_misc();
13567         INIT_G_memstack();
13568         INIT_G_var();
13569 #if ENABLE_ASH_ALIAS
13570         INIT_G_alias();
13571 #endif
13572         INIT_G_cmdtable();
13573
13574 #if PROFILE
13575         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13576 #endif
13577
13578 #if ENABLE_FEATURE_EDITING
13579         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13580 #endif
13581         state = 0;
13582         if (setjmp(jmploc.loc)) {
13583                 smallint e;
13584                 smallint s;
13585
13586                 reset();
13587
13588                 e = exception_type;
13589                 s = state;
13590                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13591                         exitshell();
13592                 }
13593                 if (e == EXINT) {
13594                         newline_and_flush(stderr);
13595                 }
13596
13597                 popstackmark(&smark);
13598                 FORCE_INT_ON; /* enable interrupts */
13599                 if (s == 1)
13600                         goto state1;
13601                 if (s == 2)
13602                         goto state2;
13603                 if (s == 3)
13604                         goto state3;
13605                 goto state4;
13606         }
13607         exception_handler = &jmploc;
13608         rootpid = getpid();
13609
13610         init();
13611         setstackmark(&smark);
13612         procargs(argv);
13613 #if DEBUG
13614         TRACE(("Shell args: "));
13615         trace_puts_args(argv);
13616 #endif
13617
13618         if (argv[0] && argv[0][0] == '-')
13619                 isloginsh = 1;
13620         if (isloginsh) {
13621                 const char *hp;
13622
13623                 state = 1;
13624                 read_profile("/etc/profile");
13625  state1:
13626                 state = 2;
13627                 hp = lookupvar("HOME");
13628                 if (hp)
13629                         read_profile("$HOME/.profile");
13630         }
13631  state2:
13632         state = 3;
13633         if (
13634 #ifndef linux
13635          getuid() == geteuid() && getgid() == getegid() &&
13636 #endif
13637          iflag
13638         ) {
13639                 const char *shinit = lookupvar("ENV");
13640                 if (shinit != NULL && *shinit != '\0')
13641                         read_profile(shinit);
13642         }
13643         popstackmark(&smark);
13644  state3:
13645         state = 4;
13646         if (minusc) {
13647                 /* evalstring pushes parsefile stack.
13648                  * Ensure we don't falsely claim that 0 (stdin)
13649                  * is one of stacked source fds.
13650                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13651                 // if (!sflag) g_parsefile->pf_fd = -1;
13652                 // ^^ not necessary since now we special-case fd 0
13653                 // in is_hidden_fd() to not be considered "hidden fd"
13654                 evalstring(minusc, 0);
13655         }
13656
13657         if (sflag || minusc == NULL) {
13658 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13659                 if (iflag) {
13660                         const char *hp = lookupvar("HISTFILE");
13661                         if (!hp) {
13662                                 hp = lookupvar("HOME");
13663                                 if (hp) {
13664                                         INT_OFF;
13665                                         hp = concat_path_file(hp, ".ash_history");
13666                                         setvar0("HISTFILE", hp);
13667                                         free((char*)hp);
13668                                         INT_ON;
13669                                         hp = lookupvar("HISTFILE");
13670                                 }
13671                         }
13672                         if (hp)
13673                                 line_input_state->hist_file = hp;
13674 # if ENABLE_FEATURE_SH_HISTFILESIZE
13675                         hp = lookupvar("HISTFILESIZE");
13676                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13677 # endif
13678                 }
13679 #endif
13680  state4: /* XXX ??? - why isn't this before the "if" statement */
13681                 cmdloop(1);
13682         }
13683 #if PROFILE
13684         monitor(0);
13685 #endif
13686 #ifdef GPROF
13687         {
13688                 extern void _mcleanup(void);
13689                 _mcleanup();
13690         }
13691 #endif
13692         TRACE(("End of main reached\n"));
13693         exitshell();
13694         /* NOTREACHED */
13695 }
13696
13697
13698 /*-
13699  * Copyright (c) 1989, 1991, 1993, 1994
13700  *      The Regents of the University of California.  All rights reserved.
13701  *
13702  * This code is derived from software contributed to Berkeley by
13703  * Kenneth Almquist.
13704  *
13705  * Redistribution and use in source and binary forms, with or without
13706  * modification, are permitted provided that the following conditions
13707  * are met:
13708  * 1. Redistributions of source code must retain the above copyright
13709  *    notice, this list of conditions and the following disclaimer.
13710  * 2. Redistributions in binary form must reproduce the above copyright
13711  *    notice, this list of conditions and the following disclaimer in the
13712  *    documentation and/or other materials provided with the distribution.
13713  * 3. Neither the name of the University nor the names of its contributors
13714  *    may be used to endorse or promote products derived from this software
13715  *    without specific prior written permission.
13716  *
13717  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13718  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13719  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13720  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13721  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13722  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13723  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13724  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13725  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13726  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13727  * SUCH DAMAGE.
13728  */