ash: make shellexec capable of using separate argv[0] and filename to exec
[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 *prog, char **argv, const char *path, int idx) NORETURN;
7748 static void shellexec(char *prog, char **argv, const char *path, int idx)
7749 {
7750         char *cmdname;
7751         int e;
7752         char **envp;
7753         int exerrno;
7754         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7755
7756         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7757         if (strchr(prog, '/') != NULL
7758 #if ENABLE_FEATURE_SH_STANDALONE
7759          || (applet_no = find_applet_by_name(prog)) >= 0
7760 #endif
7761         ) {
7762                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7763                 if (applet_no >= 0) {
7764                         /* We tried execing ourself, but it didn't work.
7765                          * Maybe /proc/self/exe doesn't exist?
7766                          * Try $PATH search.
7767                          */
7768                         goto try_PATH;
7769                 }
7770                 e = errno;
7771         } else {
7772  try_PATH:
7773                 e = ENOENT;
7774                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7775                         if (--idx < 0 && pathopt == NULL) {
7776                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7777                                 if (errno != ENOENT && errno != ENOTDIR)
7778                                         e = errno;
7779                         }
7780                         stunalloc(cmdname);
7781                 }
7782         }
7783
7784         /* Map to POSIX errors */
7785         switch (e) {
7786         case EACCES:
7787                 exerrno = 126;
7788                 break;
7789         case ENOENT:
7790                 exerrno = 127;
7791                 break;
7792         default:
7793                 exerrno = 2;
7794                 break;
7795         }
7796         exitstatus = exerrno;
7797         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7798                 prog, e, suppress_int));
7799         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7800         /* NOTREACHED */
7801 }
7802
7803 static void
7804 printentry(struct tblentry *cmdp)
7805 {
7806         int idx;
7807         const char *path;
7808         char *name;
7809
7810         idx = cmdp->param.index;
7811         path = pathval();
7812         do {
7813                 name = path_advance(&path, cmdp->cmdname);
7814                 stunalloc(name);
7815         } while (--idx >= 0);
7816         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7817 }
7818
7819 /*
7820  * Clear out command entries.  The argument specifies the first entry in
7821  * PATH which has changed.
7822  */
7823 static void
7824 clearcmdentry(int firstchange)
7825 {
7826         struct tblentry **tblp;
7827         struct tblentry **pp;
7828         struct tblentry *cmdp;
7829
7830         INT_OFF;
7831         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7832                 pp = tblp;
7833                 while ((cmdp = *pp) != NULL) {
7834                         if ((cmdp->cmdtype == CMDNORMAL &&
7835                              cmdp->param.index >= firstchange)
7836                          || (cmdp->cmdtype == CMDBUILTIN &&
7837                              builtinloc >= firstchange)
7838                         ) {
7839                                 *pp = cmdp->next;
7840                                 free(cmdp);
7841                         } else {
7842                                 pp = &cmdp->next;
7843                         }
7844                 }
7845         }
7846         INT_ON;
7847 }
7848
7849 /*
7850  * Locate a command in the command hash table.  If "add" is nonzero,
7851  * add the command to the table if it is not already present.  The
7852  * variable "lastcmdentry" is set to point to the address of the link
7853  * pointing to the entry, so that delete_cmd_entry can delete the
7854  * entry.
7855  *
7856  * Interrupts must be off if called with add != 0.
7857  */
7858 static struct tblentry **lastcmdentry;
7859
7860 static struct tblentry *
7861 cmdlookup(const char *name, int add)
7862 {
7863         unsigned int hashval;
7864         const char *p;
7865         struct tblentry *cmdp;
7866         struct tblentry **pp;
7867
7868         p = name;
7869         hashval = (unsigned char)*p << 4;
7870         while (*p)
7871                 hashval += (unsigned char)*p++;
7872         hashval &= 0x7FFF;
7873         pp = &cmdtable[hashval % CMDTABLESIZE];
7874         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7875                 if (strcmp(cmdp->cmdname, name) == 0)
7876                         break;
7877                 pp = &cmdp->next;
7878         }
7879         if (add && cmdp == NULL) {
7880                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7881                                 + strlen(name)
7882                                 /* + 1 - already done because
7883                                  * tblentry::cmdname is char[1] */);
7884                 /*cmdp->next = NULL; - ckzalloc did it */
7885                 cmdp->cmdtype = CMDUNKNOWN;
7886                 strcpy(cmdp->cmdname, name);
7887         }
7888         lastcmdentry = pp;
7889         return cmdp;
7890 }
7891
7892 /*
7893  * Delete the command entry returned on the last lookup.
7894  */
7895 static void
7896 delete_cmd_entry(void)
7897 {
7898         struct tblentry *cmdp;
7899
7900         INT_OFF;
7901         cmdp = *lastcmdentry;
7902         *lastcmdentry = cmdp->next;
7903         if (cmdp->cmdtype == CMDFUNCTION)
7904                 freefunc(cmdp->param.func);
7905         free(cmdp);
7906         INT_ON;
7907 }
7908
7909 /*
7910  * Add a new command entry, replacing any existing command entry for
7911  * the same name - except special builtins.
7912  */
7913 static void
7914 addcmdentry(char *name, struct cmdentry *entry)
7915 {
7916         struct tblentry *cmdp;
7917
7918         cmdp = cmdlookup(name, 1);
7919         if (cmdp->cmdtype == CMDFUNCTION) {
7920                 freefunc(cmdp->param.func);
7921         }
7922         cmdp->cmdtype = entry->cmdtype;
7923         cmdp->param = entry->u;
7924         cmdp->rehash = 0;
7925 }
7926
7927 static int FAST_FUNC
7928 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7929 {
7930         struct tblentry **pp;
7931         struct tblentry *cmdp;
7932         int c;
7933         struct cmdentry entry;
7934         char *name;
7935
7936         if (nextopt("r") != '\0') {
7937                 clearcmdentry(0);
7938                 return 0;
7939         }
7940
7941         if (*argptr == NULL) {
7942                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7943                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7944                                 if (cmdp->cmdtype == CMDNORMAL)
7945                                         printentry(cmdp);
7946                         }
7947                 }
7948                 return 0;
7949         }
7950
7951         c = 0;
7952         while ((name = *argptr) != NULL) {
7953                 cmdp = cmdlookup(name, 0);
7954                 if (cmdp != NULL
7955                  && (cmdp->cmdtype == CMDNORMAL
7956                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7957                 ) {
7958                         delete_cmd_entry();
7959                 }
7960                 find_command(name, &entry, DO_ERR, pathval());
7961                 if (entry.cmdtype == CMDUNKNOWN)
7962                         c = 1;
7963                 argptr++;
7964         }
7965         return c;
7966 }
7967
7968 /*
7969  * Called when a cd is done.  Marks all commands so the next time they
7970  * are executed they will be rehashed.
7971  */
7972 static void
7973 hashcd(void)
7974 {
7975         struct tblentry **pp;
7976         struct tblentry *cmdp;
7977
7978         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7979                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7980                         if (cmdp->cmdtype == CMDNORMAL
7981                          || (cmdp->cmdtype == CMDBUILTIN
7982                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7983                              && builtinloc > 0)
7984                         ) {
7985                                 cmdp->rehash = 1;
7986                         }
7987                 }
7988         }
7989 }
7990
7991 /*
7992  * Fix command hash table when PATH changed.
7993  * Called before PATH is changed.  The argument is the new value of PATH;
7994  * pathval() still returns the old value at this point.
7995  * Called with interrupts off.
7996  */
7997 static void FAST_FUNC
7998 changepath(const char *new)
7999 {
8000         const char *old;
8001         int firstchange;
8002         int idx;
8003         int idx_bltin;
8004
8005         old = pathval();
8006         firstchange = 9999;     /* assume no change */
8007         idx = 0;
8008         idx_bltin = -1;
8009         for (;;) {
8010                 if (*old != *new) {
8011                         firstchange = idx;
8012                         if ((*old == '\0' && *new == ':')
8013                          || (*old == ':' && *new == '\0')
8014                         ) {
8015                                 firstchange++;
8016                         }
8017                         old = new;      /* ignore subsequent differences */
8018                 }
8019                 if (*new == '\0')
8020                         break;
8021                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8022                         idx_bltin = idx;
8023                 if (*new == ':')
8024                         idx++;
8025                 new++;
8026                 old++;
8027         }
8028         if (builtinloc < 0 && idx_bltin >= 0)
8029                 builtinloc = idx_bltin;             /* zap builtins */
8030         if (builtinloc >= 0 && idx_bltin < 0)
8031                 firstchange = 0;
8032         clearcmdentry(firstchange);
8033         builtinloc = idx_bltin;
8034 }
8035 enum {
8036         TEOF,
8037         TNL,
8038         TREDIR,
8039         TWORD,
8040         TSEMI,
8041         TBACKGND,
8042         TAND,
8043         TOR,
8044         TPIPE,
8045         TLP,
8046         TRP,
8047         TENDCASE,
8048         TENDBQUOTE,
8049         TNOT,
8050         TCASE,
8051         TDO,
8052         TDONE,
8053         TELIF,
8054         TELSE,
8055         TESAC,
8056         TFI,
8057         TFOR,
8058 #if BASH_FUNCTION
8059         TFUNCTION,
8060 #endif
8061         TIF,
8062         TIN,
8063         TTHEN,
8064         TUNTIL,
8065         TWHILE,
8066         TBEGIN,
8067         TEND
8068 };
8069 typedef smallint token_id_t;
8070
8071 /* Nth bit indicates if token marks the end of a list */
8072 enum {
8073         tokendlist = 0
8074         /*  0 */ | (1u << TEOF)
8075         /*  1 */ | (0u << TNL)
8076         /*  2 */ | (0u << TREDIR)
8077         /*  3 */ | (0u << TWORD)
8078         /*  4 */ | (0u << TSEMI)
8079         /*  5 */ | (0u << TBACKGND)
8080         /*  6 */ | (0u << TAND)
8081         /*  7 */ | (0u << TOR)
8082         /*  8 */ | (0u << TPIPE)
8083         /*  9 */ | (0u << TLP)
8084         /* 10 */ | (1u << TRP)
8085         /* 11 */ | (1u << TENDCASE)
8086         /* 12 */ | (1u << TENDBQUOTE)
8087         /* 13 */ | (0u << TNOT)
8088         /* 14 */ | (0u << TCASE)
8089         /* 15 */ | (1u << TDO)
8090         /* 16 */ | (1u << TDONE)
8091         /* 17 */ | (1u << TELIF)
8092         /* 18 */ | (1u << TELSE)
8093         /* 19 */ | (1u << TESAC)
8094         /* 20 */ | (1u << TFI)
8095         /* 21 */ | (0u << TFOR)
8096 #if BASH_FUNCTION
8097         /* 22 */ | (0u << TFUNCTION)
8098 #endif
8099         /* 23 */ | (0u << TIF)
8100         /* 24 */ | (0u << TIN)
8101         /* 25 */ | (1u << TTHEN)
8102         /* 26 */ | (0u << TUNTIL)
8103         /* 27 */ | (0u << TWHILE)
8104         /* 28 */ | (0u << TBEGIN)
8105         /* 29 */ | (1u << TEND)
8106         , /* thus far 29 bits used */
8107 };
8108
8109 static const char *const tokname_array[] = {
8110         "end of file",
8111         "newline",
8112         "redirection",
8113         "word",
8114         ";",
8115         "&",
8116         "&&",
8117         "||",
8118         "|",
8119         "(",
8120         ")",
8121         ";;",
8122         "`",
8123 #define KWDOFFSET 13
8124         /* the following are keywords */
8125         "!",
8126         "case",
8127         "do",
8128         "done",
8129         "elif",
8130         "else",
8131         "esac",
8132         "fi",
8133         "for",
8134 #if BASH_FUNCTION
8135         "function",
8136 #endif
8137         "if",
8138         "in",
8139         "then",
8140         "until",
8141         "while",
8142         "{",
8143         "}",
8144 };
8145
8146 /* Wrapper around strcmp for qsort/bsearch/... */
8147 static int
8148 pstrcmp(const void *a, const void *b)
8149 {
8150         return strcmp((char*)a, *(char**)b);
8151 }
8152
8153 static const char *const *
8154 findkwd(const char *s)
8155 {
8156         return bsearch(s, tokname_array + KWDOFFSET,
8157                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8158                         sizeof(tokname_array[0]), pstrcmp);
8159 }
8160
8161 /*
8162  * Locate and print what a word is...
8163  */
8164 static int
8165 describe_command(char *command, const char *path, int describe_command_verbose)
8166 {
8167         struct cmdentry entry;
8168         struct tblentry *cmdp;
8169 #if ENABLE_ASH_ALIAS
8170         const struct alias *ap;
8171 #endif
8172
8173         path = path ? path : pathval();
8174
8175         if (describe_command_verbose) {
8176                 out1str(command);
8177         }
8178
8179         /* First look at the keywords */
8180         if (findkwd(command)) {
8181                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8182                 goto out;
8183         }
8184
8185 #if ENABLE_ASH_ALIAS
8186         /* Then look at the aliases */
8187         ap = lookupalias(command, 0);
8188         if (ap != NULL) {
8189                 if (!describe_command_verbose) {
8190                         out1str("alias ");
8191                         printalias(ap);
8192                         return 0;
8193                 }
8194                 out1fmt(" is an alias for %s", ap->val);
8195                 goto out;
8196         }
8197 #endif
8198         /* Then check if it is a tracked alias */
8199         cmdp = cmdlookup(command, 0);
8200         if (cmdp != NULL) {
8201                 entry.cmdtype = cmdp->cmdtype;
8202                 entry.u = cmdp->param;
8203         } else {
8204                 /* Finally use brute force */
8205                 find_command(command, &entry, DO_ABS, path);
8206         }
8207
8208         switch (entry.cmdtype) {
8209         case CMDNORMAL: {
8210                 int j = entry.u.index;
8211                 char *p;
8212                 if (j < 0) {
8213                         p = command;
8214                 } else {
8215                         do {
8216                                 p = path_advance(&path, command);
8217                                 stunalloc(p);
8218                         } while (--j >= 0);
8219                 }
8220                 if (describe_command_verbose) {
8221                         out1fmt(" is%s %s",
8222                                 (cmdp ? " a tracked alias for" : nullstr), p
8223                         );
8224                 } else {
8225                         out1str(p);
8226                 }
8227                 break;
8228         }
8229
8230         case CMDFUNCTION:
8231                 if (describe_command_verbose) {
8232                         out1str(" is a shell function");
8233                 } else {
8234                         out1str(command);
8235                 }
8236                 break;
8237
8238         case CMDBUILTIN:
8239                 if (describe_command_verbose) {
8240                         out1fmt(" is a %sshell builtin",
8241                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8242                                         "special " : nullstr
8243                         );
8244                 } else {
8245                         out1str(command);
8246                 }
8247                 break;
8248
8249         default:
8250                 if (describe_command_verbose) {
8251                         out1str(": not found\n");
8252                 }
8253                 return 127;
8254         }
8255  out:
8256         out1str("\n");
8257         return 0;
8258 }
8259
8260 static int FAST_FUNC
8261 typecmd(int argc UNUSED_PARAM, char **argv)
8262 {
8263         int i = 1;
8264         int err = 0;
8265         int verbose = 1;
8266
8267         /* type -p ... ? (we don't bother checking for 'p') */
8268         if (argv[1] && argv[1][0] == '-') {
8269                 i++;
8270                 verbose = 0;
8271         }
8272         while (argv[i]) {
8273                 err |= describe_command(argv[i++], NULL, verbose);
8274         }
8275         return err;
8276 }
8277
8278 #if ENABLE_ASH_CMDCMD
8279 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8280 static char **
8281 parse_command_args(char **argv, const char **path)
8282 {
8283         char *cp, c;
8284
8285         for (;;) {
8286                 cp = *++argv;
8287                 if (!cp)
8288                         return NULL;
8289                 if (*cp++ != '-')
8290                         break;
8291                 c = *cp++;
8292                 if (!c)
8293                         break;
8294                 if (c == '-' && !*cp) {
8295                         if (!*++argv)
8296                                 return NULL;
8297                         break;
8298                 }
8299                 do {
8300                         switch (c) {
8301                         case 'p':
8302                                 *path = bb_default_path;
8303                                 break;
8304                         default:
8305                                 /* run 'typecmd' for other options */
8306                                 return NULL;
8307                         }
8308                         c = *cp++;
8309                 } while (c);
8310         }
8311         return argv;
8312 }
8313
8314 static int FAST_FUNC
8315 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8316 {
8317         char *cmd;
8318         int c;
8319         enum {
8320                 VERIFY_BRIEF = 1,
8321                 VERIFY_VERBOSE = 2,
8322         } verify = 0;
8323         const char *path = NULL;
8324
8325         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8326          * never reaches this function.
8327          */
8328
8329         while ((c = nextopt("pvV")) != '\0')
8330                 if (c == 'V')
8331                         verify |= VERIFY_VERBOSE;
8332                 else if (c == 'v')
8333                         /*verify |= VERIFY_BRIEF*/;
8334 #if DEBUG
8335                 else if (c != 'p')
8336                         abort();
8337 #endif
8338                 else
8339                         path = bb_default_path;
8340
8341         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8342         cmd = *argptr;
8343         if (/*verify && */ cmd)
8344                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8345
8346         return 0;
8347 }
8348 #endif
8349
8350
8351 /*static int funcblocksize;     // size of structures in function */
8352 /*static int funcstringsize;    // size of strings in node */
8353 static void *funcblock;         /* block to allocate function from */
8354 static char *funcstring_end;    /* end of block to allocate strings from */
8355
8356 /* flags in argument to evaltree */
8357 #define EV_EXIT    01           /* exit after evaluating tree */
8358 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8359
8360 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8361         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8362         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8363         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8364         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8365         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8366         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8367         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8368         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8369         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8370         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8371         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8372         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8373         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8374         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8375         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8376         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8377         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8378 #if BASH_REDIR_OUTPUT
8379         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8380 #endif
8381         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8382         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8383         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8384         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8385         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8386         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8387         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8388         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8389         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8390 };
8391
8392 static int calcsize(int funcblocksize, union node *n);
8393
8394 static int
8395 sizenodelist(int funcblocksize, struct nodelist *lp)
8396 {
8397         while (lp) {
8398                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8399                 funcblocksize = calcsize(funcblocksize, lp->n);
8400                 lp = lp->next;
8401         }
8402         return funcblocksize;
8403 }
8404
8405 static int
8406 calcsize(int funcblocksize, union node *n)
8407 {
8408         if (n == NULL)
8409                 return funcblocksize;
8410         funcblocksize += nodesize[n->type];
8411         switch (n->type) {
8412         case NCMD:
8413                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8414                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8415                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8416                 break;
8417         case NPIPE:
8418                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8419                 break;
8420         case NREDIR:
8421         case NBACKGND:
8422         case NSUBSHELL:
8423                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8424                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8425                 break;
8426         case NAND:
8427         case NOR:
8428         case NSEMI:
8429         case NWHILE:
8430         case NUNTIL:
8431                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8432                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8433                 break;
8434         case NIF:
8435                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8436                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8437                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8438                 break;
8439         case NFOR:
8440                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8441                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8442                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8443                 break;
8444         case NCASE:
8445                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8446                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8447                 break;
8448         case NCLIST:
8449                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8450                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8451                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8452                 break;
8453         case NDEFUN:
8454         case NARG:
8455                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8456                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8457                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8458                 break;
8459         case NTO:
8460 #if BASH_REDIR_OUTPUT
8461         case NTO2:
8462 #endif
8463         case NCLOBBER:
8464         case NFROM:
8465         case NFROMTO:
8466         case NAPPEND:
8467                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8468                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8469                 break;
8470         case NTOFD:
8471         case NFROMFD:
8472                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8473                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8474         break;
8475         case NHERE:
8476         case NXHERE:
8477                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8478                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8479                 break;
8480         case NNOT:
8481                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8482                 break;
8483         };
8484         return funcblocksize;
8485 }
8486
8487 static char *
8488 nodeckstrdup(char *s)
8489 {
8490         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8491         return strcpy(funcstring_end, s);
8492 }
8493
8494 static union node *copynode(union node *);
8495
8496 static struct nodelist *
8497 copynodelist(struct nodelist *lp)
8498 {
8499         struct nodelist *start;
8500         struct nodelist **lpp;
8501
8502         lpp = &start;
8503         while (lp) {
8504                 *lpp = funcblock;
8505                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8506                 (*lpp)->n = copynode(lp->n);
8507                 lp = lp->next;
8508                 lpp = &(*lpp)->next;
8509         }
8510         *lpp = NULL;
8511         return start;
8512 }
8513
8514 static union node *
8515 copynode(union node *n)
8516 {
8517         union node *new;
8518
8519         if (n == NULL)
8520                 return NULL;
8521         new = funcblock;
8522         funcblock = (char *) funcblock + nodesize[n->type];
8523
8524         switch (n->type) {
8525         case NCMD:
8526                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8527                 new->ncmd.args = copynode(n->ncmd.args);
8528                 new->ncmd.assign = copynode(n->ncmd.assign);
8529                 break;
8530         case NPIPE:
8531                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8532                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8533                 break;
8534         case NREDIR:
8535         case NBACKGND:
8536         case NSUBSHELL:
8537                 new->nredir.redirect = copynode(n->nredir.redirect);
8538                 new->nredir.n = copynode(n->nredir.n);
8539                 break;
8540         case NAND:
8541         case NOR:
8542         case NSEMI:
8543         case NWHILE:
8544         case NUNTIL:
8545                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8546                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8547                 break;
8548         case NIF:
8549                 new->nif.elsepart = copynode(n->nif.elsepart);
8550                 new->nif.ifpart = copynode(n->nif.ifpart);
8551                 new->nif.test = copynode(n->nif.test);
8552                 break;
8553         case NFOR:
8554                 new->nfor.var = nodeckstrdup(n->nfor.var);
8555                 new->nfor.body = copynode(n->nfor.body);
8556                 new->nfor.args = copynode(n->nfor.args);
8557                 break;
8558         case NCASE:
8559                 new->ncase.cases = copynode(n->ncase.cases);
8560                 new->ncase.expr = copynode(n->ncase.expr);
8561                 break;
8562         case NCLIST:
8563                 new->nclist.body = copynode(n->nclist.body);
8564                 new->nclist.pattern = copynode(n->nclist.pattern);
8565                 new->nclist.next = copynode(n->nclist.next);
8566                 break;
8567         case NDEFUN:
8568         case NARG:
8569                 new->narg.backquote = copynodelist(n->narg.backquote);
8570                 new->narg.text = nodeckstrdup(n->narg.text);
8571                 new->narg.next = copynode(n->narg.next);
8572                 break;
8573         case NTO:
8574 #if BASH_REDIR_OUTPUT
8575         case NTO2:
8576 #endif
8577         case NCLOBBER:
8578         case NFROM:
8579         case NFROMTO:
8580         case NAPPEND:
8581                 new->nfile.fname = copynode(n->nfile.fname);
8582                 new->nfile.fd = n->nfile.fd;
8583                 new->nfile.next = copynode(n->nfile.next);
8584                 break;
8585         case NTOFD:
8586         case NFROMFD:
8587                 new->ndup.vname = copynode(n->ndup.vname);
8588                 new->ndup.dupfd = n->ndup.dupfd;
8589                 new->ndup.fd = n->ndup.fd;
8590                 new->ndup.next = copynode(n->ndup.next);
8591                 break;
8592         case NHERE:
8593         case NXHERE:
8594                 new->nhere.doc = copynode(n->nhere.doc);
8595                 new->nhere.fd = n->nhere.fd;
8596                 new->nhere.next = copynode(n->nhere.next);
8597                 break;
8598         case NNOT:
8599                 new->nnot.com = copynode(n->nnot.com);
8600                 break;
8601         };
8602         new->type = n->type;
8603         return new;
8604 }
8605
8606 /*
8607  * Make a copy of a parse tree.
8608  */
8609 static struct funcnode *
8610 copyfunc(union node *n)
8611 {
8612         struct funcnode *f;
8613         size_t blocksize;
8614
8615         /*funcstringsize = 0;*/
8616         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8617         f = ckzalloc(blocksize /* + funcstringsize */);
8618         funcblock = (char *) f + offsetof(struct funcnode, n);
8619         funcstring_end = (char *) f + blocksize;
8620         copynode(n);
8621         /* f->count = 0; - ckzalloc did it */
8622         return f;
8623 }
8624
8625 /*
8626  * Define a shell function.
8627  */
8628 static void
8629 defun(union node *func)
8630 {
8631         struct cmdentry entry;
8632
8633         INT_OFF;
8634         entry.cmdtype = CMDFUNCTION;
8635         entry.u.func = copyfunc(func);
8636         addcmdentry(func->narg.text, &entry);
8637         INT_ON;
8638 }
8639
8640 /* Reasons for skipping commands (see comment on breakcmd routine) */
8641 #define SKIPBREAK      (1 << 0)
8642 #define SKIPCONT       (1 << 1)
8643 #define SKIPFUNC       (1 << 2)
8644 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8645 static int skipcount;           /* number of levels to skip */
8646 static int funcnest;            /* depth of function calls */
8647 static int loopnest;            /* current loop nesting level */
8648
8649 /* Forward decl way out to parsing code - dotrap needs it */
8650 static int evalstring(char *s, int flags);
8651
8652 /* Called to execute a trap.
8653  * Single callsite - at the end of evaltree().
8654  * If we return non-zero, evaltree raises EXEXIT exception.
8655  *
8656  * Perhaps we should avoid entering new trap handlers
8657  * while we are executing a trap handler. [is it a TODO?]
8658  */
8659 static void
8660 dotrap(void)
8661 {
8662         uint8_t *g;
8663         int sig;
8664         uint8_t last_status;
8665
8666         if (!pending_sig)
8667                 return;
8668
8669         last_status = exitstatus;
8670         pending_sig = 0;
8671         barrier();
8672
8673         TRACE(("dotrap entered\n"));
8674         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8675                 char *p;
8676
8677                 if (!*g)
8678                         continue;
8679
8680                 if (evalskip) {
8681                         pending_sig = sig;
8682                         break;
8683                 }
8684
8685                 p = trap[sig];
8686                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8687                  * don't upset it by resetting gotsig[SIGINT-1] */
8688                 if (sig == SIGINT && !p)
8689                         continue;
8690
8691                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8692                 *g = 0;
8693                 if (!p)
8694                         continue;
8695                 evalstring(p, 0);
8696         }
8697         exitstatus = last_status;
8698         TRACE(("dotrap returns\n"));
8699 }
8700
8701 /* forward declarations - evaluation is fairly recursive business... */
8702 static int evalloop(union node *, int);
8703 static int evalfor(union node *, int);
8704 static int evalcase(union node *, int);
8705 static int evalsubshell(union node *, int);
8706 static void expredir(union node *);
8707 static int evalpipe(union node *, int);
8708 static int evalcommand(union node *, int);
8709 static int evalbltin(const struct builtincmd *, int, char **, int);
8710 static void prehash(union node *);
8711
8712 /*
8713  * Evaluate a parse tree.  The value is left in the global variable
8714  * exitstatus.
8715  */
8716 static int
8717 evaltree(union node *n, int flags)
8718 {
8719         int checkexit = 0;
8720         int (*evalfn)(union node *, int);
8721         int status = 0;
8722
8723         if (n == NULL) {
8724                 TRACE(("evaltree(NULL) called\n"));
8725                 goto out;
8726         }
8727         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8728
8729         dotrap();
8730
8731         switch (n->type) {
8732         default:
8733 #if DEBUG
8734                 out1fmt("Node type = %d\n", n->type);
8735                 fflush_all();
8736                 break;
8737 #endif
8738         case NNOT:
8739                 status = !evaltree(n->nnot.com, EV_TESTED);
8740                 goto setstatus;
8741         case NREDIR:
8742                 expredir(n->nredir.redirect);
8743                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8744                 if (!status) {
8745                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8746                 }
8747                 if (n->nredir.redirect)
8748                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8749                 goto setstatus;
8750         case NCMD:
8751                 evalfn = evalcommand;
8752  checkexit:
8753                 if (eflag && !(flags & EV_TESTED))
8754                         checkexit = ~0;
8755                 goto calleval;
8756         case NFOR:
8757                 evalfn = evalfor;
8758                 goto calleval;
8759         case NWHILE:
8760         case NUNTIL:
8761                 evalfn = evalloop;
8762                 goto calleval;
8763         case NSUBSHELL:
8764         case NBACKGND:
8765                 evalfn = evalsubshell;
8766                 goto checkexit;
8767         case NPIPE:
8768                 evalfn = evalpipe;
8769                 goto checkexit;
8770         case NCASE:
8771                 evalfn = evalcase;
8772                 goto calleval;
8773         case NAND:
8774         case NOR:
8775         case NSEMI: {
8776
8777 #if NAND + 1 != NOR
8778 #error NAND + 1 != NOR
8779 #endif
8780 #if NOR + 1 != NSEMI
8781 #error NOR + 1 != NSEMI
8782 #endif
8783                 unsigned is_or = n->type - NAND;
8784                 status = evaltree(
8785                         n->nbinary.ch1,
8786                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8787                 );
8788                 if ((!status) == is_or || evalskip)
8789                         break;
8790                 n = n->nbinary.ch2;
8791  evaln:
8792                 evalfn = evaltree;
8793  calleval:
8794                 status = evalfn(n, flags);
8795                 goto setstatus;
8796         }
8797         case NIF:
8798                 status = evaltree(n->nif.test, EV_TESTED);
8799                 if (evalskip)
8800                         break;
8801                 if (!status) {
8802                         n = n->nif.ifpart;
8803                         goto evaln;
8804                 }
8805                 if (n->nif.elsepart) {
8806                         n = n->nif.elsepart;
8807                         goto evaln;
8808                 }
8809                 status = 0;
8810                 goto setstatus;
8811         case NDEFUN:
8812                 defun(n);
8813                 /* Not necessary. To test it:
8814                  * "false; f() { qwerty; }; echo $?" should print 0.
8815                  */
8816                 /* status = 0; */
8817  setstatus:
8818                 exitstatus = status;
8819                 break;
8820         }
8821  out:
8822         /* Order of checks below is important:
8823          * signal handlers trigger before exit caused by "set -e".
8824          */
8825         dotrap();
8826
8827         if (checkexit & status)
8828                 raise_exception(EXEXIT);
8829         if (flags & EV_EXIT)
8830                 raise_exception(EXEXIT);
8831
8832         TRACE(("leaving evaltree (no interrupts)\n"));
8833         return exitstatus;
8834 }
8835
8836 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8837 static
8838 #endif
8839 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8840
8841 static int
8842 skiploop(void)
8843 {
8844         int skip = evalskip;
8845
8846         switch (skip) {
8847         case 0:
8848                 break;
8849         case SKIPBREAK:
8850         case SKIPCONT:
8851                 if (--skipcount <= 0) {
8852                         evalskip = 0;
8853                         break;
8854                 }
8855                 skip = SKIPBREAK;
8856                 break;
8857         }
8858         return skip;
8859 }
8860
8861 static int
8862 evalloop(union node *n, int flags)
8863 {
8864         int skip;
8865         int status;
8866
8867         loopnest++;
8868         status = 0;
8869         flags &= EV_TESTED;
8870         do {
8871                 int i;
8872
8873                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8874                 skip = skiploop();
8875                 if (skip == SKIPFUNC)
8876                         status = i;
8877                 if (skip)
8878                         continue;
8879                 if (n->type != NWHILE)
8880                         i = !i;
8881                 if (i != 0)
8882                         break;
8883                 status = evaltree(n->nbinary.ch2, flags);
8884                 skip = skiploop();
8885         } while (!(skip & ~SKIPCONT));
8886         loopnest--;
8887
8888         return status;
8889 }
8890
8891 static int
8892 evalfor(union node *n, int flags)
8893 {
8894         struct arglist arglist;
8895         union node *argp;
8896         struct strlist *sp;
8897         struct stackmark smark;
8898         int status = 0;
8899
8900         setstackmark(&smark);
8901         arglist.list = NULL;
8902         arglist.lastp = &arglist.list;
8903         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8904                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8905         }
8906         *arglist.lastp = NULL;
8907
8908         loopnest++;
8909         flags &= EV_TESTED;
8910         for (sp = arglist.list; sp; sp = sp->next) {
8911                 setvar0(n->nfor.var, sp->text);
8912                 status = evaltree(n->nfor.body, flags);
8913                 if (skiploop() & ~SKIPCONT)
8914                         break;
8915         }
8916         loopnest--;
8917         popstackmark(&smark);
8918
8919         return status;
8920 }
8921
8922 static int
8923 evalcase(union node *n, int flags)
8924 {
8925         union node *cp;
8926         union node *patp;
8927         struct arglist arglist;
8928         struct stackmark smark;
8929         int status = 0;
8930
8931         setstackmark(&smark);
8932         arglist.list = NULL;
8933         arglist.lastp = &arglist.list;
8934         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8935         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8936                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8937                         if (casematch(patp, arglist.list->text)) {
8938                                 /* Ensure body is non-empty as otherwise
8939                                  * EV_EXIT may prevent us from setting the
8940                                  * exit status.
8941                                  */
8942                                 if (evalskip == 0 && cp->nclist.body) {
8943                                         status = evaltree(cp->nclist.body, flags);
8944                                 }
8945                                 goto out;
8946                         }
8947                 }
8948         }
8949  out:
8950         popstackmark(&smark);
8951
8952         return status;
8953 }
8954
8955 /*
8956  * Kick off a subshell to evaluate a tree.
8957  */
8958 static int
8959 evalsubshell(union node *n, int flags)
8960 {
8961         struct job *jp;
8962         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8963         int status;
8964
8965         expredir(n->nredir.redirect);
8966         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8967                 goto nofork;
8968         INT_OFF;
8969         if (backgnd == FORK_FG)
8970                 get_tty_state();
8971         jp = makejob(/*n,*/ 1);
8972         if (forkshell(jp, n, backgnd) == 0) {
8973                 /* child */
8974                 INT_ON;
8975                 flags |= EV_EXIT;
8976                 if (backgnd)
8977                         flags &= ~EV_TESTED;
8978  nofork:
8979                 redirect(n->nredir.redirect, 0);
8980                 evaltreenr(n->nredir.n, flags);
8981                 /* never returns */
8982         }
8983         /* parent */
8984         status = 0;
8985         if (backgnd == FORK_FG)
8986                 status = waitforjob(jp);
8987         INT_ON;
8988         return status;
8989 }
8990
8991 /*
8992  * Compute the names of the files in a redirection list.
8993  */
8994 static void fixredir(union node *, const char *, int);
8995 static void
8996 expredir(union node *n)
8997 {
8998         union node *redir;
8999
9000         for (redir = n; redir; redir = redir->nfile.next) {
9001                 struct arglist fn;
9002
9003                 fn.list = NULL;
9004                 fn.lastp = &fn.list;
9005                 switch (redir->type) {
9006                 case NFROMTO:
9007                 case NFROM:
9008                 case NTO:
9009 #if BASH_REDIR_OUTPUT
9010                 case NTO2:
9011 #endif
9012                 case NCLOBBER:
9013                 case NAPPEND:
9014                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9015                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9016 #if BASH_REDIR_OUTPUT
9017  store_expfname:
9018 #endif
9019 #if 0
9020 // By the design of stack allocator, the loop of this kind:
9021 //      while true; do while true; do break; done </dev/null; done
9022 // will look like a memory leak: ash plans to free expfname's
9023 // of "/dev/null" as soon as it finishes running the loop
9024 // (in this case, never).
9025 // This "fix" is wrong:
9026                         if (redir->nfile.expfname)
9027                                 stunalloc(redir->nfile.expfname);
9028 // It results in corrupted state of stacked allocations.
9029 #endif
9030                         redir->nfile.expfname = fn.list->text;
9031                         break;
9032                 case NFROMFD:
9033                 case NTOFD: /* >& */
9034                         if (redir->ndup.vname) {
9035                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9036                                 if (fn.list == NULL)
9037                                         ash_msg_and_raise_error("redir error");
9038 #if BASH_REDIR_OUTPUT
9039 //FIXME: we used expandarg with different args!
9040                                 if (!isdigit_str9(fn.list->text)) {
9041                                         /* >&file, not >&fd */
9042                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9043                                                 ash_msg_and_raise_error("redir error");
9044                                         redir->type = NTO2;
9045                                         goto store_expfname;
9046                                 }
9047 #endif
9048                                 fixredir(redir, fn.list->text, 1);
9049                         }
9050                         break;
9051                 }
9052         }
9053 }
9054
9055 /*
9056  * Evaluate a pipeline.  All the processes in the pipeline are children
9057  * of the process creating the pipeline.  (This differs from some versions
9058  * of the shell, which make the last process in a pipeline the parent
9059  * of all the rest.)
9060  */
9061 static int
9062 evalpipe(union node *n, int flags)
9063 {
9064         struct job *jp;
9065         struct nodelist *lp;
9066         int pipelen;
9067         int prevfd;
9068         int pip[2];
9069         int status = 0;
9070
9071         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9072         pipelen = 0;
9073         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9074                 pipelen++;
9075         flags |= EV_EXIT;
9076         INT_OFF;
9077         if (n->npipe.pipe_backgnd == 0)
9078                 get_tty_state();
9079         jp = makejob(/*n,*/ pipelen);
9080         prevfd = -1;
9081         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9082                 prehash(lp->n);
9083                 pip[1] = -1;
9084                 if (lp->next) {
9085                         if (pipe(pip) < 0) {
9086                                 close(prevfd);
9087                                 ash_msg_and_raise_error("pipe call failed");
9088                         }
9089                 }
9090                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9091                         /* child */
9092                         INT_ON;
9093                         if (pip[1] >= 0) {
9094                                 close(pip[0]);
9095                         }
9096                         if (prevfd > 0) {
9097                                 dup2(prevfd, 0);
9098                                 close(prevfd);
9099                         }
9100                         if (pip[1] > 1) {
9101                                 dup2(pip[1], 1);
9102                                 close(pip[1]);
9103                         }
9104                         evaltreenr(lp->n, flags);
9105                         /* never returns */
9106                 }
9107                 /* parent */
9108                 if (prevfd >= 0)
9109                         close(prevfd);
9110                 prevfd = pip[0];
9111                 /* Don't want to trigger debugging */
9112                 if (pip[1] != -1)
9113                         close(pip[1]);
9114         }
9115         if (n->npipe.pipe_backgnd == 0) {
9116                 status = waitforjob(jp);
9117                 TRACE(("evalpipe:  job done exit status %d\n", status));
9118         }
9119         INT_ON;
9120
9121         return status;
9122 }
9123
9124 /*
9125  * Controls whether the shell is interactive or not.
9126  */
9127 static void
9128 setinteractive(int on)
9129 {
9130         static smallint is_interactive;
9131
9132         if (++on == is_interactive)
9133                 return;
9134         is_interactive = on;
9135         setsignal(SIGINT);
9136         setsignal(SIGQUIT);
9137         setsignal(SIGTERM);
9138 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9139         if (is_interactive > 1) {
9140                 /* Looks like they want an interactive shell */
9141                 static smallint did_banner;
9142
9143                 if (!did_banner) {
9144                         /* note: ash and hush share this string */
9145                         out1fmt("\n\n%s %s\n"
9146                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9147                                 "\n",
9148                                 bb_banner,
9149                                 "built-in shell (ash)"
9150                         );
9151                         did_banner = 1;
9152                 }
9153         }
9154 #endif
9155 }
9156
9157 static void
9158 optschanged(void)
9159 {
9160 #if DEBUG
9161         opentrace();
9162 #endif
9163         setinteractive(iflag);
9164         setjobctl(mflag);
9165 #if ENABLE_FEATURE_EDITING_VI
9166         if (viflag)
9167                 line_input_state->flags |= VI_MODE;
9168         else
9169                 line_input_state->flags &= ~VI_MODE;
9170 #else
9171         viflag = 0; /* forcibly keep the option off */
9172 #endif
9173 }
9174
9175 static struct localvar *localvars;
9176
9177 /*
9178  * Called after a function returns.
9179  * Interrupts must be off.
9180  */
9181 static void
9182 poplocalvars(void)
9183 {
9184         struct localvar *lvp;
9185         struct var *vp;
9186
9187         while ((lvp = localvars) != NULL) {
9188                 localvars = lvp->next;
9189                 vp = lvp->vp;
9190                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9191                 if (vp == NULL) {       /* $- saved */
9192                         memcpy(optlist, lvp->text, sizeof(optlist));
9193                         free((char*)lvp->text);
9194                         optschanged();
9195                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9196                         unsetvar(vp->var_text);
9197                 } else {
9198                         if (vp->var_func)
9199                                 vp->var_func(var_end(lvp->text));
9200                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9201                                 free((char*)vp->var_text);
9202                         vp->flags = lvp->flags;
9203                         vp->var_text = lvp->text;
9204                 }
9205                 free(lvp);
9206         }
9207 }
9208
9209 static int
9210 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9211 {
9212         volatile struct shparam saveparam;
9213         struct localvar *volatile savelocalvars;
9214         struct jmploc *volatile savehandler;
9215         struct jmploc jmploc;
9216         int e;
9217
9218         saveparam = shellparam;
9219         savelocalvars = localvars;
9220         savehandler = exception_handler;
9221         e = setjmp(jmploc.loc);
9222         if (e) {
9223                 goto funcdone;
9224         }
9225         INT_OFF;
9226         exception_handler = &jmploc;
9227         localvars = NULL;
9228         shellparam.malloced = 0;
9229         func->count++;
9230         funcnest++;
9231         INT_ON;
9232         shellparam.nparam = argc - 1;
9233         shellparam.p = argv + 1;
9234 #if ENABLE_ASH_GETOPTS
9235         shellparam.optind = 1;
9236         shellparam.optoff = -1;
9237 #endif
9238         evaltree(func->n.narg.next, flags & EV_TESTED);
9239  funcdone:
9240         INT_OFF;
9241         funcnest--;
9242         freefunc(func);
9243         poplocalvars();
9244         localvars = savelocalvars;
9245         freeparam(&shellparam);
9246         shellparam = saveparam;
9247         exception_handler = savehandler;
9248         INT_ON;
9249         evalskip &= ~SKIPFUNC;
9250         return e;
9251 }
9252
9253 /*
9254  * Make a variable a local variable.  When a variable is made local, it's
9255  * value and flags are saved in a localvar structure.  The saved values
9256  * will be restored when the shell function returns.  We handle the name
9257  * "-" as a special case: it makes changes to "set +-options" local
9258  * (options will be restored on return from the function).
9259  */
9260 static void
9261 mklocal(char *name)
9262 {
9263         struct localvar *lvp;
9264         struct var **vpp;
9265         struct var *vp;
9266         char *eq = strchr(name, '=');
9267
9268         INT_OFF;
9269         /* Cater for duplicate "local". Examples:
9270          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9271          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9272          */
9273         lvp = localvars;
9274         while (lvp) {
9275                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9276                         if (eq)
9277                                 setvareq(name, 0);
9278                         /* else:
9279                          * it's a duplicate "local VAR" declaration, do nothing
9280                          */
9281                         goto ret;
9282                 }
9283                 lvp = lvp->next;
9284         }
9285
9286         lvp = ckzalloc(sizeof(*lvp));
9287         if (LONE_DASH(name)) {
9288                 char *p;
9289                 p = ckmalloc(sizeof(optlist));
9290                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9291                 vp = NULL;
9292         } else {
9293                 vpp = hashvar(name);
9294                 vp = *findvar(vpp, name);
9295                 if (vp == NULL) {
9296                         /* variable did not exist yet */
9297                         if (eq)
9298                                 setvareq(name, VSTRFIXED);
9299                         else
9300                                 setvar(name, NULL, VSTRFIXED);
9301                         vp = *vpp;      /* the new variable */
9302                         lvp->flags = VUNSET;
9303                 } else {
9304                         lvp->text = vp->var_text;
9305                         lvp->flags = vp->flags;
9306                         /* make sure neither "struct var" nor string gets freed
9307                          * during (un)setting:
9308                          */
9309                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9310                         if (eq)
9311                                 setvareq(name, 0);
9312                         else
9313                                 /* "local VAR" unsets VAR: */
9314                                 setvar0(name, NULL);
9315                 }
9316         }
9317         lvp->vp = vp;
9318         lvp->next = localvars;
9319         localvars = lvp;
9320  ret:
9321         INT_ON;
9322 }
9323
9324 /*
9325  * The "local" command.
9326  */
9327 static int FAST_FUNC
9328 localcmd(int argc UNUSED_PARAM, char **argv)
9329 {
9330         char *name;
9331
9332         if (!funcnest)
9333                 ash_msg_and_raise_error("not in a function");
9334
9335         argv = argptr;
9336         while ((name = *argv++) != NULL) {
9337                 mklocal(name);
9338         }
9339         return 0;
9340 }
9341
9342 static int FAST_FUNC
9343 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9344 {
9345         return 1;
9346 }
9347
9348 static int FAST_FUNC
9349 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9350 {
9351         return 0;
9352 }
9353
9354 static int FAST_FUNC
9355 execcmd(int argc UNUSED_PARAM, char **argv)
9356 {
9357         if (argv[1]) {
9358                 iflag = 0;              /* exit on error */
9359                 mflag = 0;
9360                 optschanged();
9361                 /* We should set up signals for "exec CMD"
9362                  * the same way as for "CMD" without "exec".
9363                  * But optschanged->setinteractive->setsignal
9364                  * still thought we are a root shell. Therefore, for example,
9365                  * SIGQUIT is still set to IGN. Fix it:
9366                  */
9367                 shlvl++;
9368                 setsignal(SIGQUIT);
9369                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9370                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9371                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9372
9373                 shellexec(argv[1], argv + 1, pathval(), 0);
9374                 /* NOTREACHED */
9375         }
9376         return 0;
9377 }
9378
9379 /*
9380  * The return command.
9381  */
9382 static int FAST_FUNC
9383 returncmd(int argc UNUSED_PARAM, char **argv)
9384 {
9385         /*
9386          * If called outside a function, do what ksh does;
9387          * skip the rest of the file.
9388          */
9389         evalskip = SKIPFUNC;
9390         return argv[1] ? number(argv[1]) : exitstatus;
9391 }
9392
9393 /* Forward declarations for builtintab[] */
9394 static int breakcmd(int, char **) FAST_FUNC;
9395 static int dotcmd(int, char **) FAST_FUNC;
9396 static int evalcmd(int, char **, int) FAST_FUNC;
9397 static int exitcmd(int, char **) FAST_FUNC;
9398 static int exportcmd(int, char **) FAST_FUNC;
9399 #if ENABLE_ASH_GETOPTS
9400 static int getoptscmd(int, char **) FAST_FUNC;
9401 #endif
9402 #if ENABLE_ASH_HELP
9403 static int helpcmd(int, char **) FAST_FUNC;
9404 #endif
9405 #if MAX_HISTORY
9406 static int historycmd(int, char **) FAST_FUNC;
9407 #endif
9408 #if ENABLE_FEATURE_SH_MATH
9409 static int letcmd(int, char **) FAST_FUNC;
9410 #endif
9411 static int readcmd(int, char **) FAST_FUNC;
9412 static int setcmd(int, char **) FAST_FUNC;
9413 static int shiftcmd(int, char **) FAST_FUNC;
9414 static int timescmd(int, char **) FAST_FUNC;
9415 static int trapcmd(int, char **) FAST_FUNC;
9416 static int umaskcmd(int, char **) FAST_FUNC;
9417 static int unsetcmd(int, char **) FAST_FUNC;
9418 static int ulimitcmd(int, char **) FAST_FUNC;
9419
9420 #define BUILTIN_NOSPEC          "0"
9421 #define BUILTIN_SPECIAL         "1"
9422 #define BUILTIN_REGULAR         "2"
9423 #define BUILTIN_SPEC_REG        "3"
9424 #define BUILTIN_ASSIGN          "4"
9425 #define BUILTIN_SPEC_ASSG       "5"
9426 #define BUILTIN_REG_ASSG        "6"
9427 #define BUILTIN_SPEC_REG_ASSG   "7"
9428
9429 /* Stubs for calling non-FAST_FUNC's */
9430 #if ENABLE_ASH_ECHO
9431 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9432 #endif
9433 #if ENABLE_ASH_PRINTF
9434 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9435 #endif
9436 #if ENABLE_ASH_TEST || BASH_TEST2
9437 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9438 #endif
9439
9440 /* Keep these in proper order since it is searched via bsearch() */
9441 static const struct builtincmd builtintab[] = {
9442         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9443         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9444 #if ENABLE_ASH_TEST
9445         { BUILTIN_REGULAR       "["       , testcmd    },
9446 #endif
9447 #if BASH_TEST2
9448         { BUILTIN_REGULAR       "[["      , testcmd    },
9449 #endif
9450 #if ENABLE_ASH_ALIAS
9451         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9452 #endif
9453 #if JOBS
9454         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9455 #endif
9456         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9457         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9458         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9459 #if ENABLE_ASH_CMDCMD
9460         { BUILTIN_REGULAR       "command" , commandcmd },
9461 #endif
9462         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9463 #if ENABLE_ASH_ECHO
9464         { BUILTIN_REGULAR       "echo"    , echocmd    },
9465 #endif
9466         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9467         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9468         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9469         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9470         { BUILTIN_REGULAR       "false"   , falsecmd   },
9471 #if JOBS
9472         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9473 #endif
9474 #if ENABLE_ASH_GETOPTS
9475         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9476 #endif
9477         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9478 #if ENABLE_ASH_HELP
9479         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9480 #endif
9481 #if MAX_HISTORY
9482         { BUILTIN_NOSPEC        "history" , historycmd },
9483 #endif
9484 #if JOBS
9485         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9486         { BUILTIN_REGULAR       "kill"    , killcmd    },
9487 #endif
9488 #if ENABLE_FEATURE_SH_MATH
9489         { BUILTIN_NOSPEC        "let"     , letcmd     },
9490 #endif
9491         { BUILTIN_ASSIGN        "local"   , localcmd   },
9492 #if ENABLE_ASH_PRINTF
9493         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9494 #endif
9495         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9496         { BUILTIN_REGULAR       "read"    , readcmd    },
9497         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9498         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9499         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9500         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9501 #if BASH_SOURCE
9502         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9503 #endif
9504 #if ENABLE_ASH_TEST
9505         { BUILTIN_REGULAR       "test"    , testcmd    },
9506 #endif
9507         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9508         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9509         { BUILTIN_REGULAR       "true"    , truecmd    },
9510         { BUILTIN_NOSPEC        "type"    , typecmd    },
9511         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9512         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9513 #if ENABLE_ASH_ALIAS
9514         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9515 #endif
9516         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9517         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9518 };
9519
9520 /* Should match the above table! */
9521 #define COMMANDCMD (builtintab + \
9522         /* . : */       2 + \
9523         /* [ */         1 * ENABLE_ASH_TEST + \
9524         /* [[ */        1 * BASH_TEST2 + \
9525         /* alias */     1 * ENABLE_ASH_ALIAS + \
9526         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9527         /* break cd cddir  */   3)
9528 #define EVALCMD (COMMANDCMD + \
9529         /* command */   1 * ENABLE_ASH_CMDCMD + \
9530         /* continue */  1 + \
9531         /* echo */      1 * ENABLE_ASH_ECHO + \
9532         0)
9533 #define EXECCMD (EVALCMD + \
9534         /* eval */      1)
9535
9536 /*
9537  * Search the table of builtin commands.
9538  */
9539 static int
9540 pstrcmp1(const void *a, const void *b)
9541 {
9542         return strcmp((char*)a, *(char**)b + 1);
9543 }
9544 static struct builtincmd *
9545 find_builtin(const char *name)
9546 {
9547         struct builtincmd *bp;
9548
9549         bp = bsearch(
9550                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9551                 pstrcmp1
9552         );
9553         return bp;
9554 }
9555
9556 /*
9557  * Execute a simple command.
9558  */
9559 static int
9560 isassignment(const char *p)
9561 {
9562         const char *q = endofname(p);
9563         if (p == q)
9564                 return 0;
9565         return *q == '=';
9566 }
9567 static int FAST_FUNC
9568 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9569 {
9570         /* Preserve exitstatus of a previous possible redirection
9571          * as POSIX mandates */
9572         return back_exitstatus;
9573 }
9574 static int
9575 evalcommand(union node *cmd, int flags)
9576 {
9577         static const struct builtincmd null_bltin = {
9578                 "\0\0", bltincmd /* why three NULs? */
9579         };
9580         struct stackmark smark;
9581         union node *argp;
9582         struct arglist arglist;
9583         struct arglist varlist;
9584         char **argv;
9585         int argc;
9586         const struct strlist *sp;
9587         struct cmdentry cmdentry;
9588         struct job *jp;
9589         char *lastarg;
9590         const char *path;
9591         int spclbltin;
9592         int status;
9593         char **nargv;
9594         struct builtincmd *bcmd;
9595         smallint cmd_is_exec;
9596         smallint pseudovarflag = 0;
9597
9598         /* First expand the arguments. */
9599         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9600         setstackmark(&smark);
9601         back_exitstatus = 0;
9602
9603         cmdentry.cmdtype = CMDBUILTIN;
9604         cmdentry.u.cmd = &null_bltin;
9605         varlist.lastp = &varlist.list;
9606         *varlist.lastp = NULL;
9607         arglist.lastp = &arglist.list;
9608         *arglist.lastp = NULL;
9609
9610         argc = 0;
9611         if (cmd->ncmd.args) {
9612                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9613                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9614         }
9615
9616         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9617                 struct strlist **spp;
9618
9619                 spp = arglist.lastp;
9620                 if (pseudovarflag && isassignment(argp->narg.text))
9621                         expandarg(argp, &arglist, EXP_VARTILDE);
9622                 else
9623                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9624
9625                 for (sp = *spp; sp; sp = sp->next)
9626                         argc++;
9627         }
9628
9629         /* Reserve one extra spot at the front for shellexec. */
9630         nargv = stalloc(sizeof(char *) * (argc + 2));
9631         argv = ++nargv;
9632         for (sp = arglist.list; sp; sp = sp->next) {
9633                 TRACE(("evalcommand arg: %s\n", sp->text));
9634                 *nargv++ = sp->text;
9635         }
9636         *nargv = NULL;
9637
9638         lastarg = NULL;
9639         if (iflag && funcnest == 0 && argc > 0)
9640                 lastarg = nargv[-1];
9641
9642         preverrout_fd = 2;
9643         expredir(cmd->ncmd.redirect);
9644         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9645
9646         path = vpath.var_text;
9647         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9648                 struct strlist **spp;
9649                 char *p;
9650
9651                 spp = varlist.lastp;
9652                 expandarg(argp, &varlist, EXP_VARTILDE);
9653
9654                 /*
9655                  * Modify the command lookup path, if a PATH= assignment
9656                  * is present
9657                  */
9658                 p = (*spp)->text;
9659                 if (varcmp(p, path) == 0)
9660                         path = p;
9661         }
9662
9663         /* Print the command if xflag is set. */
9664         if (xflag) {
9665                 int n;
9666                 const char *p = " %s" + 1;
9667
9668                 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9669                 sp = varlist.list;
9670                 for (n = 0; n < 2; n++) {
9671                         while (sp) {
9672                                 fdprintf(preverrout_fd, p, sp->text);
9673                                 sp = sp->next;
9674                                 p = " %s";
9675                         }
9676                         sp = arglist.list;
9677                 }
9678                 safe_write(preverrout_fd, "\n", 1);
9679         }
9680
9681         cmd_is_exec = 0;
9682         spclbltin = -1;
9683
9684         /* Now locate the command. */
9685         if (argc) {
9686                 int cmd_flag = DO_ERR;
9687 #if ENABLE_ASH_CMDCMD
9688                 const char *oldpath = path + 5;
9689 #endif
9690                 path += 5;
9691                 for (;;) {
9692                         find_command(argv[0], &cmdentry, cmd_flag, path);
9693                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9694                                 flush_stdout_stderr();
9695                                 status = 127;
9696                                 goto bail;
9697                         }
9698
9699                         /* implement bltin and command here */
9700                         if (cmdentry.cmdtype != CMDBUILTIN)
9701                                 break;
9702                         if (spclbltin < 0)
9703                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9704                         if (cmdentry.u.cmd == EXECCMD)
9705                                 cmd_is_exec = 1;
9706 #if ENABLE_ASH_CMDCMD
9707                         if (cmdentry.u.cmd == COMMANDCMD) {
9708                                 path = oldpath;
9709                                 nargv = parse_command_args(argv, &path);
9710                                 if (!nargv)
9711                                         break;
9712                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9713                                  * nargv => "PROG". path is updated if -p.
9714                                  */
9715                                 argc -= nargv - argv;
9716                                 argv = nargv;
9717                                 cmd_flag |= DO_NOFUNC;
9718                         } else
9719 #endif
9720                                 break;
9721                 }
9722         }
9723
9724         if (status) {
9725  bail:
9726                 exitstatus = status;
9727
9728                 /* We have a redirection error. */
9729                 if (spclbltin > 0)
9730                         raise_exception(EXERROR);
9731
9732                 goto out;
9733         }
9734
9735         /* Execute the command. */
9736         switch (cmdentry.cmdtype) {
9737         default: {
9738
9739 #if ENABLE_FEATURE_SH_NOFORK
9740 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9741  *     around run_nofork_applet() call.
9742  * (2) Should this check also be done in forkshell()?
9743  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9744  */
9745                 /* find_command() encodes applet_no as (-2 - applet_no) */
9746                 int applet_no = (- cmdentry.u.index - 2);
9747                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9748                         listsetvar(varlist.list, VEXPORT|VSTACK);
9749                         /* run <applet>_main() */
9750                         status = run_nofork_applet(applet_no, argv);
9751                         break;
9752                 }
9753 #endif
9754                 /* Can we avoid forking off? For example, very last command
9755                  * in a script or a subshell does not need forking,
9756                  * we can just exec it.
9757                  */
9758                 if (!(flags & EV_EXIT) || may_have_traps) {
9759                         /* No, forking off a child is necessary */
9760                         INT_OFF;
9761                         get_tty_state();
9762                         jp = makejob(/*cmd,*/ 1);
9763                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9764                                 /* parent */
9765                                 status = waitforjob(jp);
9766                                 INT_ON;
9767                                 TRACE(("forked child exited with %d\n", status));
9768                                 break;
9769                         }
9770                         /* child */
9771                         FORCE_INT_ON;
9772                         /* fall through to exec'ing external program */
9773                 }
9774                 listsetvar(varlist.list, VEXPORT|VSTACK);
9775                 shellexec(argv[0], argv, path, cmdentry.u.index);
9776                 /* NOTREACHED */
9777         } /* default */
9778         case CMDBUILTIN:
9779                 cmdenviron = varlist.list;
9780                 if (cmdenviron) {
9781                         struct strlist *list = cmdenviron;
9782                         int i = VNOSET;
9783                         if (spclbltin > 0 || argc == 0) {
9784                                 i = 0;
9785                                 if (cmd_is_exec && argc > 1)
9786                                         i = VEXPORT;
9787                         }
9788                         listsetvar(list, i);
9789                 }
9790                 /* Tight loop with builtins only:
9791                  * "while kill -0 $child; do true; done"
9792                  * will never exit even if $child died, unless we do this
9793                  * to reap the zombie and make kill detect that it's gone: */
9794                 dowait(DOWAIT_NONBLOCK, NULL);
9795
9796                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9797                         if (exception_type == EXERROR && spclbltin <= 0) {
9798                                 FORCE_INT_ON;
9799                                 goto readstatus;
9800                         }
9801  raise:
9802                         longjmp(exception_handler->loc, 1);
9803                 }
9804                 goto readstatus;
9805
9806         case CMDFUNCTION:
9807                 listsetvar(varlist.list, 0);
9808                 /* See above for the rationale */
9809                 dowait(DOWAIT_NONBLOCK, NULL);
9810                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9811                         goto raise;
9812  readstatus:
9813                 status = exitstatus;
9814                 break;
9815         } /* switch */
9816
9817  out:
9818         if (cmd->ncmd.redirect)
9819                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9820         if (lastarg) {
9821                 /* dsl: I think this is intended to be used to support
9822                  * '_' in 'vi' command mode during line editing...
9823                  * However I implemented that within libedit itself.
9824                  */
9825                 setvar0("_", lastarg);
9826         }
9827         popstackmark(&smark);
9828
9829         return status;
9830 }
9831
9832 static int
9833 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9834 {
9835         char *volatile savecmdname;
9836         struct jmploc *volatile savehandler;
9837         struct jmploc jmploc;
9838         int status;
9839         int i;
9840
9841         savecmdname = commandname;
9842         savehandler = exception_handler;
9843         i = setjmp(jmploc.loc);
9844         if (i)
9845                 goto cmddone;
9846         exception_handler = &jmploc;
9847         commandname = argv[0];
9848         argptr = argv + 1;
9849         optptr = NULL;                  /* initialize nextopt */
9850         if (cmd == EVALCMD)
9851                 status = evalcmd(argc, argv, flags);
9852         else
9853                 status = (*cmd->builtin)(argc, argv);
9854         flush_stdout_stderr();
9855         status |= ferror(stdout);
9856         exitstatus = status;
9857  cmddone:
9858         clearerr(stdout);
9859         commandname = savecmdname;
9860         exception_handler = savehandler;
9861
9862         return i;
9863 }
9864
9865 static int
9866 goodname(const char *p)
9867 {
9868         return endofname(p)[0] == '\0';
9869 }
9870
9871
9872 /*
9873  * Search for a command.  This is called before we fork so that the
9874  * location of the command will be available in the parent as well as
9875  * the child.  The check for "goodname" is an overly conservative
9876  * check that the name will not be subject to expansion.
9877  */
9878 static void
9879 prehash(union node *n)
9880 {
9881         struct cmdentry entry;
9882
9883         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9884                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9885 }
9886
9887
9888 /* ============ Builtin commands
9889  *
9890  * Builtin commands whose functions are closely tied to evaluation
9891  * are implemented here.
9892  */
9893
9894 /*
9895  * Handle break and continue commands.  Break, continue, and return are
9896  * all handled by setting the evalskip flag.  The evaluation routines
9897  * above all check this flag, and if it is set they start skipping
9898  * commands rather than executing them.  The variable skipcount is
9899  * the number of loops to break/continue, or the number of function
9900  * levels to return.  (The latter is always 1.)  It should probably
9901  * be an error to break out of more loops than exist, but it isn't
9902  * in the standard shell so we don't make it one here.
9903  */
9904 static int FAST_FUNC
9905 breakcmd(int argc UNUSED_PARAM, char **argv)
9906 {
9907         int n = argv[1] ? number(argv[1]) : 1;
9908
9909         if (n <= 0)
9910                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9911         if (n > loopnest)
9912                 n = loopnest;
9913         if (n > 0) {
9914                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9915                 skipcount = n;
9916         }
9917         return 0;
9918 }
9919
9920
9921 /*
9922  * This implements the input routines used by the parser.
9923  */
9924
9925 enum {
9926         INPUT_PUSH_FILE = 1,
9927         INPUT_NOFILE_OK = 2,
9928 };
9929
9930 static smallint checkkwd;
9931 /* values of checkkwd variable */
9932 #define CHKALIAS        0x1
9933 #define CHKKWD          0x2
9934 #define CHKNL           0x4
9935
9936 /*
9937  * Push a string back onto the input at this current parsefile level.
9938  * We handle aliases this way.
9939  */
9940 #if !ENABLE_ASH_ALIAS
9941 #define pushstring(s, ap) pushstring(s)
9942 #endif
9943 static void
9944 pushstring(char *s, struct alias *ap)
9945 {
9946         struct strpush *sp;
9947         int len;
9948
9949         len = strlen(s);
9950         INT_OFF;
9951         if (g_parsefile->strpush) {
9952                 sp = ckzalloc(sizeof(*sp));
9953                 sp->prev = g_parsefile->strpush;
9954         } else {
9955                 sp = &(g_parsefile->basestrpush);
9956         }
9957         g_parsefile->strpush = sp;
9958         sp->prev_string = g_parsefile->next_to_pgetc;
9959         sp->prev_left_in_line = g_parsefile->left_in_line;
9960         sp->unget = g_parsefile->unget;
9961         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9962 #if ENABLE_ASH_ALIAS
9963         sp->ap = ap;
9964         if (ap) {
9965                 ap->flag |= ALIASINUSE;
9966                 sp->string = s;
9967         }
9968 #endif
9969         g_parsefile->next_to_pgetc = s;
9970         g_parsefile->left_in_line = len;
9971         g_parsefile->unget = 0;
9972         INT_ON;
9973 }
9974
9975 static void
9976 popstring(void)
9977 {
9978         struct strpush *sp = g_parsefile->strpush;
9979
9980         INT_OFF;
9981 #if ENABLE_ASH_ALIAS
9982         if (sp->ap) {
9983                 if (g_parsefile->next_to_pgetc[-1] == ' '
9984                  || g_parsefile->next_to_pgetc[-1] == '\t'
9985                 ) {
9986                         checkkwd |= CHKALIAS;
9987                 }
9988                 if (sp->string != sp->ap->val) {
9989                         free(sp->string);
9990                 }
9991                 sp->ap->flag &= ~ALIASINUSE;
9992                 if (sp->ap->flag & ALIASDEAD) {
9993                         unalias(sp->ap->name);
9994                 }
9995         }
9996 #endif
9997         g_parsefile->next_to_pgetc = sp->prev_string;
9998         g_parsefile->left_in_line = sp->prev_left_in_line;
9999         g_parsefile->unget = sp->unget;
10000         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10001         g_parsefile->strpush = sp->prev;
10002         if (sp != &(g_parsefile->basestrpush))
10003                 free(sp);
10004         INT_ON;
10005 }
10006
10007 static int
10008 preadfd(void)
10009 {
10010         int nr;
10011         char *buf = g_parsefile->buf;
10012
10013         g_parsefile->next_to_pgetc = buf;
10014 #if ENABLE_FEATURE_EDITING
10015  retry:
10016         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10017                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10018         else {
10019                 int timeout = -1;
10020 # if ENABLE_ASH_IDLE_TIMEOUT
10021                 if (iflag) {
10022                         const char *tmout_var = lookupvar("TMOUT");
10023                         if (tmout_var) {
10024                                 timeout = atoi(tmout_var) * 1000;
10025                                 if (timeout <= 0)
10026                                         timeout = -1;
10027                         }
10028                 }
10029 # endif
10030 # if ENABLE_FEATURE_TAB_COMPLETION
10031                 line_input_state->path_lookup = pathval();
10032 # endif
10033                 reinit_unicode_for_ash();
10034                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10035                 if (nr == 0) {
10036                         /* ^C pressed, "convert" to SIGINT */
10037                         write(STDOUT_FILENO, "^C", 2);
10038                         if (trap[SIGINT]) {
10039                                 buf[0] = '\n';
10040                                 buf[1] = '\0';
10041                                 raise(SIGINT);
10042                                 return 1;
10043                         }
10044                         exitstatus = 128 + SIGINT;
10045                         bb_putchar('\n');
10046                         goto retry;
10047                 }
10048                 if (nr < 0) {
10049                         if (errno == 0) {
10050                                 /* Ctrl+D pressed */
10051                                 nr = 0;
10052                         }
10053 # if ENABLE_ASH_IDLE_TIMEOUT
10054                         else if (errno == EAGAIN && timeout > 0) {
10055                                 puts("\007timed out waiting for input: auto-logout");
10056                                 exitshell();
10057                         }
10058 # endif
10059                 }
10060         }
10061 #else
10062         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10063 #endif
10064
10065 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10066         if (nr < 0) {
10067                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10068                         int flags = fcntl(0, F_GETFL);
10069                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10070                                 flags &= ~O_NONBLOCK;
10071                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10072                                         out2str("sh: turning off NDELAY mode\n");
10073                                         goto retry;
10074                                 }
10075                         }
10076                 }
10077         }
10078 #endif
10079         return nr;
10080 }
10081
10082 /*
10083  * Refill the input buffer and return the next input character:
10084  *
10085  * 1) If a string was pushed back on the input, pop it;
10086  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10087  *    or we are reading from a string so we can't refill the buffer,
10088  *    return EOF.
10089  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10090  * 4) Process input up to the next newline, deleting nul characters.
10091  */
10092 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10093 #define pgetc_debug(...) ((void)0)
10094 static int pgetc(void);
10095 static int
10096 preadbuffer(void)
10097 {
10098         char *q;
10099         int more;
10100
10101         if (g_parsefile->strpush) {
10102 #if ENABLE_ASH_ALIAS
10103                 if (g_parsefile->left_in_line == -1
10104                  && g_parsefile->strpush->ap
10105                  && g_parsefile->next_to_pgetc[-1] != ' '
10106                  && g_parsefile->next_to_pgetc[-1] != '\t'
10107                 ) {
10108                         pgetc_debug("preadbuffer PEOA");
10109                         return PEOA;
10110                 }
10111 #endif
10112                 popstring();
10113                 return pgetc();
10114         }
10115         /* on both branches above g_parsefile->left_in_line < 0.
10116          * "pgetc" needs refilling.
10117          */
10118
10119         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10120          * pungetc() may increment it a few times.
10121          * Assuming it won't increment it to less than -90.
10122          */
10123         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10124                 pgetc_debug("preadbuffer PEOF1");
10125                 /* even in failure keep left_in_line and next_to_pgetc
10126                  * in lock step, for correct multi-layer pungetc.
10127                  * left_in_line was decremented before preadbuffer(),
10128                  * must inc next_to_pgetc: */
10129                 g_parsefile->next_to_pgetc++;
10130                 return PEOF;
10131         }
10132
10133         more = g_parsefile->left_in_buffer;
10134         if (more <= 0) {
10135                 flush_stdout_stderr();
10136  again:
10137                 more = preadfd();
10138                 if (more <= 0) {
10139                         /* don't try reading again */
10140                         g_parsefile->left_in_line = -99;
10141                         pgetc_debug("preadbuffer PEOF2");
10142                         g_parsefile->next_to_pgetc++;
10143                         return PEOF;
10144                 }
10145         }
10146
10147         /* Find out where's the end of line.
10148          * Set g_parsefile->left_in_line
10149          * and g_parsefile->left_in_buffer acordingly.
10150          * NUL chars are deleted.
10151          */
10152         q = g_parsefile->next_to_pgetc;
10153         for (;;) {
10154                 char c;
10155
10156                 more--;
10157
10158                 c = *q;
10159                 if (c == '\0') {
10160                         memmove(q, q + 1, more);
10161                 } else {
10162                         q++;
10163                         if (c == '\n') {
10164                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10165                                 break;
10166                         }
10167                 }
10168
10169                 if (more <= 0) {
10170                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10171                         if (g_parsefile->left_in_line < 0)
10172                                 goto again;
10173                         break;
10174                 }
10175         }
10176         g_parsefile->left_in_buffer = more;
10177
10178         if (vflag) {
10179                 char save = *q;
10180                 *q = '\0';
10181                 out2str(g_parsefile->next_to_pgetc);
10182                 *q = save;
10183         }
10184
10185         pgetc_debug("preadbuffer at %d:%p'%s'",
10186                         g_parsefile->left_in_line,
10187                         g_parsefile->next_to_pgetc,
10188                         g_parsefile->next_to_pgetc);
10189         return (unsigned char)*g_parsefile->next_to_pgetc++;
10190 }
10191
10192 static void
10193 nlprompt(void)
10194 {
10195         g_parsefile->linno++;
10196         setprompt_if(doprompt, 2);
10197 }
10198 static void
10199 nlnoprompt(void)
10200 {
10201         g_parsefile->linno++;
10202         needprompt = doprompt;
10203 }
10204
10205 static int
10206 pgetc(void)
10207 {
10208         int c;
10209
10210         pgetc_debug("pgetc at %d:%p'%s'",
10211                         g_parsefile->left_in_line,
10212                         g_parsefile->next_to_pgetc,
10213                         g_parsefile->next_to_pgetc);
10214         if (g_parsefile->unget)
10215                 return g_parsefile->lastc[--g_parsefile->unget];
10216
10217         if (--g_parsefile->left_in_line >= 0)
10218                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10219         else
10220                 c = preadbuffer();
10221
10222         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10223         g_parsefile->lastc[0] = c;
10224
10225         return c;
10226 }
10227
10228 #if ENABLE_ASH_ALIAS
10229 static int
10230 pgetc_without_PEOA(void)
10231 {
10232         int c;
10233         do {
10234                 pgetc_debug("pgetc at %d:%p'%s'",
10235                                 g_parsefile->left_in_line,
10236                                 g_parsefile->next_to_pgetc,
10237                                 g_parsefile->next_to_pgetc);
10238                 c = pgetc();
10239         } while (c == PEOA);
10240         return c;
10241 }
10242 #else
10243 # define pgetc_without_PEOA() pgetc()
10244 #endif
10245
10246 /*
10247  * Read a line from the script.
10248  */
10249 static char *
10250 pfgets(char *line, int len)
10251 {
10252         char *p = line;
10253         int nleft = len;
10254         int c;
10255
10256         while (--nleft > 0) {
10257                 c = pgetc_without_PEOA();
10258                 if (c == PEOF) {
10259                         if (p == line)
10260                                 return NULL;
10261                         break;
10262                 }
10263                 *p++ = c;
10264                 if (c == '\n')
10265                         break;
10266         }
10267         *p = '\0';
10268         return line;
10269 }
10270
10271 /*
10272  * Undo a call to pgetc.  Only two characters may be pushed back.
10273  * PEOF may be pushed back.
10274  */
10275 static void
10276 pungetc(void)
10277 {
10278         g_parsefile->unget++;
10279 }
10280
10281 /* This one eats backslash+newline */
10282 static int
10283 pgetc_eatbnl(void)
10284 {
10285         int c;
10286
10287         while ((c = pgetc()) == '\\') {
10288                 if (pgetc() != '\n') {
10289                         pungetc();
10290                         break;
10291                 }
10292
10293                 nlprompt();
10294         }
10295
10296         return c;
10297 }
10298
10299 /*
10300  * To handle the "." command, a stack of input files is used.  Pushfile
10301  * adds a new entry to the stack and popfile restores the previous level.
10302  */
10303 static void
10304 pushfile(void)
10305 {
10306         struct parsefile *pf;
10307
10308         pf = ckzalloc(sizeof(*pf));
10309         pf->prev = g_parsefile;
10310         pf->pf_fd = -1;
10311         /*pf->strpush = NULL; - ckzalloc did it */
10312         /*pf->basestrpush.prev = NULL;*/
10313         /*pf->unget = 0;*/
10314         g_parsefile = pf;
10315 }
10316
10317 static void
10318 popfile(void)
10319 {
10320         struct parsefile *pf = g_parsefile;
10321
10322         if (pf == &basepf)
10323                 return;
10324
10325         INT_OFF;
10326         if (pf->pf_fd >= 0)
10327                 close(pf->pf_fd);
10328         free(pf->buf);
10329         while (pf->strpush)
10330                 popstring();
10331         g_parsefile = pf->prev;
10332         free(pf);
10333         INT_ON;
10334 }
10335
10336 /*
10337  * Return to top level.
10338  */
10339 static void
10340 popallfiles(void)
10341 {
10342         while (g_parsefile != &basepf)
10343                 popfile();
10344 }
10345
10346 /*
10347  * Close the file(s) that the shell is reading commands from.  Called
10348  * after a fork is done.
10349  */
10350 static void
10351 closescript(void)
10352 {
10353         popallfiles();
10354         if (g_parsefile->pf_fd > 0) {
10355                 close(g_parsefile->pf_fd);
10356                 g_parsefile->pf_fd = 0;
10357         }
10358 }
10359
10360 /*
10361  * Like setinputfile, but takes an open file descriptor.  Call this with
10362  * interrupts off.
10363  */
10364 static void
10365 setinputfd(int fd, int push)
10366 {
10367         if (push) {
10368                 pushfile();
10369                 g_parsefile->buf = NULL;
10370         }
10371         g_parsefile->pf_fd = fd;
10372         if (g_parsefile->buf == NULL)
10373                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10374         g_parsefile->left_in_buffer = 0;
10375         g_parsefile->left_in_line = 0;
10376         g_parsefile->linno = 1;
10377 }
10378
10379 /*
10380  * Set the input to take input from a file.  If push is set, push the
10381  * old input onto the stack first.
10382  */
10383 static int
10384 setinputfile(const char *fname, int flags)
10385 {
10386         int fd;
10387
10388         INT_OFF;
10389         fd = open(fname, O_RDONLY);
10390         if (fd < 0) {
10391                 if (flags & INPUT_NOFILE_OK)
10392                         goto out;
10393                 exitstatus = 127;
10394                 ash_msg_and_raise_error("can't open '%s'", fname);
10395         }
10396         if (fd < 10)
10397                 fd = savefd(fd);
10398         else
10399                 close_on_exec_on(fd);
10400         setinputfd(fd, flags & INPUT_PUSH_FILE);
10401  out:
10402         INT_ON;
10403         return fd;
10404 }
10405
10406 /*
10407  * Like setinputfile, but takes input from a string.
10408  */
10409 static void
10410 setinputstring(char *string)
10411 {
10412         INT_OFF;
10413         pushfile();
10414         g_parsefile->next_to_pgetc = string;
10415         g_parsefile->left_in_line = strlen(string);
10416         g_parsefile->buf = NULL;
10417         g_parsefile->linno = 1;
10418         INT_ON;
10419 }
10420
10421
10422 /*
10423  * Routines to check for mail.
10424  */
10425
10426 #if ENABLE_ASH_MAIL
10427
10428 /* Hash of mtimes of mailboxes */
10429 static unsigned mailtime_hash;
10430 /* Set if MAIL or MAILPATH is changed. */
10431 static smallint mail_var_path_changed;
10432
10433 /*
10434  * Print appropriate message(s) if mail has arrived.
10435  * If mail_var_path_changed is set,
10436  * then the value of MAIL has mail_var_path_changed,
10437  * so we just update the values.
10438  */
10439 static void
10440 chkmail(void)
10441 {
10442         const char *mpath;
10443         char *p;
10444         char *q;
10445         unsigned new_hash;
10446         struct stackmark smark;
10447         struct stat statb;
10448
10449         setstackmark(&smark);
10450         mpath = mpathset() ? mpathval() : mailval();
10451         new_hash = 0;
10452         for (;;) {
10453                 p = path_advance(&mpath, nullstr);
10454                 if (p == NULL)
10455                         break;
10456                 if (*p == '\0')
10457                         continue;
10458                 for (q = p; *q; q++)
10459                         continue;
10460 #if DEBUG
10461                 if (q[-1] != '/')
10462                         abort();
10463 #endif
10464                 q[-1] = '\0';                   /* delete trailing '/' */
10465                 if (stat(p, &statb) < 0) {
10466                         continue;
10467                 }
10468                 /* Very simplistic "hash": just a sum of all mtimes */
10469                 new_hash += (unsigned)statb.st_mtime;
10470         }
10471         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10472                 if (mailtime_hash != 0)
10473                         out2str("you have mail\n");
10474                 mailtime_hash = new_hash;
10475         }
10476         mail_var_path_changed = 0;
10477         popstackmark(&smark);
10478 }
10479
10480 static void FAST_FUNC
10481 changemail(const char *val UNUSED_PARAM)
10482 {
10483         mail_var_path_changed = 1;
10484 }
10485
10486 #endif /* ASH_MAIL */
10487
10488
10489 /* ============ ??? */
10490
10491 /*
10492  * Set the shell parameters.
10493  */
10494 static void
10495 setparam(char **argv)
10496 {
10497         char **newparam;
10498         char **ap;
10499         int nparam;
10500
10501         for (nparam = 0; argv[nparam]; nparam++)
10502                 continue;
10503         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10504         while (*argv) {
10505                 *ap++ = ckstrdup(*argv++);
10506         }
10507         *ap = NULL;
10508         freeparam(&shellparam);
10509         shellparam.malloced = 1;
10510         shellparam.nparam = nparam;
10511         shellparam.p = newparam;
10512 #if ENABLE_ASH_GETOPTS
10513         shellparam.optind = 1;
10514         shellparam.optoff = -1;
10515 #endif
10516 }
10517
10518 /*
10519  * Process shell options.  The global variable argptr contains a pointer
10520  * to the argument list; we advance it past the options.
10521  *
10522  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10523  * For a non-interactive shell, an error condition encountered
10524  * by a special built-in ... shall cause the shell to write a diagnostic message
10525  * to standard error and exit as shown in the following table:
10526  * Error                                           Special Built-In
10527  * ...
10528  * Utility syntax error (option or operand error)  Shall exit
10529  * ...
10530  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10531  * we see that bash does not do that (set "finishes" with error code 1 instead,
10532  * and shell continues), and people rely on this behavior!
10533  * Testcase:
10534  * set -o barfoo 2>/dev/null
10535  * echo $?
10536  *
10537  * Oh well. Let's mimic that.
10538  */
10539 static int
10540 plus_minus_o(char *name, int val)
10541 {
10542         int i;
10543
10544         if (name) {
10545                 for (i = 0; i < NOPTS; i++) {
10546                         if (strcmp(name, optnames(i)) == 0) {
10547                                 optlist[i] = val;
10548                                 return 0;
10549                         }
10550                 }
10551                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10552                 return 1;
10553         }
10554         for (i = 0; i < NOPTS; i++) {
10555                 if (val) {
10556                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10557                 } else {
10558                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10559                 }
10560         }
10561         return 0;
10562 }
10563 static void
10564 setoption(int flag, int val)
10565 {
10566         int i;
10567
10568         for (i = 0; i < NOPTS; i++) {
10569                 if (optletters(i) == flag) {
10570                         optlist[i] = val;
10571                         return;
10572                 }
10573         }
10574         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10575         /* NOTREACHED */
10576 }
10577 static int
10578 options(int cmdline)
10579 {
10580         char *p;
10581         int val;
10582         int c;
10583
10584         if (cmdline)
10585                 minusc = NULL;
10586         while ((p = *argptr) != NULL) {
10587                 c = *p++;
10588                 if (c != '-' && c != '+')
10589                         break;
10590                 argptr++;
10591                 val = 0; /* val = 0 if c == '+' */
10592                 if (c == '-') {
10593                         val = 1;
10594                         if (p[0] == '\0' || LONE_DASH(p)) {
10595                                 if (!cmdline) {
10596                                         /* "-" means turn off -x and -v */
10597                                         if (p[0] == '\0')
10598                                                 xflag = vflag = 0;
10599                                         /* "--" means reset params */
10600                                         else if (*argptr == NULL)
10601                                                 setparam(argptr);
10602                                 }
10603                                 break;    /* "-" or "--" terminates options */
10604                         }
10605                 }
10606                 /* first char was + or - */
10607                 while ((c = *p++) != '\0') {
10608                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10609                         if (c == 'c' && cmdline) {
10610                                 minusc = p;     /* command is after shell args */
10611                         } else if (c == 'o') {
10612                                 if (plus_minus_o(*argptr, val)) {
10613                                         /* it already printed err message */
10614                                         return 1; /* error */
10615                                 }
10616                                 if (*argptr)
10617                                         argptr++;
10618                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10619                                 isloginsh = 1;
10620                         /* bash does not accept +-login, we also won't */
10621                         } else if (cmdline && val && (c == '-')) { /* long options */
10622                                 if (strcmp(p, "login") == 0)
10623                                         isloginsh = 1;
10624                                 break;
10625                         } else {
10626                                 setoption(c, val);
10627                         }
10628                 }
10629         }
10630         return 0;
10631 }
10632
10633 /*
10634  * The shift builtin command.
10635  */
10636 static int FAST_FUNC
10637 shiftcmd(int argc UNUSED_PARAM, char **argv)
10638 {
10639         int n;
10640         char **ap1, **ap2;
10641
10642         n = 1;
10643         if (argv[1])
10644                 n = number(argv[1]);
10645         if (n > shellparam.nparam)
10646                 n = 0; /* bash compat, was = shellparam.nparam; */
10647         INT_OFF;
10648         shellparam.nparam -= n;
10649         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10650                 if (shellparam.malloced)
10651                         free(*ap1);
10652         }
10653         ap2 = shellparam.p;
10654         while ((*ap2++ = *ap1++) != NULL)
10655                 continue;
10656 #if ENABLE_ASH_GETOPTS
10657         shellparam.optind = 1;
10658         shellparam.optoff = -1;
10659 #endif
10660         INT_ON;
10661         return 0;
10662 }
10663
10664 /*
10665  * POSIX requires that 'set' (but not export or readonly) output the
10666  * variables in lexicographic order - by the locale's collating order (sigh).
10667  * Maybe we could keep them in an ordered balanced binary tree
10668  * instead of hashed lists.
10669  * For now just roll 'em through qsort for printing...
10670  */
10671 static int
10672 showvars(const char *sep_prefix, int on, int off)
10673 {
10674         const char *sep;
10675         char **ep, **epend;
10676
10677         ep = listvars(on, off, &epend);
10678         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10679
10680         sep = *sep_prefix ? " " : sep_prefix;
10681
10682         for (; ep < epend; ep++) {
10683                 const char *p;
10684                 const char *q;
10685
10686                 p = strchrnul(*ep, '=');
10687                 q = nullstr;
10688                 if (*p)
10689                         q = single_quote(++p);
10690                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10691         }
10692         return 0;
10693 }
10694
10695 /*
10696  * The set command builtin.
10697  */
10698 static int FAST_FUNC
10699 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10700 {
10701         int retval;
10702
10703         if (!argv[1])
10704                 return showvars(nullstr, 0, VUNSET);
10705
10706         INT_OFF;
10707         retval = options(/*cmdline:*/ 0);
10708         if (retval == 0) { /* if no parse error... */
10709                 optschanged();
10710                 if (*argptr != NULL) {
10711                         setparam(argptr);
10712                 }
10713         }
10714         INT_ON;
10715         return retval;
10716 }
10717
10718 #if ENABLE_ASH_RANDOM_SUPPORT
10719 static void FAST_FUNC
10720 change_random(const char *value)
10721 {
10722         uint32_t t;
10723
10724         if (value == NULL) {
10725                 /* "get", generate */
10726                 t = next_random(&random_gen);
10727                 /* set without recursion */
10728                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10729                 vrandom.flags &= ~VNOFUNC;
10730         } else {
10731                 /* set/reset */
10732                 t = strtoul(value, NULL, 10);
10733                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10734         }
10735 }
10736 #endif
10737
10738 #if ENABLE_ASH_GETOPTS
10739 static int
10740 getopts(char *optstr, char *optvar, char **optfirst)
10741 {
10742         char *p, *q;
10743         char c = '?';
10744         int done = 0;
10745         char sbuf[2];
10746         char **optnext;
10747         int ind = shellparam.optind;
10748         int off = shellparam.optoff;
10749
10750         sbuf[1] = '\0';
10751
10752         shellparam.optind = -1;
10753         optnext = optfirst + ind - 1;
10754
10755         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10756                 p = NULL;
10757         else
10758                 p = optnext[-1] + off;
10759         if (p == NULL || *p == '\0') {
10760                 /* Current word is done, advance */
10761                 p = *optnext;
10762                 if (p == NULL || *p != '-' || *++p == '\0') {
10763  atend:
10764                         p = NULL;
10765                         done = 1;
10766                         goto out;
10767                 }
10768                 optnext++;
10769                 if (LONE_DASH(p))        /* check for "--" */
10770                         goto atend;
10771         }
10772
10773         c = *p++;
10774         for (q = optstr; *q != c;) {
10775                 if (*q == '\0') {
10776                         if (optstr[0] == ':') {
10777                                 sbuf[0] = c;
10778                                 /*sbuf[1] = '\0'; - already is */
10779                                 setvar0("OPTARG", sbuf);
10780                         } else {
10781                                 fprintf(stderr, "Illegal option -%c\n", c);
10782                                 unsetvar("OPTARG");
10783                         }
10784                         c = '?';
10785                         goto out;
10786                 }
10787                 if (*++q == ':')
10788                         q++;
10789         }
10790
10791         if (*++q == ':') {
10792                 if (*p == '\0' && (p = *optnext) == NULL) {
10793                         if (optstr[0] == ':') {
10794                                 sbuf[0] = c;
10795                                 /*sbuf[1] = '\0'; - already is */
10796                                 setvar0("OPTARG", sbuf);
10797                                 c = ':';
10798                         } else {
10799                                 fprintf(stderr, "No arg for -%c option\n", c);
10800                                 unsetvar("OPTARG");
10801                                 c = '?';
10802                         }
10803                         goto out;
10804                 }
10805
10806                 if (p == *optnext)
10807                         optnext++;
10808                 setvar0("OPTARG", p);
10809                 p = NULL;
10810         } else
10811                 setvar0("OPTARG", nullstr);
10812  out:
10813         ind = optnext - optfirst + 1;
10814         setvar("OPTIND", itoa(ind), VNOFUNC);
10815         sbuf[0] = c;
10816         /*sbuf[1] = '\0'; - already is */
10817         setvar0(optvar, sbuf);
10818
10819         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10820         shellparam.optind = ind;
10821
10822         return done;
10823 }
10824
10825 /*
10826  * The getopts builtin.  Shellparam.optnext points to the next argument
10827  * to be processed.  Shellparam.optptr points to the next character to
10828  * be processed in the current argument.  If shellparam.optnext is NULL,
10829  * then it's the first time getopts has been called.
10830  */
10831 static int FAST_FUNC
10832 getoptscmd(int argc, char **argv)
10833 {
10834         char **optbase;
10835
10836         if (argc < 3)
10837                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10838         if (argc == 3) {
10839                 optbase = shellparam.p;
10840                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10841                         shellparam.optind = 1;
10842                         shellparam.optoff = -1;
10843                 }
10844         } else {
10845                 optbase = &argv[3];
10846                 if ((unsigned)shellparam.optind > argc - 2) {
10847                         shellparam.optind = 1;
10848                         shellparam.optoff = -1;
10849                 }
10850         }
10851
10852         return getopts(argv[1], argv[2], optbase);
10853 }
10854 #endif /* ASH_GETOPTS */
10855
10856
10857 /* ============ Shell parser */
10858
10859 struct heredoc {
10860         struct heredoc *next;   /* next here document in list */
10861         union node *here;       /* redirection node */
10862         char *eofmark;          /* string indicating end of input */
10863         smallint striptabs;     /* if set, strip leading tabs */
10864 };
10865
10866 static smallint tokpushback;           /* last token pushed back */
10867 static smallint quoteflag;             /* set if (part of) last token was quoted */
10868 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10869 static struct heredoc *heredoclist;    /* list of here documents to read */
10870 static char *wordtext;                 /* text of last word returned by readtoken */
10871 static struct nodelist *backquotelist;
10872 static union node *redirnode;
10873 static struct heredoc *heredoc;
10874
10875 static const char *
10876 tokname(char *buf, int tok)
10877 {
10878         if (tok < TSEMI)
10879                 return tokname_array[tok];
10880         sprintf(buf, "\"%s\"", tokname_array[tok]);
10881         return buf;
10882 }
10883
10884 /* raise_error_unexpected_syntax:
10885  * Called when an unexpected token is read during the parse.  The argument
10886  * is the token that is expected, or -1 if more than one type of token can
10887  * occur at this point.
10888  */
10889 static void raise_error_unexpected_syntax(int) NORETURN;
10890 static void
10891 raise_error_unexpected_syntax(int token)
10892 {
10893         char msg[64];
10894         char buf[16];
10895         int l;
10896
10897         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10898         if (token >= 0)
10899                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10900         raise_error_syntax(msg);
10901         /* NOTREACHED */
10902 }
10903
10904 #define EOFMARKLEN 79
10905
10906 /* parsing is heavily cross-recursive, need these forward decls */
10907 static union node *andor(void);
10908 static union node *pipeline(void);
10909 static union node *parse_command(void);
10910 static void parseheredoc(void);
10911 static int peektoken(void);
10912 static int readtoken(void);
10913
10914 static union node *
10915 list(int nlflag)
10916 {
10917         union node *n1, *n2, *n3;
10918         int tok;
10919
10920         n1 = NULL;
10921         for (;;) {
10922                 switch (peektoken()) {
10923                 case TNL:
10924                         if (!(nlflag & 1))
10925                                 break;
10926                         parseheredoc();
10927                         return n1;
10928
10929                 case TEOF:
10930                         if (!n1 && (nlflag & 1))
10931                                 n1 = NODE_EOF;
10932                         parseheredoc();
10933                         return n1;
10934                 }
10935
10936                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10937                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10938                         return n1;
10939                 nlflag |= 2;
10940
10941                 n2 = andor();
10942                 tok = readtoken();
10943                 if (tok == TBACKGND) {
10944                         if (n2->type == NPIPE) {
10945                                 n2->npipe.pipe_backgnd = 1;
10946                         } else {
10947                                 if (n2->type != NREDIR) {
10948                                         n3 = stzalloc(sizeof(struct nredir));
10949                                         n3->nredir.n = n2;
10950                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10951                                         n2 = n3;
10952                                 }
10953                                 n2->type = NBACKGND;
10954                         }
10955                 }
10956                 if (n1 == NULL) {
10957                         n1 = n2;
10958                 } else {
10959                         n3 = stzalloc(sizeof(struct nbinary));
10960                         n3->type = NSEMI;
10961                         n3->nbinary.ch1 = n1;
10962                         n3->nbinary.ch2 = n2;
10963                         n1 = n3;
10964                 }
10965                 switch (tok) {
10966                 case TNL:
10967                 case TEOF:
10968                         tokpushback = 1;
10969                         /* fall through */
10970                 case TBACKGND:
10971                 case TSEMI:
10972                         break;
10973                 default:
10974                         if ((nlflag & 1))
10975                                 raise_error_unexpected_syntax(-1);
10976                         tokpushback = 1;
10977                         return n1;
10978                 }
10979         }
10980 }
10981
10982 static union node *
10983 andor(void)
10984 {
10985         union node *n1, *n2, *n3;
10986         int t;
10987
10988         n1 = pipeline();
10989         for (;;) {
10990                 t = readtoken();
10991                 if (t == TAND) {
10992                         t = NAND;
10993                 } else if (t == TOR) {
10994                         t = NOR;
10995                 } else {
10996                         tokpushback = 1;
10997                         return n1;
10998                 }
10999                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11000                 n2 = pipeline();
11001                 n3 = stzalloc(sizeof(struct nbinary));
11002                 n3->type = t;
11003                 n3->nbinary.ch1 = n1;
11004                 n3->nbinary.ch2 = n2;
11005                 n1 = n3;
11006         }
11007 }
11008
11009 static union node *
11010 pipeline(void)
11011 {
11012         union node *n1, *n2, *pipenode;
11013         struct nodelist *lp, *prev;
11014         int negate;
11015
11016         negate = 0;
11017         TRACE(("pipeline: entered\n"));
11018         if (readtoken() == TNOT) {
11019                 negate = !negate;
11020                 checkkwd = CHKKWD | CHKALIAS;
11021         } else
11022                 tokpushback = 1;
11023         n1 = parse_command();
11024         if (readtoken() == TPIPE) {
11025                 pipenode = stzalloc(sizeof(struct npipe));
11026                 pipenode->type = NPIPE;
11027                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11028                 lp = stzalloc(sizeof(struct nodelist));
11029                 pipenode->npipe.cmdlist = lp;
11030                 lp->n = n1;
11031                 do {
11032                         prev = lp;
11033                         lp = stzalloc(sizeof(struct nodelist));
11034                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11035                         lp->n = parse_command();
11036                         prev->next = lp;
11037                 } while (readtoken() == TPIPE);
11038                 lp->next = NULL;
11039                 n1 = pipenode;
11040         }
11041         tokpushback = 1;
11042         if (negate) {
11043                 n2 = stzalloc(sizeof(struct nnot));
11044                 n2->type = NNOT;
11045                 n2->nnot.com = n1;
11046                 return n2;
11047         }
11048         return n1;
11049 }
11050
11051 static union node *
11052 makename(void)
11053 {
11054         union node *n;
11055
11056         n = stzalloc(sizeof(struct narg));
11057         n->type = NARG;
11058         /*n->narg.next = NULL; - stzalloc did it */
11059         n->narg.text = wordtext;
11060         n->narg.backquote = backquotelist;
11061         return n;
11062 }
11063
11064 static void
11065 fixredir(union node *n, const char *text, int err)
11066 {
11067         int fd;
11068
11069         TRACE(("Fix redir %s %d\n", text, err));
11070         if (!err)
11071                 n->ndup.vname = NULL;
11072
11073         fd = bb_strtou(text, NULL, 10);
11074         if (!errno && fd >= 0)
11075                 n->ndup.dupfd = fd;
11076         else if (LONE_DASH(text))
11077                 n->ndup.dupfd = -1;
11078         else {
11079                 if (err)
11080                         raise_error_syntax("bad fd number");
11081                 n->ndup.vname = makename();
11082         }
11083 }
11084
11085 /*
11086  * Returns true if the text contains nothing to expand (no dollar signs
11087  * or backquotes).
11088  */
11089 static int
11090 noexpand(const char *text)
11091 {
11092         unsigned char c;
11093
11094         while ((c = *text++) != '\0') {
11095                 if (c == CTLQUOTEMARK)
11096                         continue;
11097                 if (c == CTLESC)
11098                         text++;
11099                 else if (SIT(c, BASESYNTAX) == CCTL)
11100                         return 0;
11101         }
11102         return 1;
11103 }
11104
11105 static void
11106 parsefname(void)
11107 {
11108         union node *n = redirnode;
11109
11110         if (readtoken() != TWORD)
11111                 raise_error_unexpected_syntax(-1);
11112         if (n->type == NHERE) {
11113                 struct heredoc *here = heredoc;
11114                 struct heredoc *p;
11115                 int i;
11116
11117                 if (quoteflag == 0)
11118                         n->type = NXHERE;
11119                 TRACE(("Here document %d\n", n->type));
11120                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11121                         raise_error_syntax("illegal eof marker for << redirection");
11122                 rmescapes(wordtext, 0);
11123                 here->eofmark = wordtext;
11124                 here->next = NULL;
11125                 if (heredoclist == NULL)
11126                         heredoclist = here;
11127                 else {
11128                         for (p = heredoclist; p->next; p = p->next)
11129                                 continue;
11130                         p->next = here;
11131                 }
11132         } else if (n->type == NTOFD || n->type == NFROMFD) {
11133                 fixredir(n, wordtext, 0);
11134         } else {
11135                 n->nfile.fname = makename();
11136         }
11137 }
11138
11139 static union node *
11140 simplecmd(void)
11141 {
11142         union node *args, **app;
11143         union node *n = NULL;
11144         union node *vars, **vpp;
11145         union node **rpp, *redir;
11146         int savecheckkwd;
11147 #if BASH_TEST2
11148         smallint double_brackets_flag = 0;
11149 #endif
11150         IF_BASH_FUNCTION(smallint function_flag = 0;)
11151
11152         args = NULL;
11153         app = &args;
11154         vars = NULL;
11155         vpp = &vars;
11156         redir = NULL;
11157         rpp = &redir;
11158
11159         savecheckkwd = CHKALIAS;
11160         for (;;) {
11161                 int t;
11162                 checkkwd = savecheckkwd;
11163                 t = readtoken();
11164                 switch (t) {
11165 #if BASH_FUNCTION
11166                 case TFUNCTION:
11167                         if (peektoken() != TWORD)
11168                                 raise_error_unexpected_syntax(TWORD);
11169                         function_flag = 1;
11170                         break;
11171 #endif
11172 #if BASH_TEST2
11173                 case TAND: /* "&&" */
11174                 case TOR: /* "||" */
11175                         if (!double_brackets_flag) {
11176                                 tokpushback = 1;
11177                                 goto out;
11178                         }
11179                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11180 #endif
11181                 case TWORD:
11182                         n = stzalloc(sizeof(struct narg));
11183                         n->type = NARG;
11184                         /*n->narg.next = NULL; - stzalloc did it */
11185                         n->narg.text = wordtext;
11186 #if BASH_TEST2
11187                         if (strcmp("[[", wordtext) == 0)
11188                                 double_brackets_flag = 1;
11189                         else if (strcmp("]]", wordtext) == 0)
11190                                 double_brackets_flag = 0;
11191 #endif
11192                         n->narg.backquote = backquotelist;
11193                         if (savecheckkwd && isassignment(wordtext)) {
11194                                 *vpp = n;
11195                                 vpp = &n->narg.next;
11196                         } else {
11197                                 *app = n;
11198                                 app = &n->narg.next;
11199                                 savecheckkwd = 0;
11200                         }
11201 #if BASH_FUNCTION
11202                         if (function_flag) {
11203                                 checkkwd = CHKNL | CHKKWD;
11204                                 switch (peektoken()) {
11205                                 case TBEGIN:
11206                                 case TIF:
11207                                 case TCASE:
11208                                 case TUNTIL:
11209                                 case TWHILE:
11210                                 case TFOR:
11211                                         goto do_func;
11212                                 case TLP:
11213                                         function_flag = 0;
11214                                         break;
11215                                 case TWORD:
11216                                         if (strcmp("[[", wordtext) == 0)
11217                                                 goto do_func;
11218                                         /* fall through */
11219                                 default:
11220                                         raise_error_unexpected_syntax(-1);
11221                                 }
11222                         }
11223 #endif
11224                         break;
11225                 case TREDIR:
11226                         *rpp = n = redirnode;
11227                         rpp = &n->nfile.next;
11228                         parsefname();   /* read name of redirection file */
11229                         break;
11230                 case TLP:
11231  IF_BASH_FUNCTION(do_func:)
11232                         if (args && app == &args->narg.next
11233                          && !vars && !redir
11234                         ) {
11235                                 struct builtincmd *bcmd;
11236                                 const char *name;
11237
11238                                 /* We have a function */
11239                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11240                                         raise_error_unexpected_syntax(TRP);
11241                                 name = n->narg.text;
11242                                 if (!goodname(name)
11243                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11244                                 ) {
11245                                         raise_error_syntax("bad function name");
11246                                 }
11247                                 n->type = NDEFUN;
11248                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11249                                 n->narg.next = parse_command();
11250                                 return n;
11251                         }
11252                         IF_BASH_FUNCTION(function_flag = 0;)
11253                         /* fall through */
11254                 default:
11255                         tokpushback = 1;
11256                         goto out;
11257                 }
11258         }
11259  out:
11260         *app = NULL;
11261         *vpp = NULL;
11262         *rpp = NULL;
11263         n = stzalloc(sizeof(struct ncmd));
11264         n->type = NCMD;
11265         n->ncmd.args = args;
11266         n->ncmd.assign = vars;
11267         n->ncmd.redirect = redir;
11268         return n;
11269 }
11270
11271 static union node *
11272 parse_command(void)
11273 {
11274         union node *n1, *n2;
11275         union node *ap, **app;
11276         union node *cp, **cpp;
11277         union node *redir, **rpp;
11278         union node **rpp2;
11279         int t;
11280
11281         redir = NULL;
11282         rpp2 = &redir;
11283
11284         switch (readtoken()) {
11285         default:
11286                 raise_error_unexpected_syntax(-1);
11287                 /* NOTREACHED */
11288         case TIF:
11289                 n1 = stzalloc(sizeof(struct nif));
11290                 n1->type = NIF;
11291                 n1->nif.test = list(0);
11292                 if (readtoken() != TTHEN)
11293                         raise_error_unexpected_syntax(TTHEN);
11294                 n1->nif.ifpart = list(0);
11295                 n2 = n1;
11296                 while (readtoken() == TELIF) {
11297                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11298                         n2 = n2->nif.elsepart;
11299                         n2->type = NIF;
11300                         n2->nif.test = list(0);
11301                         if (readtoken() != TTHEN)
11302                                 raise_error_unexpected_syntax(TTHEN);
11303                         n2->nif.ifpart = list(0);
11304                 }
11305                 if (lasttoken == TELSE)
11306                         n2->nif.elsepart = list(0);
11307                 else {
11308                         n2->nif.elsepart = NULL;
11309                         tokpushback = 1;
11310                 }
11311                 t = TFI;
11312                 break;
11313         case TWHILE:
11314         case TUNTIL: {
11315                 int got;
11316                 n1 = stzalloc(sizeof(struct nbinary));
11317                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11318                 n1->nbinary.ch1 = list(0);
11319                 got = readtoken();
11320                 if (got != TDO) {
11321                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11322                                         got == TWORD ? wordtext : ""));
11323                         raise_error_unexpected_syntax(TDO);
11324                 }
11325                 n1->nbinary.ch2 = list(0);
11326                 t = TDONE;
11327                 break;
11328         }
11329         case TFOR:
11330                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11331                         raise_error_syntax("bad for loop variable");
11332                 n1 = stzalloc(sizeof(struct nfor));
11333                 n1->type = NFOR;
11334                 n1->nfor.var = wordtext;
11335                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11336                 if (readtoken() == TIN) {
11337                         app = &ap;
11338                         while (readtoken() == TWORD) {
11339                                 n2 = stzalloc(sizeof(struct narg));
11340                                 n2->type = NARG;
11341                                 /*n2->narg.next = NULL; - stzalloc did it */
11342                                 n2->narg.text = wordtext;
11343                                 n2->narg.backquote = backquotelist;
11344                                 *app = n2;
11345                                 app = &n2->narg.next;
11346                         }
11347                         *app = NULL;
11348                         n1->nfor.args = ap;
11349                         if (lasttoken != TNL && lasttoken != TSEMI)
11350                                 raise_error_unexpected_syntax(-1);
11351                 } else {
11352                         n2 = stzalloc(sizeof(struct narg));
11353                         n2->type = NARG;
11354                         /*n2->narg.next = NULL; - stzalloc did it */
11355                         n2->narg.text = (char *)dolatstr;
11356                         /*n2->narg.backquote = NULL;*/
11357                         n1->nfor.args = n2;
11358                         /*
11359                          * Newline or semicolon here is optional (but note
11360                          * that the original Bourne shell only allowed NL).
11361                          */
11362                         if (lasttoken != TSEMI)
11363                                 tokpushback = 1;
11364                 }
11365                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11366                 if (readtoken() != TDO)
11367                         raise_error_unexpected_syntax(TDO);
11368                 n1->nfor.body = list(0);
11369                 t = TDONE;
11370                 break;
11371         case TCASE:
11372                 n1 = stzalloc(sizeof(struct ncase));
11373                 n1->type = NCASE;
11374                 if (readtoken() != TWORD)
11375                         raise_error_unexpected_syntax(TWORD);
11376                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11377                 n2->type = NARG;
11378                 /*n2->narg.next = NULL; - stzalloc did it */
11379                 n2->narg.text = wordtext;
11380                 n2->narg.backquote = backquotelist;
11381                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11382                 if (readtoken() != TIN)
11383                         raise_error_unexpected_syntax(TIN);
11384                 cpp = &n1->ncase.cases;
11385  next_case:
11386                 checkkwd = CHKNL | CHKKWD;
11387                 t = readtoken();
11388                 while (t != TESAC) {
11389                         if (lasttoken == TLP)
11390                                 readtoken();
11391                         *cpp = cp = stzalloc(sizeof(struct nclist));
11392                         cp->type = NCLIST;
11393                         app = &cp->nclist.pattern;
11394                         for (;;) {
11395                                 *app = ap = stzalloc(sizeof(struct narg));
11396                                 ap->type = NARG;
11397                                 /*ap->narg.next = NULL; - stzalloc did it */
11398                                 ap->narg.text = wordtext;
11399                                 ap->narg.backquote = backquotelist;
11400                                 if (readtoken() != TPIPE)
11401                                         break;
11402                                 app = &ap->narg.next;
11403                                 readtoken();
11404                         }
11405                         //ap->narg.next = NULL;
11406                         if (lasttoken != TRP)
11407                                 raise_error_unexpected_syntax(TRP);
11408                         cp->nclist.body = list(2);
11409
11410                         cpp = &cp->nclist.next;
11411
11412                         checkkwd = CHKNL | CHKKWD;
11413                         t = readtoken();
11414                         if (t != TESAC) {
11415                                 if (t != TENDCASE)
11416                                         raise_error_unexpected_syntax(TENDCASE);
11417                                 goto next_case;
11418                         }
11419                 }
11420                 *cpp = NULL;
11421                 goto redir;
11422         case TLP:
11423                 n1 = stzalloc(sizeof(struct nredir));
11424                 n1->type = NSUBSHELL;
11425                 n1->nredir.n = list(0);
11426                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11427                 t = TRP;
11428                 break;
11429         case TBEGIN:
11430                 n1 = list(0);
11431                 t = TEND;
11432                 break;
11433         IF_BASH_FUNCTION(case TFUNCTION:)
11434         case TWORD:
11435         case TREDIR:
11436                 tokpushback = 1;
11437                 return simplecmd();
11438         }
11439
11440         if (readtoken() != t)
11441                 raise_error_unexpected_syntax(t);
11442
11443  redir:
11444         /* Now check for redirection which may follow command */
11445         checkkwd = CHKKWD | CHKALIAS;
11446         rpp = rpp2;
11447         while (readtoken() == TREDIR) {
11448                 *rpp = n2 = redirnode;
11449                 rpp = &n2->nfile.next;
11450                 parsefname();
11451         }
11452         tokpushback = 1;
11453         *rpp = NULL;
11454         if (redir) {
11455                 if (n1->type != NSUBSHELL) {
11456                         n2 = stzalloc(sizeof(struct nredir));
11457                         n2->type = NREDIR;
11458                         n2->nredir.n = n1;
11459                         n1 = n2;
11460                 }
11461                 n1->nredir.redirect = redir;
11462         }
11463         return n1;
11464 }
11465
11466 #if BASH_DOLLAR_SQUOTE
11467 static int
11468 decode_dollar_squote(void)
11469 {
11470         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11471         int c, cnt;
11472         char *p;
11473         char buf[4];
11474
11475         c = pgetc();
11476         p = strchr(C_escapes, c);
11477         if (p) {
11478                 buf[0] = c;
11479                 p = buf;
11480                 cnt = 3;
11481                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11482                         do {
11483                                 c = pgetc();
11484                                 *++p = c;
11485                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11486                         pungetc();
11487                 } else if (c == 'x') { /* \xHH */
11488                         do {
11489                                 c = pgetc();
11490                                 *++p = c;
11491                         } while (isxdigit(c) && --cnt);
11492                         pungetc();
11493                         if (cnt == 3) { /* \x but next char is "bad" */
11494                                 c = 'x';
11495                                 goto unrecognized;
11496                         }
11497                 } else { /* simple seq like \\ or \t */
11498                         p++;
11499                 }
11500                 *p = '\0';
11501                 p = buf;
11502                 c = bb_process_escape_sequence((void*)&p);
11503         } else { /* unrecognized "\z": print both chars unless ' or " */
11504                 if (c != '\'' && c != '"') {
11505  unrecognized:
11506                         c |= 0x100; /* "please encode \, then me" */
11507                 }
11508         }
11509         return c;
11510 }
11511 #endif
11512
11513 /*
11514  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11515  * is not NULL, read a here document.  In the latter case, eofmark is the
11516  * word which marks the end of the document and striptabs is true if
11517  * leading tabs should be stripped from the document.  The argument c
11518  * is the first character of the input token or document.
11519  *
11520  * Because C does not have internal subroutines, I have simulated them
11521  * using goto's to implement the subroutine linkage.  The following macros
11522  * will run code that appears at the end of readtoken1.
11523  */
11524 #define CHECKEND()      {goto checkend; checkend_return:;}
11525 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11526 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11527 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11528 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11529 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11530 static int
11531 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11532 {
11533         /* NB: syntax parameter fits into smallint */
11534         /* c parameter is an unsigned char or PEOF or PEOA */
11535         char *out;
11536         size_t len;
11537         char line[EOFMARKLEN + 1];
11538         struct nodelist *bqlist;
11539         smallint quotef;
11540         smallint dblquote;
11541         smallint oldstyle;
11542         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11543 #if ENABLE_ASH_EXPAND_PRMT
11544         smallint pssyntax;   /* we are expanding a prompt string */
11545 #endif
11546         int varnest;         /* levels of variables expansion */
11547         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11548         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11549         int dqvarnest;       /* levels of variables expansion within double quotes */
11550
11551         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11552
11553         startlinno = g_parsefile->linno;
11554         bqlist = NULL;
11555         quotef = 0;
11556         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11557 #if ENABLE_ASH_EXPAND_PRMT
11558         pssyntax = (syntax == PSSYNTAX);
11559         if (pssyntax)
11560                 syntax = DQSYNTAX;
11561 #endif
11562         dblquote = (syntax == DQSYNTAX);
11563         varnest = 0;
11564         IF_FEATURE_SH_MATH(arinest = 0;)
11565         IF_FEATURE_SH_MATH(parenlevel = 0;)
11566         dqvarnest = 0;
11567
11568         STARTSTACKSTR(out);
11569  loop:
11570         /* For each line, until end of word */
11571         CHECKEND();     /* set c to PEOF if at end of here document */
11572         for (;;) {      /* until end of line or end of word */
11573                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11574                 switch (SIT(c, syntax)) {
11575                 case CNL:       /* '\n' */
11576                         if (syntax == BASESYNTAX)
11577                                 goto endword;   /* exit outer loop */
11578                         USTPUTC(c, out);
11579                         nlprompt();
11580                         c = pgetc();
11581                         goto loop;              /* continue outer loop */
11582                 case CWORD:
11583                         USTPUTC(c, out);
11584                         break;
11585                 case CCTL:
11586 #if BASH_DOLLAR_SQUOTE
11587                         if (c == '\\' && bash_dollar_squote) {
11588                                 c = decode_dollar_squote();
11589                                 if (c == '\0') {
11590                                         /* skip $'\000', $'\x00' (like bash) */
11591                                         break;
11592                                 }
11593                                 if (c & 0x100) {
11594                                         /* Unknown escape. Encode as '\z' */
11595                                         c = (unsigned char)c;
11596                                         if (eofmark == NULL || dblquote)
11597                                                 USTPUTC(CTLESC, out);
11598                                         USTPUTC('\\', out);
11599                                 }
11600                         }
11601 #endif
11602                         if (eofmark == NULL || dblquote)
11603                                 USTPUTC(CTLESC, out);
11604                         USTPUTC(c, out);
11605                         break;
11606                 case CBACK:     /* backslash */
11607                         c = pgetc_without_PEOA();
11608                         if (c == PEOF) {
11609                                 USTPUTC(CTLESC, out);
11610                                 USTPUTC('\\', out);
11611                                 pungetc();
11612                         } else if (c == '\n') {
11613                                 nlprompt();
11614                         } else {
11615 #if ENABLE_ASH_EXPAND_PRMT
11616                                 if (c == '$' && pssyntax) {
11617                                         USTPUTC(CTLESC, out);
11618                                         USTPUTC('\\', out);
11619                                 }
11620 #endif
11621                                 /* Backslash is retained if we are in "str" and next char isn't special */
11622                                 if (dblquote
11623                                  && c != '\\'
11624                                  && c != '`'
11625                                  && c != '$'
11626                                  && (c != '"' || eofmark != NULL)
11627                                 ) {
11628                                         USTPUTC('\\', out);
11629                                 }
11630                                 USTPUTC(CTLESC, out);
11631                                 USTPUTC(c, out);
11632                                 quotef = 1;
11633                         }
11634                         break;
11635                 case CSQUOTE:
11636                         syntax = SQSYNTAX;
11637  quotemark:
11638                         if (eofmark == NULL) {
11639                                 USTPUTC(CTLQUOTEMARK, out);
11640                         }
11641                         break;
11642                 case CDQUOTE:
11643                         syntax = DQSYNTAX;
11644                         dblquote = 1;
11645                         goto quotemark;
11646                 case CENDQUOTE:
11647                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11648                         if (eofmark != NULL && varnest == 0) {
11649                                 USTPUTC(c, out);
11650                         } else {
11651                                 if (dqvarnest == 0) {
11652                                         syntax = BASESYNTAX;
11653                                         dblquote = 0;
11654                                 }
11655                                 quotef = 1;
11656                                 goto quotemark;
11657                         }
11658                         break;
11659                 case CVAR:      /* '$' */
11660                         PARSESUB();             /* parse substitution */
11661                         break;
11662                 case CENDVAR:   /* '}' */
11663                         if (varnest > 0) {
11664                                 varnest--;
11665                                 if (dqvarnest > 0) {
11666                                         dqvarnest--;
11667                                 }
11668                                 c = CTLENDVAR;
11669                         }
11670                         USTPUTC(c, out);
11671                         break;
11672 #if ENABLE_FEATURE_SH_MATH
11673                 case CLP:       /* '(' in arithmetic */
11674                         parenlevel++;
11675                         USTPUTC(c, out);
11676                         break;
11677                 case CRP:       /* ')' in arithmetic */
11678                         if (parenlevel > 0) {
11679                                 parenlevel--;
11680                         } else {
11681                                 if (pgetc_eatbnl() == ')') {
11682                                         c = CTLENDARI;
11683                                         if (--arinest == 0) {
11684                                                 syntax = prevsyntax;
11685                                         }
11686                                 } else {
11687                                         /*
11688                                          * unbalanced parens
11689                                          * (don't 2nd guess - no error)
11690                                          */
11691                                         pungetc();
11692                                 }
11693                         }
11694                         USTPUTC(c, out);
11695                         break;
11696 #endif
11697                 case CBQUOTE:   /* '`' */
11698                         PARSEBACKQOLD();
11699                         break;
11700                 case CENDFILE:
11701                         goto endword;           /* exit outer loop */
11702                 case CIGN:
11703                         break;
11704                 default:
11705                         if (varnest == 0) {
11706 #if BASH_REDIR_OUTPUT
11707                                 if (c == '&') {
11708 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11709                                         if (pgetc() == '>')
11710                                                 c = 0x100 + '>'; /* flag &> */
11711                                         pungetc();
11712                                 }
11713 #endif
11714                                 goto endword;   /* exit outer loop */
11715                         }
11716                         IF_ASH_ALIAS(if (c != PEOA))
11717                                 USTPUTC(c, out);
11718                 }
11719                 c = pgetc();
11720         } /* for (;;) */
11721  endword:
11722
11723 #if ENABLE_FEATURE_SH_MATH
11724         if (syntax == ARISYNTAX)
11725                 raise_error_syntax("missing '))'");
11726 #endif
11727         if (syntax != BASESYNTAX && eofmark == NULL)
11728                 raise_error_syntax("unterminated quoted string");
11729         if (varnest != 0) {
11730                 startlinno = g_parsefile->linno;
11731                 /* { */
11732                 raise_error_syntax("missing '}'");
11733         }
11734         USTPUTC('\0', out);
11735         len = out - (char *)stackblock();
11736         out = stackblock();
11737         if (eofmark == NULL) {
11738                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11739                  && quotef == 0
11740                 ) {
11741                         if (isdigit_str9(out)) {
11742                                 PARSEREDIR(); /* passed as params: out, c */
11743                                 lasttoken = TREDIR;
11744                                 return lasttoken;
11745                         }
11746                         /* else: non-number X seen, interpret it
11747                          * as "NNNX>file" = "NNNX >file" */
11748                 }
11749                 pungetc();
11750         }
11751         quoteflag = quotef;
11752         backquotelist = bqlist;
11753         grabstackblock(len);
11754         wordtext = out;
11755         lasttoken = TWORD;
11756         return lasttoken;
11757 /* end of readtoken routine */
11758
11759 /*
11760  * Check to see whether we are at the end of the here document.  When this
11761  * is called, c is set to the first character of the next input line.  If
11762  * we are at the end of the here document, this routine sets the c to PEOF.
11763  */
11764 checkend: {
11765         if (eofmark) {
11766 #if ENABLE_ASH_ALIAS
11767                 if (c == PEOA)
11768                         c = pgetc_without_PEOA();
11769 #endif
11770                 if (striptabs) {
11771                         while (c == '\t') {
11772                                 c = pgetc_without_PEOA();
11773                         }
11774                 }
11775                 if (c == *eofmark) {
11776                         if (pfgets(line, sizeof(line)) != NULL) {
11777                                 char *p, *q;
11778                                 int cc;
11779
11780                                 p = line;
11781                                 for (q = eofmark + 1;; p++, q++) {
11782                                         cc = *p;
11783                                         if (cc == '\n')
11784                                                 cc = 0;
11785                                         if (!*q || cc != *q)
11786                                                 break;
11787                                 }
11788                                 if (cc == *q) {
11789                                         c = PEOF;
11790                                         nlnoprompt();
11791                                 } else {
11792                                         pushstring(line, NULL);
11793                                 }
11794                         }
11795                 }
11796         }
11797         goto checkend_return;
11798 }
11799
11800 /*
11801  * Parse a redirection operator.  The variable "out" points to a string
11802  * specifying the fd to be redirected.  The variable "c" contains the
11803  * first character of the redirection operator.
11804  */
11805 parseredir: {
11806         /* out is already checked to be a valid number or "" */
11807         int fd = (*out == '\0' ? -1 : atoi(out));
11808         union node *np;
11809
11810         np = stzalloc(sizeof(struct nfile));
11811         if (c == '>') {
11812                 np->nfile.fd = 1;
11813                 c = pgetc();
11814                 if (c == '>')
11815                         np->type = NAPPEND;
11816                 else if (c == '|')
11817                         np->type = NCLOBBER;
11818                 else if (c == '&')
11819                         np->type = NTOFD;
11820                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11821                 else {
11822                         np->type = NTO;
11823                         pungetc();
11824                 }
11825         }
11826 #if BASH_REDIR_OUTPUT
11827         else if (c == 0x100 + '>') { /* this flags &> redirection */
11828                 np->nfile.fd = 1;
11829                 pgetc(); /* this is '>', no need to check */
11830                 np->type = NTO2;
11831         }
11832 #endif
11833         else { /* c == '<' */
11834                 /*np->nfile.fd = 0; - stzalloc did it */
11835                 c = pgetc();
11836                 switch (c) {
11837                 case '<':
11838                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11839                                 np = stzalloc(sizeof(struct nhere));
11840                                 /*np->nfile.fd = 0; - stzalloc did it */
11841                         }
11842                         np->type = NHERE;
11843                         heredoc = stzalloc(sizeof(struct heredoc));
11844                         heredoc->here = np;
11845                         c = pgetc();
11846                         if (c == '-') {
11847                                 heredoc->striptabs = 1;
11848                         } else {
11849                                 /*heredoc->striptabs = 0; - stzalloc did it */
11850                                 pungetc();
11851                         }
11852                         break;
11853
11854                 case '&':
11855                         np->type = NFROMFD;
11856                         break;
11857
11858                 case '>':
11859                         np->type = NFROMTO;
11860                         break;
11861
11862                 default:
11863                         np->type = NFROM;
11864                         pungetc();
11865                         break;
11866                 }
11867         }
11868         if (fd >= 0)
11869                 np->nfile.fd = fd;
11870         redirnode = np;
11871         goto parseredir_return;
11872 }
11873
11874 /*
11875  * Parse a substitution.  At this point, we have read the dollar sign
11876  * and nothing else.
11877  */
11878
11879 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11880  * (assuming ascii char codes, as the original implementation did) */
11881 #define is_special(c) \
11882         (((unsigned)(c) - 33 < 32) \
11883                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11884 parsesub: {
11885         unsigned char subtype;
11886         int typeloc;
11887
11888         c = pgetc_eatbnl();
11889         if (c > 255 /* PEOA or PEOF */
11890          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11891         ) {
11892 #if BASH_DOLLAR_SQUOTE
11893                 if (syntax != DQSYNTAX && c == '\'')
11894                         bash_dollar_squote = 1;
11895                 else
11896 #endif
11897                         USTPUTC('$', out);
11898                 pungetc();
11899         } else if (c == '(') {
11900                 /* $(command) or $((arith)) */
11901                 if (pgetc_eatbnl() == '(') {
11902 #if ENABLE_FEATURE_SH_MATH
11903                         PARSEARITH();
11904 #else
11905                         raise_error_syntax("you disabled math support for $((arith)) syntax");
11906 #endif
11907                 } else {
11908                         pungetc();
11909                         PARSEBACKQNEW();
11910                 }
11911         } else {
11912                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11913                 USTPUTC(CTLVAR, out);
11914                 typeloc = out - (char *)stackblock();
11915                 STADJUST(1, out);
11916                 subtype = VSNORMAL;
11917                 if (c == '{') {
11918                         c = pgetc_eatbnl();
11919                         subtype = 0;
11920                 }
11921  varname:
11922                 if (is_name(c)) {
11923                         /* $[{[#]]NAME[}] */
11924                         do {
11925                                 STPUTC(c, out);
11926                                 c = pgetc_eatbnl();
11927                         } while (is_in_name(c));
11928                 } else if (isdigit(c)) {
11929                         /* $[{[#]]NUM[}] */
11930                         do {
11931                                 STPUTC(c, out);
11932                                 c = pgetc_eatbnl();
11933                         } while (isdigit(c));
11934                 } else if (is_special(c)) {
11935                         /* $[{[#]]<specialchar>[}] */
11936                         int cc = c;
11937
11938                         c = pgetc_eatbnl();
11939                         if (!subtype && cc == '#') {
11940                                 subtype = VSLENGTH;
11941                                 if (c == '_' || isalnum(c))
11942                                         goto varname;
11943                                 cc = c;
11944                                 c = pgetc_eatbnl();
11945                                 if (cc == '}' || c != '}') {
11946                                         pungetc();
11947                                         subtype = 0;
11948                                         c = cc;
11949                                         cc = '#';
11950                                 }
11951                         }
11952                         USTPUTC(cc, out);
11953                 } else {
11954                         goto badsub;
11955                 }
11956                 if (c != '}' && subtype == VSLENGTH) {
11957                         /* ${#VAR didn't end with } */
11958                         goto badsub;
11959                 }
11960
11961                 if (subtype == 0) {
11962                         static const char types[] ALIGN1 = "}-+?=";
11963                         /* ${VAR...} but not $VAR or ${#VAR} */
11964                         /* c == first char after VAR */
11965                         switch (c) {
11966                         case ':':
11967                                 c = pgetc_eatbnl();
11968 #if BASH_SUBSTR
11969                                 /* This check is only needed to not misinterpret
11970                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11971                                  * constructs.
11972                                  */
11973                                 if (!strchr(types, c)) {
11974                                         subtype = VSSUBSTR;
11975                                         pungetc();
11976                                         break; /* "goto badsub" is bigger (!) */
11977                                 }
11978 #endif
11979                                 subtype = VSNUL;
11980                                 /*FALLTHROUGH*/
11981                         default: {
11982                                 const char *p = strchr(types, c);
11983                                 if (p == NULL)
11984                                         break;
11985                                 subtype |= p - types + VSNORMAL;
11986                                 break;
11987                         }
11988                         case '%':
11989                         case '#': {
11990                                 int cc = c;
11991                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11992                                 c = pgetc_eatbnl();
11993                                 if (c != cc)
11994                                         goto badsub;
11995                                 subtype++;
11996                                 break;
11997                         }
11998 #if BASH_PATTERN_SUBST
11999                         case '/':
12000                                 /* ${v/[/]pattern/repl} */
12001 //TODO: encode pattern and repl separately.
12002 // Currently ${v/$var_with_slash/repl} is horribly broken
12003                                 subtype = VSREPLACE;
12004                                 c = pgetc_eatbnl();
12005                                 if (c != '/')
12006                                         goto badsub;
12007                                 subtype++; /* VSREPLACEALL */
12008                                 break;
12009 #endif
12010                         }
12011                 } else {
12012  badsub:
12013                         pungetc();
12014                 }
12015                 ((unsigned char *)stackblock())[typeloc] = subtype;
12016                 if (subtype != VSNORMAL) {
12017                         varnest++;
12018                         if (dblquote)
12019                                 dqvarnest++;
12020                 }
12021                 STPUTC('=', out);
12022         }
12023         goto parsesub_return;
12024 }
12025
12026 /*
12027  * Called to parse command substitutions.  Newstyle is set if the command
12028  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12029  * list of commands (passed by reference), and savelen is the number of
12030  * characters on the top of the stack which must be preserved.
12031  */
12032 parsebackq: {
12033         struct nodelist **nlpp;
12034         union node *n;
12035         char *str;
12036         size_t savelen;
12037         smallint saveprompt = 0;
12038
12039         str = NULL;
12040         savelen = out - (char *)stackblock();
12041         if (savelen > 0) {
12042                 /*
12043                  * FIXME: this can allocate very large block on stack and SEGV.
12044                  * Example:
12045                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12046                  * allocates 100kb for every command subst. With about
12047                  * a hundred command substitutions stack overflows.
12048                  * With larger prepended string, SEGV happens sooner.
12049                  */
12050                 str = alloca(savelen);
12051                 memcpy(str, stackblock(), savelen);
12052         }
12053
12054         if (oldstyle) {
12055                 /* We must read until the closing backquote, giving special
12056                  * treatment to some slashes, and then push the string and
12057                  * reread it as input, interpreting it normally.
12058                  */
12059                 char *pout;
12060                 size_t psavelen;
12061                 char *pstr;
12062
12063                 STARTSTACKSTR(pout);
12064                 for (;;) {
12065                         int pc;
12066
12067                         setprompt_if(needprompt, 2);
12068                         pc = pgetc();
12069                         switch (pc) {
12070                         case '`':
12071                                 goto done;
12072
12073                         case '\\':
12074                                 pc = pgetc();
12075                                 if (pc == '\n') {
12076                                         nlprompt();
12077                                         /*
12078                                          * If eating a newline, avoid putting
12079                                          * the newline into the new character
12080                                          * stream (via the STPUTC after the
12081                                          * switch).
12082                                          */
12083                                         continue;
12084                                 }
12085                                 if (pc != '\\' && pc != '`' && pc != '$'
12086                                  && (!dblquote || pc != '"')
12087                                 ) {
12088                                         STPUTC('\\', pout);
12089                                 }
12090                                 if (pc <= 255 /* not PEOA or PEOF */) {
12091                                         break;
12092                                 }
12093                                 /* fall through */
12094
12095                         case PEOF:
12096                         IF_ASH_ALIAS(case PEOA:)
12097                                 startlinno = g_parsefile->linno;
12098                                 raise_error_syntax("EOF in backquote substitution");
12099
12100                         case '\n':
12101                                 nlnoprompt();
12102                                 break;
12103
12104                         default:
12105                                 break;
12106                         }
12107                         STPUTC(pc, pout);
12108                 }
12109  done:
12110                 STPUTC('\0', pout);
12111                 psavelen = pout - (char *)stackblock();
12112                 if (psavelen > 0) {
12113                         pstr = grabstackstr(pout);
12114                         setinputstring(pstr);
12115                 }
12116         }
12117         nlpp = &bqlist;
12118         while (*nlpp)
12119                 nlpp = &(*nlpp)->next;
12120         *nlpp = stzalloc(sizeof(**nlpp));
12121         /* (*nlpp)->next = NULL; - stzalloc did it */
12122
12123         if (oldstyle) {
12124                 saveprompt = doprompt;
12125                 doprompt = 0;
12126         }
12127
12128         n = list(2);
12129
12130         if (oldstyle)
12131                 doprompt = saveprompt;
12132         else if (readtoken() != TRP)
12133                 raise_error_unexpected_syntax(TRP);
12134
12135         (*nlpp)->n = n;
12136         if (oldstyle) {
12137                 /*
12138                  * Start reading from old file again, ignoring any pushed back
12139                  * tokens left from the backquote parsing
12140                  */
12141                 popfile();
12142                 tokpushback = 0;
12143         }
12144         while (stackblocksize() <= savelen)
12145                 growstackblock();
12146         STARTSTACKSTR(out);
12147         if (str) {
12148                 memcpy(out, str, savelen);
12149                 STADJUST(savelen, out);
12150         }
12151         USTPUTC(CTLBACKQ, out);
12152         if (oldstyle)
12153                 goto parsebackq_oldreturn;
12154         goto parsebackq_newreturn;
12155 }
12156
12157 #if ENABLE_FEATURE_SH_MATH
12158 /*
12159  * Parse an arithmetic expansion (indicate start of one and set state)
12160  */
12161 parsearith: {
12162         if (++arinest == 1) {
12163                 prevsyntax = syntax;
12164                 syntax = ARISYNTAX;
12165         }
12166         USTPUTC(CTLARI, out);
12167         goto parsearith_return;
12168 }
12169 #endif
12170 } /* end of readtoken */
12171
12172 /*
12173  * Read the next input token.
12174  * If the token is a word, we set backquotelist to the list of cmds in
12175  *      backquotes.  We set quoteflag to true if any part of the word was
12176  *      quoted.
12177  * If the token is TREDIR, then we set redirnode to a structure containing
12178  *      the redirection.
12179  * In all cases, the variable startlinno is set to the number of the line
12180  *      on which the token starts.
12181  *
12182  * [Change comment:  here documents and internal procedures]
12183  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12184  *  word parsing code into a separate routine.  In this case, readtoken
12185  *  doesn't need to have any internal procedures, but parseword does.
12186  *  We could also make parseoperator in essence the main routine, and
12187  *  have parseword (readtoken1?) handle both words and redirection.]
12188  */
12189 #define NEW_xxreadtoken
12190 #ifdef NEW_xxreadtoken
12191 /* singles must be first! */
12192 static const char xxreadtoken_chars[7] ALIGN1 = {
12193         '\n', '(', ')', /* singles */
12194         '&', '|', ';',  /* doubles */
12195         0
12196 };
12197
12198 #define xxreadtoken_singles 3
12199 #define xxreadtoken_doubles 3
12200
12201 static const char xxreadtoken_tokens[] ALIGN1 = {
12202         TNL, TLP, TRP,          /* only single occurrence allowed */
12203         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12204         TEOF,                   /* corresponds to trailing nul */
12205         TAND, TOR, TENDCASE     /* if double occurrence */
12206 };
12207
12208 static int
12209 xxreadtoken(void)
12210 {
12211         int c;
12212
12213         if (tokpushback) {
12214                 tokpushback = 0;
12215                 return lasttoken;
12216         }
12217         setprompt_if(needprompt, 2);
12218         startlinno = g_parsefile->linno;
12219         for (;;) {                      /* until token or start of word found */
12220                 c = pgetc();
12221                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12222                         continue;
12223
12224                 if (c == '#') {
12225                         while ((c = pgetc()) != '\n' && c != PEOF)
12226                                 continue;
12227                         pungetc();
12228                 } else if (c == '\\') {
12229                         if (pgetc() != '\n') {
12230                                 pungetc();
12231                                 break; /* return readtoken1(...) */
12232                         }
12233                         nlprompt();
12234                 } else {
12235                         const char *p;
12236
12237                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12238                         if (c != PEOF) {
12239                                 if (c == '\n') {
12240                                         nlnoprompt();
12241                                 }
12242
12243                                 p = strchr(xxreadtoken_chars, c);
12244                                 if (p == NULL)
12245                                         break; /* return readtoken1(...) */
12246
12247                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12248                                         int cc = pgetc();
12249                                         if (cc == c) {    /* double occurrence? */
12250                                                 p += xxreadtoken_doubles + 1;
12251                                         } else {
12252                                                 pungetc();
12253 #if BASH_REDIR_OUTPUT
12254                                                 if (c == '&' && cc == '>') /* &> */
12255                                                         break; /* return readtoken1(...) */
12256 #endif
12257                                         }
12258                                 }
12259                         }
12260                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12261                         return lasttoken;
12262                 }
12263         } /* for (;;) */
12264
12265         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12266 }
12267 #else /* old xxreadtoken */
12268 #define RETURN(token)   return lasttoken = token
12269 static int
12270 xxreadtoken(void)
12271 {
12272         int c;
12273
12274         if (tokpushback) {
12275                 tokpushback = 0;
12276                 return lasttoken;
12277         }
12278         setprompt_if(needprompt, 2);
12279         startlinno = g_parsefile->linno;
12280         for (;;) {      /* until token or start of word found */
12281                 c = pgetc();
12282                 switch (c) {
12283                 case ' ': case '\t':
12284                 IF_ASH_ALIAS(case PEOA:)
12285                         continue;
12286                 case '#':
12287                         while ((c = pgetc()) != '\n' && c != PEOF)
12288                                 continue;
12289                         pungetc();
12290                         continue;
12291                 case '\\':
12292                         if (pgetc() == '\n') {
12293                                 nlprompt();
12294                                 continue;
12295                         }
12296                         pungetc();
12297                         goto breakloop;
12298                 case '\n':
12299                         nlnoprompt();
12300                         RETURN(TNL);
12301                 case PEOF:
12302                         RETURN(TEOF);
12303                 case '&':
12304                         if (pgetc() == '&')
12305                                 RETURN(TAND);
12306                         pungetc();
12307                         RETURN(TBACKGND);
12308                 case '|':
12309                         if (pgetc() == '|')
12310                                 RETURN(TOR);
12311                         pungetc();
12312                         RETURN(TPIPE);
12313                 case ';':
12314                         if (pgetc() == ';')
12315                                 RETURN(TENDCASE);
12316                         pungetc();
12317                         RETURN(TSEMI);
12318                 case '(':
12319                         RETURN(TLP);
12320                 case ')':
12321                         RETURN(TRP);
12322                 default:
12323                         goto breakloop;
12324                 }
12325         }
12326  breakloop:
12327         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12328 #undef RETURN
12329 }
12330 #endif /* old xxreadtoken */
12331
12332 static int
12333 readtoken(void)
12334 {
12335         int t;
12336         int kwd = checkkwd;
12337 #if DEBUG
12338         smallint alreadyseen = tokpushback;
12339 #endif
12340
12341 #if ENABLE_ASH_ALIAS
12342  top:
12343 #endif
12344
12345         t = xxreadtoken();
12346
12347         /*
12348          * eat newlines
12349          */
12350         if (kwd & CHKNL) {
12351                 while (t == TNL) {
12352                         parseheredoc();
12353                         t = xxreadtoken();
12354                 }
12355         }
12356
12357         if (t != TWORD || quoteflag) {
12358                 goto out;
12359         }
12360
12361         /*
12362          * check for keywords
12363          */
12364         if (kwd & CHKKWD) {
12365                 const char *const *pp;
12366
12367                 pp = findkwd(wordtext);
12368                 if (pp) {
12369                         lasttoken = t = pp - tokname_array;
12370                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12371                         goto out;
12372                 }
12373         }
12374
12375         if (checkkwd & CHKALIAS) {
12376 #if ENABLE_ASH_ALIAS
12377                 struct alias *ap;
12378                 ap = lookupalias(wordtext, 1);
12379                 if (ap != NULL) {
12380                         if (*ap->val) {
12381                                 pushstring(ap->val, ap);
12382                         }
12383                         goto top;
12384                 }
12385 #endif
12386         }
12387  out:
12388         checkkwd = 0;
12389 #if DEBUG
12390         if (!alreadyseen)
12391                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12392         else
12393                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12394 #endif
12395         return t;
12396 }
12397
12398 static int
12399 peektoken(void)
12400 {
12401         int t;
12402
12403         t = readtoken();
12404         tokpushback = 1;
12405         return t;
12406 }
12407
12408 /*
12409  * Read and parse a command.  Returns NODE_EOF on end of file.
12410  * (NULL is a valid parse tree indicating a blank line.)
12411  */
12412 static union node *
12413 parsecmd(int interact)
12414 {
12415         tokpushback = 0;
12416         checkkwd = 0;
12417         heredoclist = 0;
12418         doprompt = interact;
12419         setprompt_if(doprompt, doprompt);
12420         needprompt = 0;
12421         return list(1);
12422 }
12423
12424 /*
12425  * Input any here documents.
12426  */
12427 static void
12428 parseheredoc(void)
12429 {
12430         struct heredoc *here;
12431         union node *n;
12432
12433         here = heredoclist;
12434         heredoclist = NULL;
12435
12436         while (here) {
12437                 setprompt_if(needprompt, 2);
12438                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12439                                 here->eofmark, here->striptabs);
12440                 n = stzalloc(sizeof(struct narg));
12441                 n->narg.type = NARG;
12442                 /*n->narg.next = NULL; - stzalloc did it */
12443                 n->narg.text = wordtext;
12444                 n->narg.backquote = backquotelist;
12445                 here->here->nhere.doc = n;
12446                 here = here->next;
12447         }
12448 }
12449
12450
12451 /*
12452  * called by editline -- any expansions to the prompt should be added here.
12453  */
12454 #if ENABLE_ASH_EXPAND_PRMT
12455 static const char *
12456 expandstr(const char *ps)
12457 {
12458         union node n;
12459         int saveprompt;
12460
12461         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12462          * and token processing _can_ alter it (delete NULs etc). */
12463         setinputstring((char *)ps);
12464
12465         saveprompt = doprompt;
12466         doprompt = 0;
12467         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12468         doprompt = saveprompt;
12469
12470         popfile();
12471
12472         n.narg.type = NARG;
12473         n.narg.next = NULL;
12474         n.narg.text = wordtext;
12475         n.narg.backquote = backquotelist;
12476
12477         expandarg(&n, NULL, EXP_QUOTED);
12478         return stackblock();
12479 }
12480 #endif
12481
12482 /*
12483  * Execute a command or commands contained in a string.
12484  */
12485 static int
12486 evalstring(char *s, int flags)
12487 {
12488         struct jmploc *volatile savehandler;
12489         struct jmploc jmploc;
12490         int ex;
12491
12492         union node *n;
12493         struct stackmark smark;
12494         int status;
12495
12496         s = sstrdup(s);
12497         setinputstring(s);
12498         setstackmark(&smark);
12499
12500         status = 0;
12501         /* On exception inside execution loop, we must popfile().
12502          * Try interactively:
12503          *      readonly a=a
12504          *      command eval "a=b"  # throws "is read only" error
12505          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12506          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12507          */
12508         savehandler = exception_handler;
12509         ex = setjmp(jmploc.loc);
12510         if (ex)
12511                 goto out;
12512         exception_handler = &jmploc;
12513
12514         while ((n = parsecmd(0)) != NODE_EOF) {
12515                 int i;
12516
12517                 i = evaltree(n, flags);
12518                 if (n)
12519                         status = i;
12520                 popstackmark(&smark);
12521                 if (evalskip)
12522                         break;
12523         }
12524  out:
12525         popstackmark(&smark);
12526         popfile();
12527         stunalloc(s);
12528
12529         exception_handler = savehandler;
12530         if (ex)
12531                 longjmp(exception_handler->loc, ex);
12532
12533         return status;
12534 }
12535
12536 /*
12537  * The eval command.
12538  */
12539 static int FAST_FUNC
12540 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12541 {
12542         char *p;
12543         char *concat;
12544
12545         if (argv[1]) {
12546                 p = argv[1];
12547                 argv += 2;
12548                 if (argv[0]) {
12549                         STARTSTACKSTR(concat);
12550                         for (;;) {
12551                                 concat = stack_putstr(p, concat);
12552                                 p = *argv++;
12553                                 if (p == NULL)
12554                                         break;
12555                                 STPUTC(' ', concat);
12556                         }
12557                         STPUTC('\0', concat);
12558                         p = grabstackstr(concat);
12559                 }
12560                 return evalstring(p, flags & EV_TESTED);
12561         }
12562         return 0;
12563 }
12564
12565 /*
12566  * Read and execute commands.
12567  * "Top" is nonzero for the top level command loop;
12568  * it turns on prompting if the shell is interactive.
12569  */
12570 static int
12571 cmdloop(int top)
12572 {
12573         union node *n;
12574         struct stackmark smark;
12575         int inter;
12576         int status = 0;
12577         int numeof = 0;
12578
12579         TRACE(("cmdloop(%d) called\n", top));
12580         for (;;) {
12581                 int skip;
12582
12583                 setstackmark(&smark);
12584 #if JOBS
12585                 if (doing_jobctl)
12586                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12587 #endif
12588                 inter = 0;
12589                 if (iflag && top) {
12590                         inter++;
12591                         chkmail();
12592                 }
12593                 n = parsecmd(inter);
12594 #if DEBUG
12595                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12596                         showtree(n);
12597 #endif
12598                 if (n == NODE_EOF) {
12599                         if (!top || numeof >= 50)
12600                                 break;
12601                         if (!stoppedjobs()) {
12602                                 if (!Iflag)
12603                                         break;
12604                                 out2str("\nUse \"exit\" to leave shell.\n");
12605                         }
12606                         numeof++;
12607                 } else if (nflag == 0) {
12608                         int i;
12609
12610                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12611                         job_warning >>= 1;
12612                         numeof = 0;
12613                         i = evaltree(n, 0);
12614                         if (n)
12615                                 status = i;
12616                 }
12617                 popstackmark(&smark);
12618                 skip = evalskip;
12619
12620                 if (skip) {
12621                         evalskip &= ~SKIPFUNC;
12622                         break;
12623                 }
12624         }
12625         return status;
12626 }
12627
12628 /*
12629  * Take commands from a file.  To be compatible we should do a path
12630  * search for the file, which is necessary to find sub-commands.
12631  */
12632 static char *
12633 find_dot_file(char *name)
12634 {
12635         char *fullname;
12636         const char *path = pathval();
12637         struct stat statb;
12638
12639         /* don't try this for absolute or relative paths */
12640         if (strchr(name, '/'))
12641                 return name;
12642
12643         while ((fullname = path_advance(&path, name)) != NULL) {
12644                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12645                         /*
12646                          * Don't bother freeing here, since it will
12647                          * be freed by the caller.
12648                          */
12649                         return fullname;
12650                 }
12651                 if (fullname != name)
12652                         stunalloc(fullname);
12653         }
12654
12655         /* not found in the PATH */
12656         ash_msg_and_raise_error("%s: not found", name);
12657         /* NOTREACHED */
12658 }
12659
12660 static int FAST_FUNC
12661 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12662 {
12663         /* "false; . empty_file; echo $?" should print 0, not 1: */
12664         int status = 0;
12665         char *fullname;
12666         char **argv;
12667         char *args_need_save;
12668         struct strlist *sp;
12669         volatile struct shparam saveparam;
12670
12671         for (sp = cmdenviron; sp; sp = sp->next)
12672                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12673
12674         nextopt(nullstr); /* handle possible "--" */
12675         argv = argptr;
12676
12677         if (!argv[0]) {
12678                 /* bash says: "bash: .: filename argument required" */
12679                 return 2; /* bash compat */
12680         }
12681
12682         /* This aborts if file isn't found, which is POSIXly correct.
12683          * bash returns exitcode 1 instead.
12684          */
12685         fullname = find_dot_file(argv[0]);
12686         argv++;
12687         args_need_save = argv[0];
12688         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12689                 int argc;
12690                 saveparam = shellparam;
12691                 shellparam.malloced = 0;
12692                 argc = 1;
12693                 while (argv[argc])
12694                         argc++;
12695                 shellparam.nparam = argc;
12696                 shellparam.p = argv;
12697         };
12698
12699         /* This aborts if file can't be opened, which is POSIXly correct.
12700          * bash returns exitcode 1 instead.
12701          */
12702         setinputfile(fullname, INPUT_PUSH_FILE);
12703         commandname = fullname;
12704         status = cmdloop(0);
12705         popfile();
12706
12707         if (args_need_save) {
12708                 freeparam(&shellparam);
12709                 shellparam = saveparam;
12710         };
12711
12712         return status;
12713 }
12714
12715 static int FAST_FUNC
12716 exitcmd(int argc UNUSED_PARAM, char **argv)
12717 {
12718         if (stoppedjobs())
12719                 return 0;
12720         if (argv[1])
12721                 exitstatus = number(argv[1]);
12722         raise_exception(EXEXIT);
12723         /* NOTREACHED */
12724 }
12725
12726 /*
12727  * Read a file containing shell functions.
12728  */
12729 static void
12730 readcmdfile(char *name)
12731 {
12732         setinputfile(name, INPUT_PUSH_FILE);
12733         cmdloop(0);
12734         popfile();
12735 }
12736
12737
12738 /* ============ find_command inplementation */
12739
12740 /*
12741  * Resolve a command name.  If you change this routine, you may have to
12742  * change the shellexec routine as well.
12743  */
12744 static void
12745 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12746 {
12747         struct tblentry *cmdp;
12748         int idx;
12749         int prev;
12750         char *fullname;
12751         struct stat statb;
12752         int e;
12753         int updatetbl;
12754         struct builtincmd *bcmd;
12755
12756         /* If name contains a slash, don't use PATH or hash table */
12757         if (strchr(name, '/') != NULL) {
12758                 entry->u.index = -1;
12759                 if (act & DO_ABS) {
12760                         while (stat(name, &statb) < 0) {
12761 #ifdef SYSV
12762                                 if (errno == EINTR)
12763                                         continue;
12764 #endif
12765                                 entry->cmdtype = CMDUNKNOWN;
12766                                 return;
12767                         }
12768                 }
12769                 entry->cmdtype = CMDNORMAL;
12770                 return;
12771         }
12772
12773 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12774
12775         updatetbl = (path == pathval());
12776         if (!updatetbl) {
12777                 act |= DO_ALTPATH;
12778                 if (strstr(path, "%builtin") != NULL)
12779                         act |= DO_ALTBLTIN;
12780         }
12781
12782         /* If name is in the table, check answer will be ok */
12783         cmdp = cmdlookup(name, 0);
12784         if (cmdp != NULL) {
12785                 int bit;
12786
12787                 switch (cmdp->cmdtype) {
12788                 default:
12789 #if DEBUG
12790                         abort();
12791 #endif
12792                 case CMDNORMAL:
12793                         bit = DO_ALTPATH;
12794                         break;
12795                 case CMDFUNCTION:
12796                         bit = DO_NOFUNC;
12797                         break;
12798                 case CMDBUILTIN:
12799                         bit = DO_ALTBLTIN;
12800                         break;
12801                 }
12802                 if (act & bit) {
12803                         updatetbl = 0;
12804                         cmdp = NULL;
12805                 } else if (cmdp->rehash == 0)
12806                         /* if not invalidated by cd, we're done */
12807                         goto success;
12808         }
12809
12810         /* If %builtin not in path, check for builtin next */
12811         bcmd = find_builtin(name);
12812         if (bcmd) {
12813                 if (IS_BUILTIN_REGULAR(bcmd))
12814                         goto builtin_success;
12815                 if (act & DO_ALTPATH) {
12816                         if (!(act & DO_ALTBLTIN))
12817                                 goto builtin_success;
12818                 } else if (builtinloc <= 0) {
12819                         goto builtin_success;
12820                 }
12821         }
12822
12823 #if ENABLE_FEATURE_SH_STANDALONE
12824         {
12825                 int applet_no = find_applet_by_name(name);
12826                 if (applet_no >= 0) {
12827                         entry->cmdtype = CMDNORMAL;
12828                         entry->u.index = -2 - applet_no;
12829                         return;
12830                 }
12831         }
12832 #endif
12833
12834         /* We have to search path. */
12835         prev = -1;              /* where to start */
12836         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12837                 if (cmdp->cmdtype == CMDBUILTIN)
12838                         prev = builtinloc;
12839                 else
12840                         prev = cmdp->param.index;
12841         }
12842
12843         e = ENOENT;
12844         idx = -1;
12845  loop:
12846         while ((fullname = path_advance(&path, name)) != NULL) {
12847                 stunalloc(fullname);
12848                 /* NB: code below will still use fullname
12849                  * despite it being "unallocated" */
12850                 idx++;
12851                 if (pathopt) {
12852                         if (prefix(pathopt, "builtin")) {
12853                                 if (bcmd)
12854                                         goto builtin_success;
12855                                 continue;
12856                         }
12857                         if ((act & DO_NOFUNC)
12858                          || !prefix(pathopt, "func")
12859                         ) {     /* ignore unimplemented options */
12860                                 continue;
12861                         }
12862                 }
12863                 /* if rehash, don't redo absolute path names */
12864                 if (fullname[0] == '/' && idx <= prev) {
12865                         if (idx < prev)
12866                                 continue;
12867                         TRACE(("searchexec \"%s\": no change\n", name));
12868                         goto success;
12869                 }
12870                 while (stat(fullname, &statb) < 0) {
12871 #ifdef SYSV
12872                         if (errno == EINTR)
12873                                 continue;
12874 #endif
12875                         if (errno != ENOENT && errno != ENOTDIR)
12876                                 e = errno;
12877                         goto loop;
12878                 }
12879                 e = EACCES;     /* if we fail, this will be the error */
12880                 if (!S_ISREG(statb.st_mode))
12881                         continue;
12882                 if (pathopt) {          /* this is a %func directory */
12883                         stalloc(strlen(fullname) + 1);
12884                         /* NB: stalloc will return space pointed by fullname
12885                          * (because we don't have any intervening allocations
12886                          * between stunalloc above and this stalloc) */
12887                         readcmdfile(fullname);
12888                         cmdp = cmdlookup(name, 0);
12889                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12890                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12891                         stunalloc(fullname);
12892                         goto success;
12893                 }
12894                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12895                 if (!updatetbl) {
12896                         entry->cmdtype = CMDNORMAL;
12897                         entry->u.index = idx;
12898                         return;
12899                 }
12900                 INT_OFF;
12901                 cmdp = cmdlookup(name, 1);
12902                 cmdp->cmdtype = CMDNORMAL;
12903                 cmdp->param.index = idx;
12904                 INT_ON;
12905                 goto success;
12906         }
12907
12908         /* We failed.  If there was an entry for this command, delete it */
12909         if (cmdp && updatetbl)
12910                 delete_cmd_entry();
12911         if (act & DO_ERR)
12912                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12913         entry->cmdtype = CMDUNKNOWN;
12914         return;
12915
12916  builtin_success:
12917         if (!updatetbl) {
12918                 entry->cmdtype = CMDBUILTIN;
12919                 entry->u.cmd = bcmd;
12920                 return;
12921         }
12922         INT_OFF;
12923         cmdp = cmdlookup(name, 1);
12924         cmdp->cmdtype = CMDBUILTIN;
12925         cmdp->param.cmd = bcmd;
12926         INT_ON;
12927  success:
12928         cmdp->rehash = 0;
12929         entry->cmdtype = cmdp->cmdtype;
12930         entry->u = cmdp->param;
12931 }
12932
12933
12934 /*
12935  * The trap builtin.
12936  */
12937 static int FAST_FUNC
12938 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12939 {
12940         char *action;
12941         char **ap;
12942         int signo, exitcode;
12943
12944         nextopt(nullstr);
12945         ap = argptr;
12946         if (!*ap) {
12947                 for (signo = 0; signo < NSIG; signo++) {
12948                         char *tr = trap_ptr[signo];
12949                         if (tr) {
12950                                 /* note: bash adds "SIG", but only if invoked
12951                                  * as "bash". If called as "sh", or if set -o posix,
12952                                  * then it prints short signal names.
12953                                  * We are printing short names: */
12954                                 out1fmt("trap -- %s %s\n",
12955                                                 single_quote(tr),
12956                                                 get_signame(signo));
12957                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12958                  * In this case, we will exit very soon, no need to free(). */
12959                                 /* if (trap_ptr != trap && tp[0]) */
12960                                 /*      free(tr); */
12961                         }
12962                 }
12963                 /*
12964                 if (trap_ptr != trap) {
12965                         free(trap_ptr);
12966                         trap_ptr = trap;
12967                 }
12968                 */
12969                 return 0;
12970         }
12971
12972         action = NULL;
12973         if (ap[1])
12974                 action = *ap++;
12975         exitcode = 0;
12976         while (*ap) {
12977                 signo = get_signum(*ap);
12978                 if (signo < 0) {
12979                         /* Mimic bash message exactly */
12980                         ash_msg("%s: invalid signal specification", *ap);
12981                         exitcode = 1;
12982                         goto next;
12983                 }
12984                 INT_OFF;
12985                 if (action) {
12986                         if (LONE_DASH(action))
12987                                 action = NULL;
12988                         else {
12989                                 if (action[0]) /* not NULL and not "" and not "-" */
12990                                         may_have_traps = 1;
12991                                 action = ckstrdup(action);
12992                         }
12993                 }
12994                 free(trap[signo]);
12995                 trap[signo] = action;
12996                 if (signo != 0)
12997                         setsignal(signo);
12998                 INT_ON;
12999  next:
13000                 ap++;
13001         }
13002         return exitcode;
13003 }
13004
13005
13006 /* ============ Builtins */
13007
13008 #if ENABLE_ASH_HELP
13009 static int FAST_FUNC
13010 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13011 {
13012         unsigned col;
13013         unsigned i;
13014
13015         out1fmt(
13016                 "Built-in commands:\n"
13017                 "------------------\n");
13018         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13019                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13020                                         builtintab[i].name + 1);
13021                 if (col > 60) {
13022                         out1fmt("\n");
13023                         col = 0;
13024                 }
13025         }
13026 # if ENABLE_FEATURE_SH_STANDALONE
13027         {
13028                 const char *a = applet_names;
13029                 while (*a) {
13030                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13031                         if (col > 60) {
13032                                 out1fmt("\n");
13033                                 col = 0;
13034                         }
13035                         while (*a++ != '\0')
13036                                 continue;
13037                 }
13038         }
13039 # endif
13040         newline_and_flush(stdout);
13041         return EXIT_SUCCESS;
13042 }
13043 #endif
13044
13045 #if MAX_HISTORY
13046 static int FAST_FUNC
13047 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13048 {
13049         show_history(line_input_state);
13050         return EXIT_SUCCESS;
13051 }
13052 #endif
13053
13054 /*
13055  * The export and readonly commands.
13056  */
13057 static int FAST_FUNC
13058 exportcmd(int argc UNUSED_PARAM, char **argv)
13059 {
13060         struct var *vp;
13061         char *name;
13062         const char *p;
13063         char **aptr;
13064         char opt;
13065         int flag;
13066         int flag_off;
13067
13068         /* "readonly" in bash accepts, but ignores -n.
13069          * We do the same: it saves a conditional in nextopt's param.
13070          */
13071         flag_off = 0;
13072         while ((opt = nextopt("np")) != '\0') {
13073                 if (opt == 'n')
13074                         flag_off = VEXPORT;
13075         }
13076         flag = VEXPORT;
13077         if (argv[0][0] == 'r') {
13078                 flag = VREADONLY;
13079                 flag_off = 0; /* readonly ignores -n */
13080         }
13081         flag_off = ~flag_off;
13082
13083         /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
13084         {
13085                 aptr = argptr;
13086                 name = *aptr;
13087                 if (name) {
13088                         do {
13089                                 p = strchr(name, '=');
13090                                 if (p != NULL) {
13091                                         p++;
13092                                 } else {
13093                                         vp = *findvar(hashvar(name), name);
13094                                         if (vp) {
13095                                                 vp->flags = ((vp->flags | flag) & flag_off);
13096                                                 continue;
13097                                         }
13098                                 }
13099                                 setvar(name, p, (flag & flag_off));
13100                         } while ((name = *++aptr) != NULL);
13101                         return 0;
13102                 }
13103         }
13104
13105         /* No arguments. Show the list of exported or readonly vars.
13106          * -n is ignored.
13107          */
13108         showvars(argv[0], flag, 0);
13109         return 0;
13110 }
13111
13112 /*
13113  * Delete a function if it exists.
13114  */
13115 static void
13116 unsetfunc(const char *name)
13117 {
13118         struct tblentry *cmdp;
13119
13120         cmdp = cmdlookup(name, 0);
13121         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13122                 delete_cmd_entry();
13123 }
13124
13125 /*
13126  * The unset builtin command.  We unset the function before we unset the
13127  * variable to allow a function to be unset when there is a readonly variable
13128  * with the same name.
13129  */
13130 static int FAST_FUNC
13131 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13132 {
13133         char **ap;
13134         int i;
13135         int flag = 0;
13136         int ret = 0;
13137
13138         while ((i = nextopt("vf")) != 0) {
13139                 flag = i;
13140         }
13141
13142         for (ap = argptr; *ap; ap++) {
13143                 if (flag != 'f') {
13144                         i = unsetvar(*ap);
13145                         ret |= i;
13146                         if (!(i & 2))
13147                                 continue;
13148                 }
13149                 if (flag != 'v')
13150                         unsetfunc(*ap);
13151         }
13152         return ret & 1;
13153 }
13154
13155 static const unsigned char timescmd_str[] ALIGN1 = {
13156         ' ',  offsetof(struct tms, tms_utime),
13157         '\n', offsetof(struct tms, tms_stime),
13158         ' ',  offsetof(struct tms, tms_cutime),
13159         '\n', offsetof(struct tms, tms_cstime),
13160         0
13161 };
13162 static int FAST_FUNC
13163 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13164 {
13165         unsigned long clk_tck, s, t;
13166         const unsigned char *p;
13167         struct tms buf;
13168
13169         clk_tck = bb_clk_tck();
13170         times(&buf);
13171
13172         p = timescmd_str;
13173         do {
13174                 t = *(clock_t *)(((char *) &buf) + p[1]);
13175                 s = t / clk_tck;
13176                 t = t % clk_tck;
13177                 out1fmt("%lum%lu.%03lus%c",
13178                         s / 60, s % 60,
13179                         (t * 1000) / clk_tck,
13180                         p[0]);
13181                 p += 2;
13182         } while (*p);
13183
13184         return 0;
13185 }
13186
13187 #if ENABLE_FEATURE_SH_MATH
13188 /*
13189  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13190  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13191  *
13192  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13193  */
13194 static int FAST_FUNC
13195 letcmd(int argc UNUSED_PARAM, char **argv)
13196 {
13197         arith_t i;
13198
13199         argv++;
13200         if (!*argv)
13201                 ash_msg_and_raise_error("expression expected");
13202         do {
13203                 i = ash_arith(*argv);
13204         } while (*++argv);
13205
13206         return !i;
13207 }
13208 #endif
13209
13210 /*
13211  * The read builtin. Options:
13212  *      -r              Do not interpret '\' specially
13213  *      -s              Turn off echo (tty only)
13214  *      -n NCHARS       Read NCHARS max
13215  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13216  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13217  *      -u FD           Read from given FD instead of fd 0
13218  * This uses unbuffered input, which may be avoidable in some cases.
13219  * TODO: bash also has:
13220  *      -a ARRAY        Read into array[0],[1],etc
13221  *      -d DELIM        End on DELIM char, not newline
13222  *      -e              Use line editing (tty only)
13223  */
13224 static int FAST_FUNC
13225 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13226 {
13227         char *opt_n = NULL;
13228         char *opt_p = NULL;
13229         char *opt_t = NULL;
13230         char *opt_u = NULL;
13231         int read_flags = 0;
13232         const char *r;
13233         int i;
13234
13235         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13236                 switch (i) {
13237                 case 'p':
13238                         opt_p = optionarg;
13239                         break;
13240                 case 'n':
13241                         opt_n = optionarg;
13242                         break;
13243                 case 's':
13244                         read_flags |= BUILTIN_READ_SILENT;
13245                         break;
13246                 case 't':
13247                         opt_t = optionarg;
13248                         break;
13249                 case 'r':
13250                         read_flags |= BUILTIN_READ_RAW;
13251                         break;
13252                 case 'u':
13253                         opt_u = optionarg;
13254                         break;
13255                 default:
13256                         break;
13257                 }
13258         }
13259
13260         /* "read -s" needs to save/restore termios, can't allow ^C
13261          * to jump out of it.
13262          */
13263         INT_OFF;
13264         r = shell_builtin_read(setvar0,
13265                 argptr,
13266                 bltinlookup("IFS"), /* can be NULL */
13267                 read_flags,
13268                 opt_n,
13269                 opt_p,
13270                 opt_t,
13271                 opt_u
13272         );
13273         INT_ON;
13274
13275         if ((uintptr_t)r > 1)
13276                 ash_msg_and_raise_error(r);
13277
13278         return (uintptr_t)r;
13279 }
13280
13281 static int FAST_FUNC
13282 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13283 {
13284         static const char permuser[3] ALIGN1 = "ogu";
13285
13286         mode_t mask;
13287         int symbolic_mode = 0;
13288
13289         while (nextopt("S") != '\0') {
13290                 symbolic_mode = 1;
13291         }
13292
13293         INT_OFF;
13294         mask = umask(0);
13295         umask(mask);
13296         INT_ON;
13297
13298         if (*argptr == NULL) {
13299                 if (symbolic_mode) {
13300                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13301                         char *p = buf;
13302                         int i;
13303
13304                         i = 2;
13305                         for (;;) {
13306                                 *p++ = ',';
13307                                 *p++ = permuser[i];
13308                                 *p++ = '=';
13309                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13310                                 if (!(mask & 0400)) *p++ = 'r';
13311                                 if (!(mask & 0200)) *p++ = 'w';
13312                                 if (!(mask & 0100)) *p++ = 'x';
13313                                 mask <<= 3;
13314                                 if (--i < 0)
13315                                         break;
13316                         }
13317                         *p = '\0';
13318                         puts(buf + 1);
13319                 } else {
13320                         out1fmt("%04o\n", mask);
13321                 }
13322         } else {
13323                 char *modestr = *argptr;
13324                 /* numeric umasks are taken as-is */
13325                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13326                 if (!isdigit(modestr[0]))
13327                         mask ^= 0777;
13328                 mask = bb_parse_mode(modestr, mask);
13329                 if ((unsigned)mask > 0777) {
13330                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13331                 }
13332                 if (!isdigit(modestr[0]))
13333                         mask ^= 0777;
13334                 umask(mask);
13335         }
13336         return 0;
13337 }
13338
13339 static int FAST_FUNC
13340 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13341 {
13342         return shell_builtin_ulimit(argv);
13343 }
13344
13345 /* ============ main() and helpers */
13346
13347 /*
13348  * Called to exit the shell.
13349  */
13350 static void
13351 exitshell(void)
13352 {
13353         struct jmploc loc;
13354         char *p;
13355         int status;
13356
13357 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13358         save_history(line_input_state);
13359 #endif
13360         status = exitstatus;
13361         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13362         if (setjmp(loc.loc)) {
13363                 if (exception_type == EXEXIT)
13364                         status = exitstatus;
13365                 goto out;
13366         }
13367         exception_handler = &loc;
13368         p = trap[0];
13369         if (p) {
13370                 trap[0] = NULL;
13371                 evalskip = 0;
13372                 evalstring(p, 0);
13373                 /*free(p); - we'll exit soon */
13374         }
13375  out:
13376         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13377          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13378          */
13379         setjobctl(0);
13380         flush_stdout_stderr();
13381         _exit(status);
13382         /* NOTREACHED */
13383 }
13384
13385 static void
13386 init(void)
13387 {
13388         /* we will never free this */
13389         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13390
13391         sigmode[SIGCHLD - 1] = S_DFL;
13392         setsignal(SIGCHLD);
13393
13394         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13395          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13396          */
13397         signal(SIGHUP, SIG_DFL);
13398
13399         {
13400                 char **envp;
13401                 const char *p;
13402                 struct stat st1, st2;
13403
13404                 initvar();
13405                 for (envp = environ; envp && *envp; envp++) {
13406                         p = endofname(*envp);
13407                         if (p != *envp && *p == '=') {
13408                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13409                         }
13410                 }
13411
13412                 setvareq((char*)defoptindvar, VTEXTFIXED);
13413
13414                 setvar0("PPID", utoa(getppid()));
13415 #if BASH_SHLVL_VAR
13416                 p = lookupvar("SHLVL");
13417                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13418 #endif
13419 #if BASH_HOSTNAME_VAR
13420                 if (!lookupvar("HOSTNAME")) {
13421                         struct utsname uts;
13422                         uname(&uts);
13423                         setvar0("HOSTNAME", uts.nodename);
13424                 }
13425 #endif
13426                 p = lookupvar("PWD");
13427                 if (p) {
13428                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13429                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13430                         ) {
13431                                 p = NULL;
13432                         }
13433                 }
13434                 setpwd(p, 0);
13435         }
13436 }
13437
13438
13439 //usage:#define ash_trivial_usage
13440 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13441 //usage:#define ash_full_usage "\n\n"
13442 //usage:        "Unix shell interpreter"
13443
13444 /*
13445  * Process the shell command line arguments.
13446  */
13447 static void
13448 procargs(char **argv)
13449 {
13450         int i;
13451         const char *xminusc;
13452         char **xargv;
13453
13454         xargv = argv;
13455         arg0 = xargv[0];
13456         /* if (xargv[0]) - mmm, this is always true! */
13457                 xargv++;
13458         for (i = 0; i < NOPTS; i++)
13459                 optlist[i] = 2;
13460         argptr = xargv;
13461         if (options(/*cmdline:*/ 1)) {
13462                 /* it already printed err message */
13463                 raise_exception(EXERROR);
13464         }
13465         xargv = argptr;
13466         xminusc = minusc;
13467         if (*xargv == NULL) {
13468                 if (xminusc)
13469                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13470                 sflag = 1;
13471         }
13472         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13473                 iflag = 1;
13474         if (mflag == 2)
13475                 mflag = iflag;
13476         for (i = 0; i < NOPTS; i++)
13477                 if (optlist[i] == 2)
13478                         optlist[i] = 0;
13479 #if DEBUG == 2
13480         debug = 1;
13481 #endif
13482         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13483         if (xminusc) {
13484                 minusc = *xargv++;
13485                 if (*xargv)
13486                         goto setarg0;
13487         } else if (!sflag) {
13488                 setinputfile(*xargv, 0);
13489  setarg0:
13490                 arg0 = *xargv++;
13491                 commandname = arg0;
13492         }
13493
13494         shellparam.p = xargv;
13495 #if ENABLE_ASH_GETOPTS
13496         shellparam.optind = 1;
13497         shellparam.optoff = -1;
13498 #endif
13499         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13500         while (*xargv) {
13501                 shellparam.nparam++;
13502                 xargv++;
13503         }
13504         optschanged();
13505 }
13506
13507 /*
13508  * Read /etc/profile, ~/.profile, $ENV.
13509  */
13510 static void
13511 read_profile(const char *name)
13512 {
13513         name = expandstr(name);
13514         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13515                 return;
13516         cmdloop(0);
13517         popfile();
13518 }
13519
13520 /*
13521  * This routine is called when an error or an interrupt occurs in an
13522  * interactive shell and control is returned to the main command loop.
13523  * (In dash, this function is auto-generated by build machinery).
13524  */
13525 static void
13526 reset(void)
13527 {
13528         /* from eval.c: */
13529         evalskip = 0;
13530         loopnest = 0;
13531
13532         /* from expand.c: */
13533         ifsfree();
13534
13535         /* from input.c: */
13536         g_parsefile->left_in_buffer = 0;
13537         g_parsefile->left_in_line = 0;      /* clear input buffer */
13538         popallfiles();
13539
13540         /* from redir.c: */
13541         while (redirlist)
13542                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13543 }
13544
13545 #if PROFILE
13546 static short profile_buf[16384];
13547 extern int etext();
13548 #endif
13549
13550 /*
13551  * Main routine.  We initialize things, parse the arguments, execute
13552  * profiles if we're a login shell, and then call cmdloop to execute
13553  * commands.  The setjmp call sets up the location to jump to when an
13554  * exception occurs.  When an exception occurs the variable "state"
13555  * is used to figure out how far we had gotten.
13556  */
13557 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13558 int ash_main(int argc UNUSED_PARAM, char **argv)
13559 {
13560         volatile smallint state;
13561         struct jmploc jmploc;
13562         struct stackmark smark;
13563
13564         /* Initialize global data */
13565         INIT_G_misc();
13566         INIT_G_memstack();
13567         INIT_G_var();
13568 #if ENABLE_ASH_ALIAS
13569         INIT_G_alias();
13570 #endif
13571         INIT_G_cmdtable();
13572
13573 #if PROFILE
13574         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13575 #endif
13576
13577 #if ENABLE_FEATURE_EDITING
13578         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13579 #endif
13580         state = 0;
13581         if (setjmp(jmploc.loc)) {
13582                 smallint e;
13583                 smallint s;
13584
13585                 reset();
13586
13587                 e = exception_type;
13588                 s = state;
13589                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13590                         exitshell();
13591                 }
13592                 if (e == EXINT) {
13593                         newline_and_flush(stderr);
13594                 }
13595
13596                 popstackmark(&smark);
13597                 FORCE_INT_ON; /* enable interrupts */
13598                 if (s == 1)
13599                         goto state1;
13600                 if (s == 2)
13601                         goto state2;
13602                 if (s == 3)
13603                         goto state3;
13604                 goto state4;
13605         }
13606         exception_handler = &jmploc;
13607         rootpid = getpid();
13608
13609         init();
13610         setstackmark(&smark);
13611         procargs(argv);
13612 #if DEBUG
13613         TRACE(("Shell args: "));
13614         trace_puts_args(argv);
13615 #endif
13616
13617         if (argv[0] && argv[0][0] == '-')
13618                 isloginsh = 1;
13619         if (isloginsh) {
13620                 const char *hp;
13621
13622                 state = 1;
13623                 read_profile("/etc/profile");
13624  state1:
13625                 state = 2;
13626                 hp = lookupvar("HOME");
13627                 if (hp)
13628                         read_profile("$HOME/.profile");
13629         }
13630  state2:
13631         state = 3;
13632         if (
13633 #ifndef linux
13634          getuid() == geteuid() && getgid() == getegid() &&
13635 #endif
13636          iflag
13637         ) {
13638                 const char *shinit = lookupvar("ENV");
13639                 if (shinit != NULL && *shinit != '\0')
13640                         read_profile(shinit);
13641         }
13642         popstackmark(&smark);
13643  state3:
13644         state = 4;
13645         if (minusc) {
13646                 /* evalstring pushes parsefile stack.
13647                  * Ensure we don't falsely claim that 0 (stdin)
13648                  * is one of stacked source fds.
13649                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13650                 // if (!sflag) g_parsefile->pf_fd = -1;
13651                 // ^^ not necessary since now we special-case fd 0
13652                 // in is_hidden_fd() to not be considered "hidden fd"
13653                 evalstring(minusc, 0);
13654         }
13655
13656         if (sflag || minusc == NULL) {
13657 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13658                 if (iflag) {
13659                         const char *hp = lookupvar("HISTFILE");
13660                         if (!hp) {
13661                                 hp = lookupvar("HOME");
13662                                 if (hp) {
13663                                         INT_OFF;
13664                                         hp = concat_path_file(hp, ".ash_history");
13665                                         setvar0("HISTFILE", hp);
13666                                         free((char*)hp);
13667                                         INT_ON;
13668                                         hp = lookupvar("HISTFILE");
13669                                 }
13670                         }
13671                         if (hp)
13672                                 line_input_state->hist_file = hp;
13673 # if ENABLE_FEATURE_SH_HISTFILESIZE
13674                         hp = lookupvar("HISTFILESIZE");
13675                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13676 # endif
13677                 }
13678 #endif
13679  state4: /* XXX ??? - why isn't this before the "if" statement */
13680                 cmdloop(1);
13681         }
13682 #if PROFILE
13683         monitor(0);
13684 #endif
13685 #ifdef GPROF
13686         {
13687                 extern void _mcleanup(void);
13688                 _mcleanup();
13689         }
13690 #endif
13691         TRACE(("End of main reached\n"));
13692         exitshell();
13693         /* NOTREACHED */
13694 }
13695
13696
13697 /*-
13698  * Copyright (c) 1989, 1991, 1993, 1994
13699  *      The Regents of the University of California.  All rights reserved.
13700  *
13701  * This code is derived from software contributed to Berkeley by
13702  * Kenneth Almquist.
13703  *
13704  * Redistribution and use in source and binary forms, with or without
13705  * modification, are permitted provided that the following conditions
13706  * are met:
13707  * 1. Redistributions of source code must retain the above copyright
13708  *    notice, this list of conditions and the following disclaimer.
13709  * 2. Redistributions in binary form must reproduce the above copyright
13710  *    notice, this list of conditions and the following disclaimer in the
13711  *    documentation and/or other materials provided with the distribution.
13712  * 3. Neither the name of the University nor the names of its contributors
13713  *    may be used to endorse or promote products derived from this software
13714  *    without specific prior written permission.
13715  *
13716  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13717  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13718  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13719  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13720  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13721  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13722  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13723  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13724  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13725  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13726  * SUCH DAMAGE.
13727  */