ash: allow "trap NUM [SIG]..." syntax
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #endif
218 #if ENABLE_ASH_RANDOM_SUPPORT
219 # include "random.h"
220 #else
221 # define CLEAR_RANDOM_T(rnd) ((void)0)
222 #endif
223
224 #include "NUM_APPLETS.h"
225 #if NUM_APPLETS == 1
226 /* STANDALONE does not make sense, and won't compile */
227 # undef CONFIG_FEATURE_SH_STANDALONE
228 # undef ENABLE_FEATURE_SH_STANDALONE
229 # undef IF_FEATURE_SH_STANDALONE
230 # undef IF_NOT_FEATURE_SH_STANDALONE
231 # define ENABLE_FEATURE_SH_STANDALONE 0
232 # define IF_FEATURE_SH_STANDALONE(...)
233 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
234 #endif
235
236 #ifndef PIPE_BUF
237 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
238 #endif
239
240 #if !BB_MMU
241 # error "Do not even bother, ash will not run on NOMMU machine"
242 #endif
243
244
245 /* ============ Hash table sizes. Configurable. */
246
247 #define VTABSIZE 39
248 #define ATABSIZE 39
249 #define CMDTABLESIZE 31         /* should be prime */
250
251
252 /* ============ Shell options */
253
254 static const char *const optletters_optnames[] = {
255         "e"   "errexit",
256         "f"   "noglob",
257         "I"   "ignoreeof",
258         "i"   "interactive",
259         "m"   "monitor",
260         "n"   "noexec",
261         "s"   "stdin",
262         "x"   "xtrace",
263         "v"   "verbose",
264         "C"   "noclobber",
265         "a"   "allexport",
266         "b"   "notify",
267         "u"   "nounset",
268         "\0"  "vi"
269 #if BASH_PIPEFAIL
270         ,"\0"  "pipefail"
271 #endif
272 #if DEBUG
273         ,"\0"  "nolog"
274         ,"\0"  "debug"
275 #endif
276 };
277
278 #define optletters(n)  optletters_optnames[n][0]
279 #define optnames(n)   (optletters_optnames[n] + 1)
280
281 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
282
283
284 /* ============ Misc data */
285
286 #define msg_illnum "Illegal number: %s"
287
288 /*
289  * We enclose jmp_buf in a structure so that we can declare pointers to
290  * jump locations.  The global variable handler contains the location to
291  * jump to when an exception occurs, and the global variable exception_type
292  * contains a code identifying the exception.  To implement nested
293  * exception handlers, the user should save the value of handler on entry
294  * to an inner scope, set handler to point to a jmploc structure for the
295  * inner scope, and restore handler on exit from the scope.
296  */
297 struct jmploc {
298         jmp_buf loc;
299 };
300
301 struct globals_misc {
302         uint8_t exitstatus;     /* exit status of last command */
303         uint8_t back_exitstatus;/* exit status of backquoted command */
304         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
305         int rootpid;            /* pid of main shell */
306         /* shell level: 0 for the main shell, 1 for its children, and so on */
307         int shlvl;
308 #define rootshell (!shlvl)
309         char *minusc;  /* argument to -c option */
310
311         char *curdir; // = nullstr;     /* current working directory */
312         char *physdir; // = nullstr;    /* physical working directory */
313
314         char *arg0; /* value of $0 */
315
316         struct jmploc *exception_handler;
317
318         volatile int suppress_int; /* counter */
319         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
320         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
321         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
322         smallint exception_type; /* kind of exception (0..5) */
323         /* exceptions */
324 #define EXINT 0         /* SIGINT received */
325 #define EXERROR 1       /* a generic error */
326 #define EXEXIT 4        /* exit the shell */
327
328         smallint isloginsh;
329         char nullstr[1];        /* zero length string */
330
331         char optlist[NOPTS];
332 #define eflag optlist[0]
333 #define fflag optlist[1]
334 #define Iflag optlist[2]
335 #define iflag optlist[3]
336 #define mflag optlist[4]
337 #define nflag optlist[5]
338 #define sflag optlist[6]
339 #define xflag optlist[7]
340 #define vflag optlist[8]
341 #define Cflag optlist[9]
342 #define aflag optlist[10]
343 #define bflag optlist[11]
344 #define uflag optlist[12]
345 #define viflag optlist[13]
346 #if BASH_PIPEFAIL
347 # define pipefail optlist[14]
348 #else
349 # define pipefail 0
350 #endif
351 #if DEBUG
352 # define nolog optlist[14 + BASH_PIPEFAIL]
353 # define debug optlist[15 + BASH_PIPEFAIL]
354 #endif
355
356         /* trap handler commands */
357         /*
358          * Sigmode records the current value of the signal handlers for the various
359          * modes.  A value of zero means that the current handler is not known.
360          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
361          */
362         char sigmode[NSIG - 1];
363 #define S_DFL      1            /* default signal handling (SIG_DFL) */
364 #define S_CATCH    2            /* signal is caught */
365 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
366 #define S_HARD_IGN 4            /* signal is ignored permanently */
367
368         /* indicates specified signal received */
369         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
370         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
371         char *trap[NSIG];
372         char **trap_ptr;        /* used only by "trap hack" */
373
374         /* Rarely referenced stuff */
375 #if ENABLE_ASH_RANDOM_SUPPORT
376         random_t random_gen;
377 #endif
378         pid_t backgndpid;        /* pid of last background process */
379 };
380 extern struct globals_misc *const ash_ptr_to_globals_misc;
381 #define G_misc (*ash_ptr_to_globals_misc)
382 #define exitstatus        (G_misc.exitstatus )
383 #define back_exitstatus   (G_misc.back_exitstatus )
384 #define job_warning       (G_misc.job_warning)
385 #define rootpid     (G_misc.rootpid    )
386 #define shlvl       (G_misc.shlvl      )
387 #define minusc      (G_misc.minusc     )
388 #define curdir      (G_misc.curdir     )
389 #define physdir     (G_misc.physdir    )
390 #define arg0        (G_misc.arg0       )
391 #define exception_handler (G_misc.exception_handler)
392 #define exception_type    (G_misc.exception_type   )
393 #define suppress_int      (G_misc.suppress_int     )
394 #define pending_int       (G_misc.pending_int      )
395 #define got_sigchld       (G_misc.got_sigchld      )
396 #define pending_sig       (G_misc.pending_sig      )
397 #define isloginsh   (G_misc.isloginsh  )
398 #define nullstr     (G_misc.nullstr    )
399 #define optlist     (G_misc.optlist    )
400 #define sigmode     (G_misc.sigmode    )
401 #define gotsig      (G_misc.gotsig     )
402 #define may_have_traps    (G_misc.may_have_traps   )
403 #define trap        (G_misc.trap       )
404 #define trap_ptr    (G_misc.trap_ptr   )
405 #define random_gen  (G_misc.random_gen )
406 #define backgndpid  (G_misc.backgndpid )
407 #define INIT_G_misc() do { \
408         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
409         barrier(); \
410         curdir = nullstr; \
411         physdir = nullstr; \
412         trap_ptr = trap; \
413 } while (0)
414
415
416 /* ============ DEBUG */
417 #if DEBUG
418 static void trace_printf(const char *fmt, ...);
419 static void trace_vprintf(const char *fmt, va_list va);
420 # define TRACE(param)    trace_printf param
421 # define TRACEV(param)   trace_vprintf param
422 # define close(fd) do { \
423         int dfd = (fd); \
424         if (close(dfd) < 0) \
425                 bb_error_msg("bug on %d: closing %d(0x%x)", \
426                         __LINE__, dfd, dfd); \
427 } while (0)
428 #else
429 # define TRACE(param)
430 # define TRACEV(param)
431 #endif
432
433
434 /* ============ Utility functions */
435 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
436 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
437
438 static int
439 isdigit_str9(const char *str)
440 {
441         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
442         while (--maxlen && isdigit(*str))
443                 str++;
444         return (*str == '\0');
445 }
446
447 static const char *
448 var_end(const char *var)
449 {
450         while (*var)
451                 if (*var++ == '=')
452                         break;
453         return var;
454 }
455
456
457 /* ============ Interrupts / exceptions */
458
459 static void exitshell(void) NORETURN;
460
461 /*
462  * These macros allow the user to suspend the handling of interrupt signals
463  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
464  * much more efficient and portable.  (But hacking the kernel is so much
465  * more fun than worrying about efficiency and portability. :-))
466  */
467 #if DEBUG_INTONOFF
468 # define INT_OFF do { \
469         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
470         suppress_int++; \
471         barrier(); \
472 } while (0)
473 #else
474 # define INT_OFF do { \
475         suppress_int++; \
476         barrier(); \
477 } while (0)
478 #endif
479
480 /*
481  * Called to raise an exception.  Since C doesn't include exceptions, we
482  * just do a longjmp to the exception handler.  The type of exception is
483  * stored in the global variable "exception_type".
484  */
485 static void raise_exception(int) NORETURN;
486 static void
487 raise_exception(int e)
488 {
489 #if DEBUG
490         if (exception_handler == NULL)
491                 abort();
492 #endif
493         INT_OFF;
494         exception_type = e;
495         longjmp(exception_handler->loc, 1);
496 }
497 #if DEBUG
498 #define raise_exception(e) do { \
499         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
500         raise_exception(e); \
501 } while (0)
502 #endif
503
504 /*
505  * Called when a SIGINT is received.  (If the user specifies
506  * that SIGINT is to be trapped or ignored using the trap builtin, then
507  * this routine is not called.)  Suppressint is nonzero when interrupts
508  * are held using the INT_OFF macro.  (The test for iflag is just
509  * defensive programming.)
510  */
511 static void raise_interrupt(void) NORETURN;
512 static void
513 raise_interrupt(void)
514 {
515         pending_int = 0;
516         /* Signal is not automatically unmasked after it is raised,
517          * do it ourself - unmask all signals */
518         sigprocmask_allsigs(SIG_UNBLOCK);
519         /* pending_sig = 0; - now done in signal_handler() */
520
521         if (!(rootshell && iflag)) {
522                 /* Kill ourself with SIGINT */
523                 signal(SIGINT, SIG_DFL);
524                 raise(SIGINT);
525         }
526         /* bash: ^C even on empty command line sets $? */
527         exitstatus = SIGINT + 128;
528         raise_exception(EXINT);
529         /* NOTREACHED */
530 }
531 #if DEBUG
532 #define raise_interrupt() do { \
533         TRACE(("raising interrupt on line %d\n", __LINE__)); \
534         raise_interrupt(); \
535 } while (0)
536 #endif
537
538 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
539 int_on(void)
540 {
541         barrier();
542         if (--suppress_int == 0 && pending_int) {
543                 raise_interrupt();
544         }
545 }
546 #if DEBUG_INTONOFF
547 # define INT_ON do { \
548         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
549         int_on(); \
550 } while (0)
551 #else
552 # define INT_ON int_on()
553 #endif
554 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
555 force_int_on(void)
556 {
557         barrier();
558         suppress_int = 0;
559         if (pending_int)
560                 raise_interrupt();
561 }
562 #define FORCE_INT_ON force_int_on()
563
564 #define SAVE_INT(v) ((v) = suppress_int)
565
566 #define RESTORE_INT(v) do { \
567         barrier(); \
568         suppress_int = (v); \
569         if (suppress_int == 0 && pending_int) \
570                 raise_interrupt(); \
571 } while (0)
572
573
574 /* ============ Stdout/stderr output */
575
576 static void
577 outstr(const char *p, FILE *file)
578 {
579         INT_OFF;
580         fputs(p, file);
581         INT_ON;
582 }
583
584 static void
585 flush_stdout_stderr(void)
586 {
587         INT_OFF;
588         fflush_all();
589         INT_ON;
590 }
591
592 /* Was called outcslow(c,FILE*), but c was always '\n' */
593 static void
594 newline_and_flush(FILE *dest)
595 {
596         INT_OFF;
597         putc('\n', dest);
598         fflush(dest);
599         INT_ON;
600 }
601
602 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
603 static int
604 out1fmt(const char *fmt, ...)
605 {
606         va_list ap;
607         int r;
608
609         INT_OFF;
610         va_start(ap, fmt);
611         r = vprintf(fmt, ap);
612         va_end(ap);
613         INT_ON;
614         return r;
615 }
616
617 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
618 static int
619 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
620 {
621         va_list ap;
622         int ret;
623
624         va_start(ap, fmt);
625         INT_OFF;
626         ret = vsnprintf(outbuf, length, fmt, ap);
627         va_end(ap);
628         INT_ON;
629         return ret;
630 }
631
632 static void
633 out1str(const char *p)
634 {
635         outstr(p, stdout);
636 }
637
638 static void
639 out2str(const char *p)
640 {
641         outstr(p, stderr);
642         flush_stdout_stderr();
643 }
644
645
646 /* ============ Parser structures */
647
648 /* control characters in argument strings */
649 #define CTL_FIRST CTLESC
650 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
651 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
652 #define CTLENDVAR    ((unsigned char)'\203')
653 #define CTLBACKQ     ((unsigned char)'\204')
654 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
655 #define CTLENDARI    ((unsigned char)'\207')
656 #define CTLQUOTEMARK ((unsigned char)'\210')
657 #define CTL_LAST CTLQUOTEMARK
658
659 /* variable substitution byte (follows CTLVAR) */
660 #define VSTYPE  0x0f            /* type of variable substitution */
661 #define VSNUL   0x10            /* colon--treat the empty string as unset */
662
663 /* values of VSTYPE field */
664 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
665 #define VSMINUS         0x2     /* ${var-text} */
666 #define VSPLUS          0x3     /* ${var+text} */
667 #define VSQUESTION      0x4     /* ${var?message} */
668 #define VSASSIGN        0x5     /* ${var=text} */
669 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
670 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
671 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
672 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
673 #define VSLENGTH        0xa     /* ${#var} */
674 #if BASH_SUBSTR
675 #define VSSUBSTR        0xc     /* ${var:position:length} */
676 #endif
677 #if BASH_PATTERN_SUBST
678 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
679 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
680 #endif
681
682 static const char dolatstr[] ALIGN1 = {
683         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
684 };
685 #define DOLATSTRLEN 6
686
687 #define NCMD      0
688 #define NPIPE     1
689 #define NREDIR    2
690 #define NBACKGND  3
691 #define NSUBSHELL 4
692 #define NAND      5
693 #define NOR       6
694 #define NSEMI     7
695 #define NIF       8
696 #define NWHILE    9
697 #define NUNTIL   10
698 #define NFOR     11
699 #define NCASE    12
700 #define NCLIST   13
701 #define NDEFUN   14
702 #define NARG     15
703 #define NTO      16
704 #if BASH_REDIR_OUTPUT
705 #define NTO2     17
706 #endif
707 #define NCLOBBER 18
708 #define NFROM    19
709 #define NFROMTO  20
710 #define NAPPEND  21
711 #define NTOFD    22
712 #define NFROMFD  23
713 #define NHERE    24
714 #define NXHERE   25
715 #define NNOT     26
716 #define N_NUMBER 27
717
718 union node;
719
720 struct ncmd {
721         smallint type; /* Nxxxx */
722         union node *assign;
723         union node *args;
724         union node *redirect;
725 };
726
727 struct npipe {
728         smallint type;
729         smallint pipe_backgnd;
730         struct nodelist *cmdlist;
731 };
732
733 struct nredir {
734         smallint type;
735         union node *n;
736         union node *redirect;
737 };
738
739 struct nbinary {
740         smallint type;
741         union node *ch1;
742         union node *ch2;
743 };
744
745 struct nif {
746         smallint type;
747         union node *test;
748         union node *ifpart;
749         union node *elsepart;
750 };
751
752 struct nfor {
753         smallint type;
754         union node *args;
755         union node *body;
756         char *var;
757 };
758
759 struct ncase {
760         smallint type;
761         union node *expr;
762         union node *cases;
763 };
764
765 struct nclist {
766         smallint type;
767         union node *next;
768         union node *pattern;
769         union node *body;
770 };
771
772 struct narg {
773         smallint type;
774         union node *next;
775         char *text;
776         struct nodelist *backquote;
777 };
778
779 /* nfile and ndup layout must match!
780  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
781  * that it is actually NTO2 (>&file), and change its type.
782  */
783 struct nfile {
784         smallint type;
785         union node *next;
786         int fd;
787         int _unused_dupfd;
788         union node *fname;
789         char *expfname;
790 };
791
792 struct ndup {
793         smallint type;
794         union node *next;
795         int fd;
796         int dupfd;
797         union node *vname;
798         char *_unused_expfname;
799 };
800
801 struct nhere {
802         smallint type;
803         union node *next;
804         int fd;
805         union node *doc;
806 };
807
808 struct nnot {
809         smallint type;
810         union node *com;
811 };
812
813 union node {
814         smallint type;
815         struct ncmd ncmd;
816         struct npipe npipe;
817         struct nredir nredir;
818         struct nbinary nbinary;
819         struct nif nif;
820         struct nfor nfor;
821         struct ncase ncase;
822         struct nclist nclist;
823         struct narg narg;
824         struct nfile nfile;
825         struct ndup ndup;
826         struct nhere nhere;
827         struct nnot nnot;
828 };
829
830 /*
831  * NODE_EOF is returned by parsecmd when it encounters an end of file.
832  * It must be distinct from NULL.
833  */
834 #define NODE_EOF ((union node *) -1L)
835
836 struct nodelist {
837         struct nodelist *next;
838         union node *n;
839 };
840
841 struct funcnode {
842         int count;
843         union node n;
844 };
845
846 /*
847  * Free a parse tree.
848  */
849 static void
850 freefunc(struct funcnode *f)
851 {
852         if (f && --f->count < 0)
853                 free(f);
854 }
855
856
857 /* ============ Debugging output */
858
859 #if DEBUG
860
861 static FILE *tracefile;
862
863 static void
864 trace_printf(const char *fmt, ...)
865 {
866         va_list va;
867
868         if (debug != 1)
869                 return;
870         if (DEBUG_TIME)
871                 fprintf(tracefile, "%u ", (int) time(NULL));
872         if (DEBUG_PID)
873                 fprintf(tracefile, "[%u] ", (int) getpid());
874         if (DEBUG_SIG)
875                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
876         va_start(va, fmt);
877         vfprintf(tracefile, fmt, va);
878         va_end(va);
879 }
880
881 static void
882 trace_vprintf(const char *fmt, va_list va)
883 {
884         if (debug != 1)
885                 return;
886         vfprintf(tracefile, fmt, va);
887         fprintf(tracefile, "\n");
888 }
889
890 static void
891 trace_puts(const char *s)
892 {
893         if (debug != 1)
894                 return;
895         fputs(s, tracefile);
896 }
897
898 static void
899 trace_puts_quoted(char *s)
900 {
901         char *p;
902         char c;
903
904         if (debug != 1)
905                 return;
906         putc('"', tracefile);
907         for (p = s; *p; p++) {
908                 switch ((unsigned char)*p) {
909                 case '\n': c = 'n'; goto backslash;
910                 case '\t': c = 't'; goto backslash;
911                 case '\r': c = 'r'; goto backslash;
912                 case '\"': c = '\"'; goto backslash;
913                 case '\\': c = '\\'; goto backslash;
914                 case CTLESC: c = 'e'; goto backslash;
915                 case CTLVAR: c = 'v'; goto backslash;
916                 case CTLBACKQ: c = 'q'; goto backslash;
917  backslash:
918                         putc('\\', tracefile);
919                         putc(c, tracefile);
920                         break;
921                 default:
922                         if (*p >= ' ' && *p <= '~')
923                                 putc(*p, tracefile);
924                         else {
925                                 putc('\\', tracefile);
926                                 putc((*p >> 6) & 03, tracefile);
927                                 putc((*p >> 3) & 07, tracefile);
928                                 putc(*p & 07, tracefile);
929                         }
930                         break;
931                 }
932         }
933         putc('"', tracefile);
934 }
935
936 static void
937 trace_puts_args(char **ap)
938 {
939         if (debug != 1)
940                 return;
941         if (!*ap)
942                 return;
943         while (1) {
944                 trace_puts_quoted(*ap);
945                 if (!*++ap) {
946                         putc('\n', tracefile);
947                         break;
948                 }
949                 putc(' ', tracefile);
950         }
951 }
952
953 static void
954 opentrace(void)
955 {
956         char s[100];
957 #ifdef O_APPEND
958         int flags;
959 #endif
960
961         if (debug != 1) {
962                 if (tracefile)
963                         fflush(tracefile);
964                 /* leave open because libedit might be using it */
965                 return;
966         }
967         strcpy(s, "./trace");
968         if (tracefile) {
969                 if (!freopen(s, "a", tracefile)) {
970                         fprintf(stderr, "Can't re-open %s\n", s);
971                         debug = 0;
972                         return;
973                 }
974         } else {
975                 tracefile = fopen(s, "a");
976                 if (tracefile == NULL) {
977                         fprintf(stderr, "Can't open %s\n", s);
978                         debug = 0;
979                         return;
980                 }
981         }
982 #ifdef O_APPEND
983         flags = fcntl(fileno(tracefile), F_GETFL);
984         if (flags >= 0)
985                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
986 #endif
987         setlinebuf(tracefile);
988         fputs("\nTracing started.\n", tracefile);
989 }
990
991 static void
992 indent(int amount, char *pfx, FILE *fp)
993 {
994         int i;
995
996         for (i = 0; i < amount; i++) {
997                 if (pfx && i == amount - 1)
998                         fputs(pfx, fp);
999                 putc('\t', fp);
1000         }
1001 }
1002
1003 /* little circular references here... */
1004 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1005
1006 static void
1007 sharg(union node *arg, FILE *fp)
1008 {
1009         char *p;
1010         struct nodelist *bqlist;
1011         unsigned char subtype;
1012
1013         if (arg->type != NARG) {
1014                 out1fmt("<node type %d>\n", arg->type);
1015                 abort();
1016         }
1017         bqlist = arg->narg.backquote;
1018         for (p = arg->narg.text; *p; p++) {
1019                 switch ((unsigned char)*p) {
1020                 case CTLESC:
1021                         p++;
1022                         putc(*p, fp);
1023                         break;
1024                 case CTLVAR:
1025                         putc('$', fp);
1026                         putc('{', fp);
1027                         subtype = *++p;
1028                         if (subtype == VSLENGTH)
1029                                 putc('#', fp);
1030
1031                         while (*p != '=') {
1032                                 putc(*p, fp);
1033                                 p++;
1034                         }
1035
1036                         if (subtype & VSNUL)
1037                                 putc(':', fp);
1038
1039                         switch (subtype & VSTYPE) {
1040                         case VSNORMAL:
1041                                 putc('}', fp);
1042                                 break;
1043                         case VSMINUS:
1044                                 putc('-', fp);
1045                                 break;
1046                         case VSPLUS:
1047                                 putc('+', fp);
1048                                 break;
1049                         case VSQUESTION:
1050                                 putc('?', fp);
1051                                 break;
1052                         case VSASSIGN:
1053                                 putc('=', fp);
1054                                 break;
1055                         case VSTRIMLEFT:
1056                                 putc('#', fp);
1057                                 break;
1058                         case VSTRIMLEFTMAX:
1059                                 putc('#', fp);
1060                                 putc('#', fp);
1061                                 break;
1062                         case VSTRIMRIGHT:
1063                                 putc('%', fp);
1064                                 break;
1065                         case VSTRIMRIGHTMAX:
1066                                 putc('%', fp);
1067                                 putc('%', fp);
1068                                 break;
1069                         case VSLENGTH:
1070                                 break;
1071                         default:
1072                                 out1fmt("<subtype %d>", subtype);
1073                         }
1074                         break;
1075                 case CTLENDVAR:
1076                         putc('}', fp);
1077                         break;
1078                 case CTLBACKQ:
1079                         putc('$', fp);
1080                         putc('(', fp);
1081                         shtree(bqlist->n, -1, NULL, fp);
1082                         putc(')', fp);
1083                         break;
1084                 default:
1085                         putc(*p, fp);
1086                         break;
1087                 }
1088         }
1089 }
1090
1091 static void
1092 shcmd(union node *cmd, FILE *fp)
1093 {
1094         union node *np;
1095         int first;
1096         const char *s;
1097         int dftfd;
1098
1099         first = 1;
1100         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1101                 if (!first)
1102                         putc(' ', fp);
1103                 sharg(np, fp);
1104                 first = 0;
1105         }
1106         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1107                 if (!first)
1108                         putc(' ', fp);
1109                 dftfd = 0;
1110                 switch (np->nfile.type) {
1111                 case NTO:      s = ">>"+1; dftfd = 1; break;
1112                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1113                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1114 #if BASH_REDIR_OUTPUT
1115                 case NTO2:
1116 #endif
1117                 case NTOFD:    s = ">&"; dftfd = 1; break;
1118                 case NFROM:    s = "<"; break;
1119                 case NFROMFD:  s = "<&"; break;
1120                 case NFROMTO:  s = "<>"; break;
1121                 default:       s = "*error*"; break;
1122                 }
1123                 if (np->nfile.fd != dftfd)
1124                         fprintf(fp, "%d", np->nfile.fd);
1125                 fputs(s, fp);
1126                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1127                         fprintf(fp, "%d", np->ndup.dupfd);
1128                 } else {
1129                         sharg(np->nfile.fname, fp);
1130                 }
1131                 first = 0;
1132         }
1133 }
1134
1135 static void
1136 shtree(union node *n, int ind, char *pfx, FILE *fp)
1137 {
1138         struct nodelist *lp;
1139         const char *s;
1140
1141         if (n == NULL)
1142                 return;
1143
1144         indent(ind, pfx, fp);
1145
1146         if (n == NODE_EOF) {
1147                 fputs("<EOF>", fp);
1148                 return;
1149         }
1150
1151         switch (n->type) {
1152         case NSEMI:
1153                 s = "; ";
1154                 goto binop;
1155         case NAND:
1156                 s = " && ";
1157                 goto binop;
1158         case NOR:
1159                 s = " || ";
1160  binop:
1161                 shtree(n->nbinary.ch1, ind, NULL, fp);
1162                 /* if (ind < 0) */
1163                         fputs(s, fp);
1164                 shtree(n->nbinary.ch2, ind, NULL, fp);
1165                 break;
1166         case NCMD:
1167                 shcmd(n, fp);
1168                 if (ind >= 0)
1169                         putc('\n', fp);
1170                 break;
1171         case NPIPE:
1172                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1173                         shtree(lp->n, 0, NULL, fp);
1174                         if (lp->next)
1175                                 fputs(" | ", fp);
1176                 }
1177                 if (n->npipe.pipe_backgnd)
1178                         fputs(" &", fp);
1179                 if (ind >= 0)
1180                         putc('\n', fp);
1181                 break;
1182         default:
1183                 fprintf(fp, "<node type %d>", n->type);
1184                 if (ind >= 0)
1185                         putc('\n', fp);
1186                 break;
1187         }
1188 }
1189
1190 static void
1191 showtree(union node *n)
1192 {
1193         trace_puts("showtree called\n");
1194         shtree(n, 1, NULL, stderr);
1195 }
1196
1197 #endif /* DEBUG */
1198
1199
1200 /* ============ Parser data */
1201
1202 /*
1203  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1204  */
1205 struct strlist {
1206         struct strlist *next;
1207         char *text;
1208 };
1209
1210 struct alias;
1211
1212 struct strpush {
1213         struct strpush *prev;   /* preceding string on stack */
1214         char *prev_string;
1215         int prev_left_in_line;
1216 #if ENABLE_ASH_ALIAS
1217         struct alias *ap;       /* if push was associated with an alias */
1218 #endif
1219         char *string;           /* remember the string since it may change */
1220
1221         /* Remember last two characters for pungetc. */
1222         int lastc[2];
1223
1224         /* Number of outstanding calls to pungetc. */
1225         int unget;
1226 };
1227
1228 struct parsefile {
1229         struct parsefile *prev; /* preceding file on stack */
1230         int linno;              /* current line */
1231         int pf_fd;              /* file descriptor (or -1 if string) */
1232         int left_in_line;       /* number of chars left in this line */
1233         int left_in_buffer;     /* number of chars left in this buffer past the line */
1234         char *next_to_pgetc;    /* next char in buffer */
1235         char *buf;              /* input buffer */
1236         struct strpush *strpush; /* for pushing strings at this level */
1237         struct strpush basestrpush; /* so pushing one is fast */
1238
1239         /* Remember last two characters for pungetc. */
1240         int lastc[2];
1241
1242         /* Number of outstanding calls to pungetc. */
1243         int unget;
1244 };
1245
1246 static struct parsefile basepf;        /* top level input file */
1247 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1248 static int startlinno;                 /* line # where last token started */
1249 static char *commandname;              /* currently executing command */
1250 static struct strlist *cmdenviron;     /* environment for builtin command */
1251
1252
1253 /* ============ Message printing */
1254
1255 static void
1256 ash_vmsg(const char *msg, va_list ap)
1257 {
1258         fprintf(stderr, "%s: ", arg0);
1259         if (commandname) {
1260                 if (strcmp(arg0, commandname))
1261                         fprintf(stderr, "%s: ", commandname);
1262                 if (!iflag || g_parsefile->pf_fd > 0)
1263                         fprintf(stderr, "line %d: ", startlinno);
1264         }
1265         vfprintf(stderr, msg, ap);
1266         newline_and_flush(stderr);
1267 }
1268
1269 /*
1270  * Exverror is called to raise the error exception.  If the second argument
1271  * is not NULL then error prints an error message using printf style
1272  * formatting.  It then raises the error exception.
1273  */
1274 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1275 static void
1276 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1277 {
1278 #if DEBUG
1279         if (msg) {
1280                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1281                 TRACEV((msg, ap));
1282         } else
1283                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1284         if (msg)
1285 #endif
1286                 ash_vmsg(msg, ap);
1287
1288         flush_stdout_stderr();
1289         raise_exception(cond);
1290         /* NOTREACHED */
1291 }
1292
1293 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1294 static void
1295 ash_msg_and_raise_error(const char *msg, ...)
1296 {
1297         va_list ap;
1298
1299         exitstatus = 2;
1300
1301         va_start(ap, msg);
1302         ash_vmsg_and_raise(EXERROR, msg, ap);
1303         /* NOTREACHED */
1304         va_end(ap);
1305 }
1306
1307 static void raise_error_syntax(const char *) NORETURN;
1308 static void
1309 raise_error_syntax(const char *msg)
1310 {
1311         ash_msg_and_raise_error("syntax error: %s", msg);
1312         /* NOTREACHED */
1313 }
1314
1315 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1316 static void
1317 ash_msg_and_raise(int cond, const char *msg, ...)
1318 {
1319         va_list ap;
1320
1321         va_start(ap, msg);
1322         ash_vmsg_and_raise(cond, msg, ap);
1323         /* NOTREACHED */
1324         va_end(ap);
1325 }
1326
1327 /*
1328  * error/warning routines for external builtins
1329  */
1330 static void
1331 ash_msg(const char *fmt, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, fmt);
1336         ash_vmsg(fmt, ap);
1337         va_end(ap);
1338 }
1339
1340 /*
1341  * Return a string describing an error.  The returned string may be a
1342  * pointer to a static buffer that will be overwritten on the next call.
1343  * Action describes the operation that got the error.
1344  */
1345 static const char *
1346 errmsg(int e, const char *em)
1347 {
1348         if (e == ENOENT || e == ENOTDIR) {
1349                 return em;
1350         }
1351         return strerror(e);
1352 }
1353
1354
1355 /* ============ Memory allocation */
1356
1357 #if 0
1358 /* I consider these wrappers nearly useless:
1359  * ok, they return you to nearest exception handler, but
1360  * how much memory do you leak in the process, making
1361  * memory starvation worse?
1362  */
1363 static void *
1364 ckrealloc(void * p, size_t nbytes)
1365 {
1366         p = realloc(p, nbytes);
1367         if (!p)
1368                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1369         return p;
1370 }
1371
1372 static void *
1373 ckmalloc(size_t nbytes)
1374 {
1375         return ckrealloc(NULL, nbytes);
1376 }
1377
1378 static void *
1379 ckzalloc(size_t nbytes)
1380 {
1381         return memset(ckmalloc(nbytes), 0, nbytes);
1382 }
1383
1384 static char *
1385 ckstrdup(const char *s)
1386 {
1387         char *p = strdup(s);
1388         if (!p)
1389                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1390         return p;
1391 }
1392 #else
1393 /* Using bbox equivalents. They exit if out of memory */
1394 # define ckrealloc xrealloc
1395 # define ckmalloc  xmalloc
1396 # define ckzalloc  xzalloc
1397 # define ckstrdup  xstrdup
1398 #endif
1399
1400 /*
1401  * It appears that grabstackstr() will barf with such alignments
1402  * because stalloc() will return a string allocated in a new stackblock.
1403  */
1404 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1405 enum {
1406         /* Most machines require the value returned from malloc to be aligned
1407          * in some way.  The following macro will get this right
1408          * on many machines.  */
1409         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1410         /* Minimum size of a block */
1411         MINSIZE = SHELL_ALIGN(504),
1412 };
1413
1414 struct stack_block {
1415         struct stack_block *prev;
1416         char space[MINSIZE];
1417 };
1418
1419 struct stackmark {
1420         struct stack_block *stackp;
1421         char *stacknxt;
1422         size_t stacknleft;
1423 };
1424
1425
1426 struct globals_memstack {
1427         struct stack_block *g_stackp; // = &stackbase;
1428         char *g_stacknxt; // = stackbase.space;
1429         char *sstrend; // = stackbase.space + MINSIZE;
1430         size_t g_stacknleft; // = MINSIZE;
1431         struct stack_block stackbase;
1432 };
1433 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1434 #define G_memstack (*ash_ptr_to_globals_memstack)
1435 #define g_stackp     (G_memstack.g_stackp    )
1436 #define g_stacknxt   (G_memstack.g_stacknxt  )
1437 #define sstrend      (G_memstack.sstrend     )
1438 #define g_stacknleft (G_memstack.g_stacknleft)
1439 #define stackbase    (G_memstack.stackbase   )
1440 #define INIT_G_memstack() do { \
1441         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1442         barrier(); \
1443         g_stackp = &stackbase; \
1444         g_stacknxt = stackbase.space; \
1445         g_stacknleft = MINSIZE; \
1446         sstrend = stackbase.space + MINSIZE; \
1447 } while (0)
1448
1449
1450 #define stackblock()     ((void *)g_stacknxt)
1451 #define stackblocksize() g_stacknleft
1452
1453 /*
1454  * Parse trees for commands are allocated in lifo order, so we use a stack
1455  * to make this more efficient, and also to avoid all sorts of exception
1456  * handling code to handle interrupts in the middle of a parse.
1457  *
1458  * The size 504 was chosen because the Ultrix malloc handles that size
1459  * well.
1460  */
1461 static void *
1462 stalloc(size_t nbytes)
1463 {
1464         char *p;
1465         size_t aligned;
1466
1467         aligned = SHELL_ALIGN(nbytes);
1468         if (aligned > g_stacknleft) {
1469                 size_t len;
1470                 size_t blocksize;
1471                 struct stack_block *sp;
1472
1473                 blocksize = aligned;
1474                 if (blocksize < MINSIZE)
1475                         blocksize = MINSIZE;
1476                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1477                 if (len < blocksize)
1478                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1479                 INT_OFF;
1480                 sp = ckmalloc(len);
1481                 sp->prev = g_stackp;
1482                 g_stacknxt = sp->space;
1483                 g_stacknleft = blocksize;
1484                 sstrend = g_stacknxt + blocksize;
1485                 g_stackp = sp;
1486                 INT_ON;
1487         }
1488         p = g_stacknxt;
1489         g_stacknxt += aligned;
1490         g_stacknleft -= aligned;
1491         return p;
1492 }
1493
1494 static void *
1495 stzalloc(size_t nbytes)
1496 {
1497         return memset(stalloc(nbytes), 0, nbytes);
1498 }
1499
1500 static void
1501 stunalloc(void *p)
1502 {
1503 #if DEBUG
1504         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1505                 write(STDERR_FILENO, "stunalloc\n", 10);
1506                 abort();
1507         }
1508 #endif
1509         g_stacknleft += g_stacknxt - (char *)p;
1510         g_stacknxt = p;
1511 }
1512
1513 /*
1514  * Like strdup but works with the ash stack.
1515  */
1516 static char *
1517 sstrdup(const char *p)
1518 {
1519         size_t len = strlen(p) + 1;
1520         return memcpy(stalloc(len), p, len);
1521 }
1522
1523 static inline void
1524 grabstackblock(size_t len)
1525 {
1526         stalloc(len);
1527 }
1528
1529 static void
1530 pushstackmark(struct stackmark *mark, size_t len)
1531 {
1532         mark->stackp = g_stackp;
1533         mark->stacknxt = g_stacknxt;
1534         mark->stacknleft = g_stacknleft;
1535         grabstackblock(len);
1536 }
1537
1538 static void
1539 setstackmark(struct stackmark *mark)
1540 {
1541         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1542 }
1543
1544 static void
1545 popstackmark(struct stackmark *mark)
1546 {
1547         struct stack_block *sp;
1548
1549         if (!mark->stackp)
1550                 return;
1551
1552         INT_OFF;
1553         while (g_stackp != mark->stackp) {
1554                 sp = g_stackp;
1555                 g_stackp = sp->prev;
1556                 free(sp);
1557         }
1558         g_stacknxt = mark->stacknxt;
1559         g_stacknleft = mark->stacknleft;
1560         sstrend = mark->stacknxt + mark->stacknleft;
1561         INT_ON;
1562 }
1563
1564 /*
1565  * When the parser reads in a string, it wants to stick the string on the
1566  * stack and only adjust the stack pointer when it knows how big the
1567  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1568  * of space on top of the stack and stackblocklen returns the length of
1569  * this block.  Growstackblock will grow this space by at least one byte,
1570  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1571  * part of the block that has been used.
1572  */
1573 static void
1574 growstackblock(void)
1575 {
1576         size_t newlen;
1577
1578         newlen = g_stacknleft * 2;
1579         if (newlen < g_stacknleft)
1580                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1581         if (newlen < 128)
1582                 newlen += 128;
1583
1584         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1585                 struct stack_block *sp;
1586                 struct stack_block *prevstackp;
1587                 size_t grosslen;
1588
1589                 INT_OFF;
1590                 sp = g_stackp;
1591                 prevstackp = sp->prev;
1592                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1593                 sp = ckrealloc(sp, grosslen);
1594                 sp->prev = prevstackp;
1595                 g_stackp = sp;
1596                 g_stacknxt = sp->space;
1597                 g_stacknleft = newlen;
1598                 sstrend = sp->space + newlen;
1599                 INT_ON;
1600         } else {
1601                 char *oldspace = g_stacknxt;
1602                 size_t oldlen = g_stacknleft;
1603                 char *p = stalloc(newlen);
1604
1605                 /* free the space we just allocated */
1606                 g_stacknxt = memcpy(p, oldspace, oldlen);
1607                 g_stacknleft += newlen;
1608         }
1609 }
1610
1611 /*
1612  * The following routines are somewhat easier to use than the above.
1613  * The user declares a variable of type STACKSTR, which may be declared
1614  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1615  * the user uses the macro STPUTC to add characters to the string.  In
1616  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1617  * grown as necessary.  When the user is done, she can just leave the
1618  * string there and refer to it using stackblock().  Or she can allocate
1619  * the space for it using grabstackstr().  If it is necessary to allow
1620  * someone else to use the stack temporarily and then continue to grow
1621  * the string, the user should use grabstack to allocate the space, and
1622  * then call ungrabstr(p) to return to the previous mode of operation.
1623  *
1624  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1625  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1626  * is space for at least one character.
1627  */
1628 static void *
1629 growstackstr(void)
1630 {
1631         size_t len = stackblocksize();
1632         growstackblock();
1633         return (char *)stackblock() + len;
1634 }
1635
1636 /*
1637  * Called from CHECKSTRSPACE.
1638  */
1639 static char *
1640 makestrspace(size_t newlen, char *p)
1641 {
1642         size_t len = p - g_stacknxt;
1643         size_t size;
1644
1645         for (;;) {
1646                 size_t nleft;
1647
1648                 size = stackblocksize();
1649                 nleft = size - len;
1650                 if (nleft >= newlen)
1651                         break;
1652                 growstackblock();
1653         }
1654         return (char *)stackblock() + len;
1655 }
1656
1657 static char *
1658 stack_nputstr(const char *s, size_t n, char *p)
1659 {
1660         p = makestrspace(n, p);
1661         p = (char *)mempcpy(p, s, n);
1662         return p;
1663 }
1664
1665 static char *
1666 stack_putstr(const char *s, char *p)
1667 {
1668         return stack_nputstr(s, strlen(s), p);
1669 }
1670
1671 static char *
1672 _STPUTC(int c, char *p)
1673 {
1674         if (p == sstrend)
1675                 p = growstackstr();
1676         *p++ = c;
1677         return p;
1678 }
1679
1680 #define STARTSTACKSTR(p)        ((p) = stackblock())
1681 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1682 #define CHECKSTRSPACE(n, p) do { \
1683         char *q = (p); \
1684         size_t l = (n); \
1685         size_t m = sstrend - q; \
1686         if (l > m) \
1687                 (p) = makestrspace(l, q); \
1688 } while (0)
1689 #define USTPUTC(c, p)           (*(p)++ = (c))
1690 #define STACKSTRNUL(p) do { \
1691         if ((p) == sstrend) \
1692                 (p) = growstackstr(); \
1693         *(p) = '\0'; \
1694 } while (0)
1695 #define STUNPUTC(p)             (--(p))
1696 #define STTOPC(p)               ((p)[-1])
1697 #define STADJUST(amount, p)     ((p) += (amount))
1698
1699 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1700 #define ungrabstackstr(s, p)    stunalloc(s)
1701 #define stackstrend()           ((void *)sstrend)
1702
1703
1704 /* ============ String helpers */
1705
1706 /*
1707  * prefix -- see if pfx is a prefix of string.
1708  */
1709 static char *
1710 prefix(const char *string, const char *pfx)
1711 {
1712         while (*pfx) {
1713                 if (*pfx++ != *string++)
1714                         return NULL;
1715         }
1716         return (char *) string;
1717 }
1718
1719 /*
1720  * Check for a valid number.  This should be elsewhere.
1721  */
1722 static int
1723 is_number(const char *p)
1724 {
1725         do {
1726                 if (!isdigit(*p))
1727                         return 0;
1728         } while (*++p != '\0');
1729         return 1;
1730 }
1731
1732 /*
1733  * Convert a string of digits to an integer, printing an error message on
1734  * failure.
1735  */
1736 static int
1737 number(const char *s)
1738 {
1739         if (!is_number(s))
1740                 ash_msg_and_raise_error(msg_illnum, s);
1741         return atoi(s);
1742 }
1743
1744 /*
1745  * Produce a single quoted string suitable as input to the shell.
1746  * The return string is allocated on the stack.
1747  */
1748 static char *
1749 single_quote(const char *s)
1750 {
1751         char *p;
1752
1753         STARTSTACKSTR(p);
1754
1755         do {
1756                 char *q;
1757                 size_t len;
1758
1759                 len = strchrnul(s, '\'') - s;
1760
1761                 q = p = makestrspace(len + 3, p);
1762
1763                 *q++ = '\'';
1764                 q = (char *)mempcpy(q, s, len);
1765                 *q++ = '\'';
1766                 s += len;
1767
1768                 STADJUST(q - p, p);
1769
1770                 if (*s != '\'')
1771                         break;
1772                 len = 0;
1773                 do len++; while (*++s == '\'');
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '"';
1778                 q = (char *)mempcpy(q, s - len, len);
1779                 *q++ = '"';
1780
1781                 STADJUST(q - p, p);
1782         } while (*s);
1783
1784         USTPUTC('\0', p);
1785
1786         return stackblock();
1787 }
1788
1789 /*
1790  * Produce a possibly single quoted string suitable as input to the shell.
1791  * If quoting was done, the return string is allocated on the stack,
1792  * otherwise a pointer to the original string is returned.
1793  */
1794 static const char *
1795 maybe_single_quote(const char *s)
1796 {
1797         const char *p = s;
1798
1799         while (*p) {
1800                 /* Assuming ACSII */
1801                 /* quote ctrl_chars space !"#$%&'()* */
1802                 if (*p < '+')
1803                         goto need_quoting;
1804                 /* quote ;<=>? */
1805                 if (*p >= ';' && *p <= '?')
1806                         goto need_quoting;
1807                 /* quote `[\ */
1808                 if (*p == '`')
1809                         goto need_quoting;
1810                 if (*p == '[')
1811                         goto need_quoting;
1812                 if (*p == '\\')
1813                         goto need_quoting;
1814                 /* quote {|}~ DEL and high bytes */
1815                 if (*p > 'z')
1816                         goto need_quoting;
1817                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1818                 /* TODO: maybe avoid quoting % */
1819                 p++;
1820         }
1821         return s;
1822
1823  need_quoting:
1824         return single_quote(s);
1825 }
1826
1827
1828 /* ============ nextopt */
1829
1830 static char **argptr;                  /* argument list for builtin commands */
1831 static char *optionarg;                /* set by nextopt (like getopt) */
1832 static char *optptr;                   /* used by nextopt */
1833
1834 /*
1835  * XXX - should get rid of. Have all builtins use getopt(3).
1836  * The library getopt must have the BSD extension static variable
1837  * "optreset", otherwise it can't be used within the shell safely.
1838  *
1839  * Standard option processing (a la getopt) for builtin routines.
1840  * The only argument that is passed to nextopt is the option string;
1841  * the other arguments are unnecessary. It returns the character,
1842  * or '\0' on end of input.
1843  */
1844 static int
1845 nextopt(const char *optstring)
1846 {
1847         char *p;
1848         const char *q;
1849         char c;
1850
1851         p = optptr;
1852         if (p == NULL || *p == '\0') {
1853                 /* We ate entire "-param", take next one */
1854                 p = *argptr;
1855                 if (p == NULL)
1856                         return '\0';
1857                 if (*p != '-')
1858                         return '\0';
1859                 if (*++p == '\0') /* just "-" ? */
1860                         return '\0';
1861                 argptr++;
1862                 if (LONE_DASH(p)) /* "--" ? */
1863                         return '\0';
1864                 /* p => next "-param" */
1865         }
1866         /* p => some option char in the middle of a "-param" */
1867         c = *p++;
1868         for (q = optstring; *q != c;) {
1869                 if (*q == '\0')
1870                         ash_msg_and_raise_error("illegal option -%c", c);
1871                 if (*++q == ':')
1872                         q++;
1873         }
1874         if (*++q == ':') {
1875                 if (*p == '\0') {
1876                         p = *argptr++;
1877                         if (p == NULL)
1878                                 ash_msg_and_raise_error("no arg for -%c option", c);
1879                 }
1880                 optionarg = p;
1881                 p = NULL;
1882         }
1883         optptr = p;
1884         return c;
1885 }
1886
1887
1888 /* ============ Shell variables */
1889
1890 /*
1891  * The parsefile structure pointed to by the global variable parsefile
1892  * contains information about the current file being read.
1893  */
1894 struct shparam {
1895         int nparam;             /* # of positional parameters (without $0) */
1896 #if ENABLE_ASH_GETOPTS
1897         int optind;             /* next parameter to be processed by getopts */
1898         int optoff;             /* used by getopts */
1899 #endif
1900         unsigned char malloced; /* if parameter list dynamically allocated */
1901         char **p;               /* parameter list */
1902 };
1903
1904 /*
1905  * Free the list of positional parameters.
1906  */
1907 static void
1908 freeparam(volatile struct shparam *param)
1909 {
1910         if (param->malloced) {
1911                 char **ap, **ap1;
1912                 ap = ap1 = param->p;
1913                 while (*ap)
1914                         free(*ap++);
1915                 free(ap1);
1916         }
1917 }
1918
1919 #if ENABLE_ASH_GETOPTS
1920 static void FAST_FUNC getoptsreset(const char *value);
1921 #endif
1922
1923 struct var {
1924         struct var *next;               /* next entry in hash list */
1925         int flags;                      /* flags are defined above */
1926         const char *var_text;           /* name=value */
1927         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1928                                         /* the variable gets set/unset */
1929 };
1930
1931 struct localvar {
1932         struct localvar *next;          /* next local variable in list */
1933         struct var *vp;                 /* the variable that was made local */
1934         int flags;                      /* saved flags */
1935         const char *text;               /* saved text */
1936 };
1937
1938 /* flags */
1939 #define VEXPORT         0x01    /* variable is exported */
1940 #define VREADONLY       0x02    /* variable cannot be modified */
1941 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1942 #define VTEXTFIXED      0x08    /* text is statically allocated */
1943 #define VSTACK          0x10    /* text is allocated on the stack */
1944 #define VUNSET          0x20    /* the variable is not set */
1945 #define VNOFUNC         0x40    /* don't call the callback function */
1946 #define VNOSET          0x80    /* do not set variable - just readonly test */
1947 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1948 #if ENABLE_ASH_RANDOM_SUPPORT
1949 # define VDYNAMIC       0x200   /* dynamic variable */
1950 #else
1951 # define VDYNAMIC       0
1952 #endif
1953
1954
1955 /* Need to be before varinit_data[] */
1956 #if ENABLE_LOCALE_SUPPORT
1957 static void FAST_FUNC
1958 change_lc_all(const char *value)
1959 {
1960         if (value && *value != '\0')
1961                 setlocale(LC_ALL, value);
1962 }
1963 static void FAST_FUNC
1964 change_lc_ctype(const char *value)
1965 {
1966         if (value && *value != '\0')
1967                 setlocale(LC_CTYPE, value);
1968 }
1969 #endif
1970 #if ENABLE_ASH_MAIL
1971 static void chkmail(void);
1972 static void changemail(const char *var_value) FAST_FUNC;
1973 #else
1974 # define chkmail()  ((void)0)
1975 #endif
1976 static void changepath(const char *) FAST_FUNC;
1977 #if ENABLE_ASH_RANDOM_SUPPORT
1978 static void change_random(const char *) FAST_FUNC;
1979 #endif
1980
1981 static const struct {
1982         int flags;
1983         const char *var_text;
1984         void (*var_func)(const char *) FAST_FUNC;
1985 } varinit_data[] = {
1986         /*
1987          * Note: VEXPORT would not work correctly here for NOFORK applets:
1988          * some environment strings may be constant.
1989          */
1990         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1991 #if ENABLE_ASH_MAIL
1992         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1993         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1994 #endif
1995         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1996         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
1997         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
1998         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
1999 #if ENABLE_ASH_GETOPTS
2000         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2001 #endif
2002 #if ENABLE_ASH_RANDOM_SUPPORT
2003         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2004 #endif
2005 #if ENABLE_LOCALE_SUPPORT
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2008 #endif
2009 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2010         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2011 #endif
2012 };
2013
2014 struct redirtab;
2015
2016 struct globals_var {
2017         struct shparam shellparam;      /* $@ current positional parameters */
2018         struct redirtab *redirlist;
2019         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2020         struct var *vartab[VTABSIZE];
2021         struct var varinit[ARRAY_SIZE(varinit_data)];
2022 };
2023 extern struct globals_var *const ash_ptr_to_globals_var;
2024 #define G_var (*ash_ptr_to_globals_var)
2025 #define shellparam    (G_var.shellparam   )
2026 //#define redirlist     (G_var.redirlist    )
2027 #define preverrout_fd (G_var.preverrout_fd)
2028 #define vartab        (G_var.vartab       )
2029 #define varinit       (G_var.varinit      )
2030 #define INIT_G_var() do { \
2031         unsigned i; \
2032         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2033         barrier(); \
2034         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2035                 varinit[i].flags    = varinit_data[i].flags; \
2036                 varinit[i].var_text = varinit_data[i].var_text; \
2037                 varinit[i].var_func = varinit_data[i].var_func; \
2038         } \
2039 } while (0)
2040
2041 #define vifs      varinit[0]
2042 #if ENABLE_ASH_MAIL
2043 # define vmail    (&vifs)[1]
2044 # define vmpath   (&vmail)[1]
2045 # define vpath    (&vmpath)[1]
2046 #else
2047 # define vpath    (&vifs)[1]
2048 #endif
2049 #define vps1      (&vpath)[1]
2050 #define vps2      (&vps1)[1]
2051 #define vps4      (&vps2)[1]
2052 #if ENABLE_ASH_GETOPTS
2053 # define voptind  (&vps4)[1]
2054 # if ENABLE_ASH_RANDOM_SUPPORT
2055 #  define vrandom (&voptind)[1]
2056 # endif
2057 #else
2058 # if ENABLE_ASH_RANDOM_SUPPORT
2059 #  define vrandom (&vps4)[1]
2060 # endif
2061 #endif
2062
2063 /*
2064  * The following macros access the values of the above variables.
2065  * They have to skip over the name.  They return the null string
2066  * for unset variables.
2067  */
2068 #define ifsval()        (vifs.var_text + 4)
2069 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2070 #if ENABLE_ASH_MAIL
2071 # define mailval()      (vmail.var_text + 5)
2072 # define mpathval()     (vmpath.var_text + 9)
2073 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2074 #endif
2075 #define pathval()       (vpath.var_text + 5)
2076 #define ps1val()        (vps1.var_text + 4)
2077 #define ps2val()        (vps2.var_text + 4)
2078 #define ps4val()        (vps4.var_text + 4)
2079 #if ENABLE_ASH_GETOPTS
2080 # define optindval()    (voptind.var_text + 7)
2081 #endif
2082
2083 #if ENABLE_ASH_GETOPTS
2084 static void FAST_FUNC
2085 getoptsreset(const char *value)
2086 {
2087         shellparam.optind = number(value) ?: 1;
2088         shellparam.optoff = -1;
2089 }
2090 #endif
2091
2092 /*
2093  * Compares two strings up to the first = or '\0'.  The first
2094  * string must be terminated by '='; the second may be terminated by
2095  * either '=' or '\0'.
2096  */
2097 static int
2098 varcmp(const char *p, const char *q)
2099 {
2100         int c, d;
2101
2102         while ((c = *p) == (d = *q)) {
2103                 if (c == '\0' || c == '=')
2104                         goto out;
2105                 p++;
2106                 q++;
2107         }
2108         if (c == '=')
2109                 c = '\0';
2110         if (d == '=')
2111                 d = '\0';
2112  out:
2113         return c - d;
2114 }
2115
2116 /*
2117  * Find the appropriate entry in the hash table from the name.
2118  */
2119 static struct var **
2120 hashvar(const char *p)
2121 {
2122         unsigned hashval;
2123
2124         hashval = ((unsigned char) *p) << 4;
2125         while (*p && *p != '=')
2126                 hashval += (unsigned char) *p++;
2127         return &vartab[hashval % VTABSIZE];
2128 }
2129
2130 static int
2131 vpcmp(const void *a, const void *b)
2132 {
2133         return varcmp(*(const char **)a, *(const char **)b);
2134 }
2135
2136 /*
2137  * This routine initializes the builtin variables.
2138  */
2139 static void
2140 initvar(void)
2141 {
2142         struct var *vp;
2143         struct var *end;
2144         struct var **vpp;
2145
2146         /*
2147          * PS1 depends on uid
2148          */
2149 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2150         vps1.var_text = "PS1=\\w \\$ ";
2151 #else
2152         if (!geteuid())
2153                 vps1.var_text = "PS1=# ";
2154 #endif
2155         vp = varinit;
2156         end = vp + ARRAY_SIZE(varinit);
2157         do {
2158                 vpp = hashvar(vp->var_text);
2159                 vp->next = *vpp;
2160                 *vpp = vp;
2161         } while (++vp < end);
2162 }
2163
2164 static struct var **
2165 findvar(struct var **vpp, const char *name)
2166 {
2167         for (; *vpp; vpp = &(*vpp)->next) {
2168                 if (varcmp((*vpp)->var_text, name) == 0) {
2169                         break;
2170                 }
2171         }
2172         return vpp;
2173 }
2174
2175 /*
2176  * Find the value of a variable.  Returns NULL if not set.
2177  */
2178 static const char* FAST_FUNC
2179 lookupvar(const char *name)
2180 {
2181         struct var *v;
2182
2183         v = *findvar(hashvar(name), name);
2184         if (v) {
2185 #if ENABLE_ASH_RANDOM_SUPPORT
2186         /*
2187          * Dynamic variables are implemented roughly the same way they are
2188          * in bash. Namely, they're "special" so long as they aren't unset.
2189          * As soon as they're unset, they're no longer dynamic, and dynamic
2190          * lookup will no longer happen at that point. -- PFM.
2191          */
2192                 if (v->flags & VDYNAMIC)
2193                         v->var_func(NULL);
2194 #endif
2195                 if (!(v->flags & VUNSET))
2196                         return var_end(v->var_text);
2197         }
2198         return NULL;
2199 }
2200
2201 #if ENABLE_UNICODE_SUPPORT
2202 static void
2203 reinit_unicode_for_ash(void)
2204 {
2205         /* Unicode support should be activated even if LANG is set
2206          * _during_ shell execution, not only if it was set when
2207          * shell was started. Therefore, re-check LANG every time:
2208          */
2209         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2210          || ENABLE_UNICODE_USING_LOCALE
2211         ) {
2212                 const char *s = lookupvar("LC_ALL");
2213                 if (!s) s = lookupvar("LC_CTYPE");
2214                 if (!s) s = lookupvar("LANG");
2215                 reinit_unicode(s);
2216         }
2217 }
2218 #else
2219 # define reinit_unicode_for_ash() ((void)0)
2220 #endif
2221
2222 /*
2223  * Search the environment of a builtin command.
2224  */
2225 static const char *
2226 bltinlookup(const char *name)
2227 {
2228         struct strlist *sp;
2229
2230         for (sp = cmdenviron; sp; sp = sp->next) {
2231                 if (varcmp(sp->text, name) == 0)
2232                         return var_end(sp->text);
2233         }
2234         return lookupvar(name);
2235 }
2236
2237 /*
2238  * Same as setvar except that the variable and value are passed in
2239  * the first argument as name=value.  Since the first argument will
2240  * be actually stored in the table, it should not be a string that
2241  * will go away.
2242  * Called with interrupts off.
2243  */
2244 static void
2245 setvareq(char *s, int flags)
2246 {
2247         struct var *vp, **vpp;
2248
2249         vpp = hashvar(s);
2250         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2251         vp = *findvar(vpp, s);
2252         if (vp) {
2253                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2254                         const char *n;
2255
2256                         if (flags & VNOSAVE)
2257                                 free(s);
2258                         n = vp->var_text;
2259                         exitstatus = 1;
2260                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2261                 }
2262
2263                 if (flags & VNOSET)
2264                         return;
2265
2266                 if (vp->var_func && !(flags & VNOFUNC))
2267                         vp->var_func(var_end(s));
2268
2269                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2270                         free((char*)vp->var_text);
2271
2272                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2273                         *vpp = vp->next;
2274                         free(vp);
2275  out_free:
2276                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2277                                 free(s);
2278                         return;
2279                 }
2280
2281                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2282         } else {
2283                 /* variable s is not found */
2284                 if (flags & VNOSET)
2285                         return;
2286                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2287                         goto out_free;
2288                 vp = ckzalloc(sizeof(*vp));
2289                 vp->next = *vpp;
2290                 /*vp->func = NULL; - ckzalloc did it */
2291                 *vpp = vp;
2292         }
2293         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2294                 s = ckstrdup(s);
2295         vp->var_text = s;
2296         vp->flags = flags;
2297 }
2298
2299 /*
2300  * Set the value of a variable.  The flags argument is ored with the
2301  * flags of the variable.  If val is NULL, the variable is unset.
2302  */
2303 static void
2304 setvar(const char *name, const char *val, int flags)
2305 {
2306         const char *q;
2307         char *p;
2308         char *nameeq;
2309         size_t namelen;
2310         size_t vallen;
2311
2312         q = endofname(name);
2313         p = strchrnul(q, '=');
2314         namelen = p - name;
2315         if (!namelen || p != q)
2316                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2317         vallen = 0;
2318         if (val == NULL) {
2319                 flags |= VUNSET;
2320         } else {
2321                 vallen = strlen(val);
2322         }
2323
2324         INT_OFF;
2325         nameeq = ckmalloc(namelen + vallen + 2);
2326         p = mempcpy(nameeq, name, namelen);
2327         if (val) {
2328                 *p++ = '=';
2329                 p = mempcpy(p, val, vallen);
2330         }
2331         *p = '\0';
2332         setvareq(nameeq, flags | VNOSAVE);
2333         INT_ON;
2334 }
2335
2336 static void FAST_FUNC
2337 setvar0(const char *name, const char *val)
2338 {
2339         setvar(name, val, 0);
2340 }
2341
2342 /*
2343  * Unset the specified variable.
2344  */
2345 static void
2346 unsetvar(const char *s)
2347 {
2348         setvar0(s, NULL);
2349 }
2350
2351 /*
2352  * Process a linked list of variable assignments.
2353  */
2354 static void
2355 listsetvar(struct strlist *list_set_var, int flags)
2356 {
2357         struct strlist *lp = list_set_var;
2358
2359         if (!lp)
2360                 return;
2361         INT_OFF;
2362         do {
2363                 setvareq(lp->text, flags);
2364                 lp = lp->next;
2365         } while (lp);
2366         INT_ON;
2367 }
2368
2369 /*
2370  * Generate a list of variables satisfying the given conditions.
2371  */
2372 static char **
2373 listvars(int on, int off, char ***end)
2374 {
2375         struct var **vpp;
2376         struct var *vp;
2377         char **ep;
2378         int mask;
2379
2380         STARTSTACKSTR(ep);
2381         vpp = vartab;
2382         mask = on | off;
2383         do {
2384                 for (vp = *vpp; vp; vp = vp->next) {
2385                         if ((vp->flags & mask) == on) {
2386                                 if (ep == stackstrend())
2387                                         ep = growstackstr();
2388                                 *ep++ = (char*)vp->var_text;
2389                         }
2390                 }
2391         } while (++vpp < vartab + VTABSIZE);
2392         if (ep == stackstrend())
2393                 ep = growstackstr();
2394         if (end)
2395                 *end = ep;
2396         *ep++ = NULL;
2397         return grabstackstr(ep);
2398 }
2399
2400
2401 /* ============ Path search helper
2402  *
2403  * The variable path (passed by reference) should be set to the start
2404  * of the path before the first call; path_advance will update
2405  * this value as it proceeds.  Successive calls to path_advance will return
2406  * the possible path expansions in sequence.  If an option (indicated by
2407  * a percent sign) appears in the path entry then the global variable
2408  * pathopt will be set to point to it; otherwise pathopt will be set to
2409  * NULL.
2410  */
2411 static const char *pathopt;     /* set by path_advance */
2412
2413 static char *
2414 path_advance(const char **path, const char *name)
2415 {
2416         const char *p;
2417         char *q;
2418         const char *start;
2419         size_t len;
2420
2421         if (*path == NULL)
2422                 return NULL;
2423         start = *path;
2424         for (p = start; *p && *p != ':' && *p != '%'; p++)
2425                 continue;
2426         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2427         while (stackblocksize() < len)
2428                 growstackblock();
2429         q = stackblock();
2430         if (p != start) {
2431                 q = mempcpy(q, start, p - start);
2432                 *q++ = '/';
2433         }
2434         strcpy(q, name);
2435         pathopt = NULL;
2436         if (*p == '%') {
2437                 pathopt = ++p;
2438                 while (*p && *p != ':')
2439                         p++;
2440         }
2441         if (*p == ':')
2442                 *path = p + 1;
2443         else
2444                 *path = NULL;
2445         return stalloc(len);
2446 }
2447
2448
2449 /* ============ Prompt */
2450
2451 static smallint doprompt;                   /* if set, prompt the user */
2452 static smallint needprompt;                 /* true if interactive and at start of line */
2453
2454 #if ENABLE_FEATURE_EDITING
2455 static line_input_t *line_input_state;
2456 static const char *cmdedit_prompt;
2457 static void
2458 putprompt(const char *s)
2459 {
2460         if (ENABLE_ASH_EXPAND_PRMT) {
2461                 free((char*)cmdedit_prompt);
2462                 cmdedit_prompt = ckstrdup(s);
2463                 return;
2464         }
2465         cmdedit_prompt = s;
2466 }
2467 #else
2468 static void
2469 putprompt(const char *s)
2470 {
2471         out2str(s);
2472 }
2473 #endif
2474
2475 /* expandstr() needs parsing machinery, so it is far away ahead... */
2476 static const char *expandstr(const char *ps);
2477
2478 static void
2479 setprompt_if(smallint do_set, int whichprompt)
2480 {
2481         const char *prompt;
2482         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2483
2484         if (!do_set)
2485                 return;
2486
2487         needprompt = 0;
2488
2489         switch (whichprompt) {
2490         case 1:
2491                 prompt = ps1val();
2492                 break;
2493         case 2:
2494                 prompt = ps2val();
2495                 break;
2496         default:                        /* 0 */
2497                 prompt = nullstr;
2498         }
2499 #if ENABLE_ASH_EXPAND_PRMT
2500         pushstackmark(&smark, stackblocksize());
2501         putprompt(expandstr(prompt));
2502         popstackmark(&smark);
2503 #else
2504         putprompt(prompt);
2505 #endif
2506 }
2507
2508
2509 /* ============ The cd and pwd commands */
2510
2511 #define CD_PHYSICAL 1
2512 #define CD_PRINT 2
2513
2514 static int
2515 cdopt(void)
2516 {
2517         int flags = 0;
2518         int i, j;
2519
2520         j = 'L';
2521         while ((i = nextopt("LP")) != '\0') {
2522                 if (i != j) {
2523                         flags ^= CD_PHYSICAL;
2524                         j = i;
2525                 }
2526         }
2527
2528         return flags;
2529 }
2530
2531 /*
2532  * Update curdir (the name of the current directory) in response to a
2533  * cd command.
2534  */
2535 static const char *
2536 updatepwd(const char *dir)
2537 {
2538         char *new;
2539         char *p;
2540         char *cdcomppath;
2541         const char *lim;
2542
2543         cdcomppath = sstrdup(dir);
2544         STARTSTACKSTR(new);
2545         if (*dir != '/') {
2546                 if (curdir == nullstr)
2547                         return 0;
2548                 new = stack_putstr(curdir, new);
2549         }
2550         new = makestrspace(strlen(dir) + 2, new);
2551         lim = (char *)stackblock() + 1;
2552         if (*dir != '/') {
2553                 if (new[-1] != '/')
2554                         USTPUTC('/', new);
2555                 if (new > lim && *lim == '/')
2556                         lim++;
2557         } else {
2558                 USTPUTC('/', new);
2559                 cdcomppath++;
2560                 if (dir[1] == '/' && dir[2] != '/') {
2561                         USTPUTC('/', new);
2562                         cdcomppath++;
2563                         lim++;
2564                 }
2565         }
2566         p = strtok(cdcomppath, "/");
2567         while (p) {
2568                 switch (*p) {
2569                 case '.':
2570                         if (p[1] == '.' && p[2] == '\0') {
2571                                 while (new > lim) {
2572                                         STUNPUTC(new);
2573                                         if (new[-1] == '/')
2574                                                 break;
2575                                 }
2576                                 break;
2577                         }
2578                         if (p[1] == '\0')
2579                                 break;
2580                         /* fall through */
2581                 default:
2582                         new = stack_putstr(p, new);
2583                         USTPUTC('/', new);
2584                 }
2585                 p = strtok(NULL, "/");
2586         }
2587         if (new > lim)
2588                 STUNPUTC(new);
2589         *new = 0;
2590         return stackblock();
2591 }
2592
2593 /*
2594  * Find out what the current directory is. If we already know the current
2595  * directory, this routine returns immediately.
2596  */
2597 static char *
2598 getpwd(void)
2599 {
2600         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2601         return dir ? dir : nullstr;
2602 }
2603
2604 static void
2605 setpwd(const char *val, int setold)
2606 {
2607         char *oldcur, *dir;
2608
2609         oldcur = dir = curdir;
2610
2611         if (setold) {
2612                 setvar("OLDPWD", oldcur, VEXPORT);
2613         }
2614         INT_OFF;
2615         if (physdir != nullstr) {
2616                 if (physdir != oldcur)
2617                         free(physdir);
2618                 physdir = nullstr;
2619         }
2620         if (oldcur == val || !val) {
2621                 char *s = getpwd();
2622                 physdir = s;
2623                 if (!val)
2624                         dir = s;
2625         } else
2626                 dir = ckstrdup(val);
2627         if (oldcur != dir && oldcur != nullstr) {
2628                 free(oldcur);
2629         }
2630         curdir = dir;
2631         INT_ON;
2632         setvar("PWD", dir, VEXPORT);
2633 }
2634
2635 static void hashcd(void);
2636
2637 /*
2638  * Actually do the chdir.  We also call hashcd to let other routines
2639  * know that the current directory has changed.
2640  */
2641 static int
2642 docd(const char *dest, int flags)
2643 {
2644         const char *dir = NULL;
2645         int err;
2646
2647         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2648
2649         INT_OFF;
2650         if (!(flags & CD_PHYSICAL)) {
2651                 dir = updatepwd(dest);
2652                 if (dir)
2653                         dest = dir;
2654         }
2655         err = chdir(dest);
2656         if (err)
2657                 goto out;
2658         setpwd(dir, 1);
2659         hashcd();
2660  out:
2661         INT_ON;
2662         return err;
2663 }
2664
2665 static int FAST_FUNC
2666 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2667 {
2668         const char *dest;
2669         const char *path;
2670         const char *p;
2671         char c;
2672         struct stat statb;
2673         int flags;
2674
2675         flags = cdopt();
2676         dest = *argptr;
2677         if (!dest)
2678                 dest = bltinlookup("HOME");
2679         else if (LONE_DASH(dest)) {
2680                 dest = bltinlookup("OLDPWD");
2681                 flags |= CD_PRINT;
2682         }
2683         if (!dest)
2684                 dest = nullstr;
2685         if (*dest == '/')
2686                 goto step6;
2687         if (*dest == '.') {
2688                 c = dest[1];
2689  dotdot:
2690                 switch (c) {
2691                 case '\0':
2692                 case '/':
2693                         goto step6;
2694                 case '.':
2695                         c = dest[2];
2696                         if (c != '.')
2697                                 goto dotdot;
2698                 }
2699         }
2700         if (!*dest)
2701                 dest = ".";
2702         path = bltinlookup("CDPATH");
2703         while (path) {
2704                 c = *path;
2705                 p = path_advance(&path, dest);
2706                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2707                         if (c && c != ':')
2708                                 flags |= CD_PRINT;
2709  docd:
2710                         if (!docd(p, flags))
2711                                 goto out;
2712                         goto err;
2713                 }
2714         }
2715
2716  step6:
2717         p = dest;
2718         goto docd;
2719
2720  err:
2721         ash_msg_and_raise_error("can't cd to %s", dest);
2722         /* NOTREACHED */
2723  out:
2724         if (flags & CD_PRINT)
2725                 out1fmt("%s\n", curdir);
2726         return 0;
2727 }
2728
2729 static int FAST_FUNC
2730 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2731 {
2732         int flags;
2733         const char *dir = curdir;
2734
2735         flags = cdopt();
2736         if (flags) {
2737                 if (physdir == nullstr)
2738                         setpwd(dir, 0);
2739                 dir = physdir;
2740         }
2741         out1fmt("%s\n", dir);
2742         return 0;
2743 }
2744
2745
2746 /* ============ ... */
2747
2748
2749 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2750
2751 /* Syntax classes */
2752 #define CWORD     0             /* character is nothing special */
2753 #define CNL       1             /* newline character */
2754 #define CBACK     2             /* a backslash character */
2755 #define CSQUOTE   3             /* single quote */
2756 #define CDQUOTE   4             /* double quote */
2757 #define CENDQUOTE 5             /* a terminating quote */
2758 #define CBQUOTE   6             /* backwards single quote */
2759 #define CVAR      7             /* a dollar sign */
2760 #define CENDVAR   8             /* a '}' character */
2761 #define CLP       9             /* a left paren in arithmetic */
2762 #define CRP      10             /* a right paren in arithmetic */
2763 #define CENDFILE 11             /* end of file */
2764 #define CCTL     12             /* like CWORD, except it must be escaped */
2765 #define CSPCL    13             /* these terminate a word */
2766 #define CIGN     14             /* character should be ignored */
2767
2768 #define PEOF     256
2769 #if ENABLE_ASH_ALIAS
2770 # define PEOA    257
2771 #endif
2772
2773 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2774
2775 #if ENABLE_FEATURE_SH_MATH
2776 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2777 #else
2778 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2779 #endif
2780 static const uint16_t S_I_T[] ALIGN2 = {
2781 #if ENABLE_ASH_ALIAS
2782         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2783 #endif
2784         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2785         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2786         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2787         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2788         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2789         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2790         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2791         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2792         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2793         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2794         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2795 #if !USE_SIT_FUNCTION
2796         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2797         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2798         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2799 #endif
2800 #undef SIT_ITEM
2801 };
2802 /* Constants below must match table above */
2803 enum {
2804 #if ENABLE_ASH_ALIAS
2805         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2806 #endif
2807         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2808         CNL_CNL_CNL_CNL                    , /*  2 */
2809         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2810         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2811         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2812         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2813         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2814         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2815         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2816         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2817         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2818         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2819         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2820         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2821 };
2822
2823 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2824  * caller must ensure proper cast on it if c is *char_ptr!
2825  */
2826 /* Values for syntax param */
2827 #define BASESYNTAX 0    /* not in quotes */
2828 #define DQSYNTAX   1    /* in double quotes */
2829 #define SQSYNTAX   2    /* in single quotes */
2830 #define ARISYNTAX  3    /* in arithmetic */
2831 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2832
2833 #if USE_SIT_FUNCTION
2834
2835 static int
2836 SIT(int c, int syntax)
2837 {
2838         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2839         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2840         /*
2841          * This causes '/' to be prepended with CTLESC in dquoted string,
2842          * making "./file"* treated incorrectly because we feed
2843          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2844          * The "homegrown" glob implementation is okay with that,
2845          * but glibc one isn't. With '/' always treated as CWORD,
2846          * both work fine.
2847          */
2848 # if ENABLE_ASH_ALIAS
2849         static const uint8_t syntax_index_table[] ALIGN1 = {
2850                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2851                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2852                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2853                 11, 3                           /* "}~" */
2854         };
2855 # else
2856         static const uint8_t syntax_index_table[] ALIGN1 = {
2857                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2858                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2859                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2860                 10, 2                           /* "}~" */
2861         };
2862 # endif
2863         const char *s;
2864         int indx;
2865
2866         if (c == PEOF)
2867                 return CENDFILE;
2868 # if ENABLE_ASH_ALIAS
2869         if (c == PEOA)
2870                 indx = 0;
2871         else
2872 # endif
2873         {
2874                 /* Cast is purely for paranoia here,
2875                  * just in case someone passed signed char to us */
2876                 if ((unsigned char)c >= CTL_FIRST
2877                  && (unsigned char)c <= CTL_LAST
2878                 ) {
2879                         return CCTL;
2880                 }
2881                 s = strchrnul(spec_symbls, c);
2882                 if (*s == '\0')
2883                         return CWORD;
2884                 indx = syntax_index_table[s - spec_symbls];
2885         }
2886         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2887 }
2888
2889 #else   /* !USE_SIT_FUNCTION */
2890
2891 static const uint8_t syntax_index_table[] ALIGN1 = {
2892         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2893         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2894         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2895         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2896         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2897         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2898         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2899         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2900         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2901         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2902         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2903         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2904         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2905         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2906         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2907         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2912         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2913         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2914         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2915         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2916         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2917         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2918         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2919         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2920         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2921         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2922         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2926         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2927         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2928         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2929         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2930         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2931         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2932         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2933         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2934         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2935         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2936         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2937         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2938         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2939         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2940 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2941         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2942         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2943         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2953         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2954         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2955         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2956         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2957         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2958         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2986         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2987         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2988         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2991         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2994         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2995         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2996         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3019         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3020         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3021         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3022         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3023         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3024         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3025         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3026         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3027         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3028         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3029         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3030         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3031         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3032         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3033         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3034         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3150         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3151 # if ENABLE_ASH_ALIAS
3152         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3153 # endif
3154 };
3155
3156 #if 1
3157 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3158 #else /* debug version, caught one signed char bug */
3159 # define SIT(c, syntax) \
3160         ({ \
3161                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3162                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3163                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3164                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3165                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3166         })
3167 #endif
3168
3169 #endif  /* !USE_SIT_FUNCTION */
3170
3171
3172 /* ============ Alias handling */
3173
3174 #if ENABLE_ASH_ALIAS
3175
3176 #define ALIASINUSE 1
3177 #define ALIASDEAD  2
3178
3179 struct alias {
3180         struct alias *next;
3181         char *name;
3182         char *val;
3183         int flag;
3184 };
3185
3186
3187 static struct alias **atab; // [ATABSIZE];
3188 #define INIT_G_alias() do { \
3189         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3190 } while (0)
3191
3192
3193 static struct alias **
3194 __lookupalias(const char *name)
3195 {
3196         unsigned int hashval;
3197         struct alias **app;
3198         const char *p;
3199         unsigned int ch;
3200
3201         p = name;
3202
3203         ch = (unsigned char)*p;
3204         hashval = ch << 4;
3205         while (ch) {
3206                 hashval += ch;
3207                 ch = (unsigned char)*++p;
3208         }
3209         app = &atab[hashval % ATABSIZE];
3210
3211         for (; *app; app = &(*app)->next) {
3212                 if (strcmp(name, (*app)->name) == 0) {
3213                         break;
3214                 }
3215         }
3216
3217         return app;
3218 }
3219
3220 static struct alias *
3221 lookupalias(const char *name, int check)
3222 {
3223         struct alias *ap = *__lookupalias(name);
3224
3225         if (check && ap && (ap->flag & ALIASINUSE))
3226                 return NULL;
3227         return ap;
3228 }
3229
3230 static struct alias *
3231 freealias(struct alias *ap)
3232 {
3233         struct alias *next;
3234
3235         if (ap->flag & ALIASINUSE) {
3236                 ap->flag |= ALIASDEAD;
3237                 return ap;
3238         }
3239
3240         next = ap->next;
3241         free(ap->name);
3242         free(ap->val);
3243         free(ap);
3244         return next;
3245 }
3246
3247 static void
3248 setalias(const char *name, const char *val)
3249 {
3250         struct alias *ap, **app;
3251
3252         app = __lookupalias(name);
3253         ap = *app;
3254         INT_OFF;
3255         if (ap) {
3256                 if (!(ap->flag & ALIASINUSE)) {
3257                         free(ap->val);
3258                 }
3259                 ap->val = ckstrdup(val);
3260                 ap->flag &= ~ALIASDEAD;
3261         } else {
3262                 /* not found */
3263                 ap = ckzalloc(sizeof(struct alias));
3264                 ap->name = ckstrdup(name);
3265                 ap->val = ckstrdup(val);
3266                 /*ap->flag = 0; - ckzalloc did it */
3267                 /*ap->next = NULL;*/
3268                 *app = ap;
3269         }
3270         INT_ON;
3271 }
3272
3273 static int
3274 unalias(const char *name)
3275 {
3276         struct alias **app;
3277
3278         app = __lookupalias(name);
3279
3280         if (*app) {
3281                 INT_OFF;
3282                 *app = freealias(*app);
3283                 INT_ON;
3284                 return 0;
3285         }
3286
3287         return 1;
3288 }
3289
3290 static void
3291 rmaliases(void)
3292 {
3293         struct alias *ap, **app;
3294         int i;
3295
3296         INT_OFF;
3297         for (i = 0; i < ATABSIZE; i++) {
3298                 app = &atab[i];
3299                 for (ap = *app; ap; ap = *app) {
3300                         *app = freealias(*app);
3301                         if (ap == *app) {
3302                                 app = &ap->next;
3303                         }
3304                 }
3305         }
3306         INT_ON;
3307 }
3308
3309 static void
3310 printalias(const struct alias *ap)
3311 {
3312         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3313 }
3314
3315 /*
3316  * TODO - sort output
3317  */
3318 static int FAST_FUNC
3319 aliascmd(int argc UNUSED_PARAM, char **argv)
3320 {
3321         char *n, *v;
3322         int ret = 0;
3323         struct alias *ap;
3324
3325         if (!argv[1]) {
3326                 int i;
3327
3328                 for (i = 0; i < ATABSIZE; i++) {
3329                         for (ap = atab[i]; ap; ap = ap->next) {
3330                                 printalias(ap);
3331                         }
3332                 }
3333                 return 0;
3334         }
3335         while ((n = *++argv) != NULL) {
3336                 v = strchr(n+1, '=');
3337                 if (v == NULL) { /* n+1: funny ksh stuff */
3338                         ap = *__lookupalias(n);
3339                         if (ap == NULL) {
3340                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3341                                 ret = 1;
3342                         } else
3343                                 printalias(ap);
3344                 } else {
3345                         *v++ = '\0';
3346                         setalias(n, v);
3347                 }
3348         }
3349
3350         return ret;
3351 }
3352
3353 static int FAST_FUNC
3354 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3355 {
3356         int i;
3357
3358         while (nextopt("a") != '\0') {
3359                 rmaliases();
3360                 return 0;
3361         }
3362         for (i = 0; *argptr; argptr++) {
3363                 if (unalias(*argptr)) {
3364                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3365                         i = 1;
3366                 }
3367         }
3368
3369         return i;
3370 }
3371
3372 #endif /* ASH_ALIAS */
3373
3374
3375 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3376 #define FORK_FG    0
3377 #define FORK_BG    1
3378 #define FORK_NOJOB 2
3379
3380 /* mode flags for showjob(s) */
3381 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3382 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3383 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3384 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3385
3386 /*
3387  * A job structure contains information about a job.  A job is either a
3388  * single process or a set of processes contained in a pipeline.  In the
3389  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3390  * array of pids.
3391  */
3392 struct procstat {
3393         pid_t   ps_pid;         /* process id */
3394         int     ps_status;      /* last process status from wait() */
3395         char    *ps_cmd;        /* text of command being run */
3396 };
3397
3398 struct job {
3399         struct procstat ps0;    /* status of process */
3400         struct procstat *ps;    /* status or processes when more than one */
3401 #if JOBS
3402         int stopstatus;         /* status of a stopped job */
3403 #endif
3404         unsigned nprocs;        /* number of processes */
3405
3406 #define JOBRUNNING      0       /* at least one proc running */
3407 #define JOBSTOPPED      1       /* all procs are stopped */
3408 #define JOBDONE         2       /* all procs are completed */
3409         unsigned
3410                 state: 8,
3411 #if JOBS
3412                 sigint: 1,      /* job was killed by SIGINT */
3413                 jobctl: 1,      /* job running under job control */
3414 #endif
3415                 waited: 1,      /* true if this entry has been waited for */
3416                 used: 1,        /* true if this entry is in used */
3417                 changed: 1;     /* true if status has changed */
3418         struct job *prev_job;   /* previous job */
3419 };
3420
3421 static struct job *makejob(/*union node *,*/ int);
3422 static int forkshell(struct job *, union node *, int);
3423 static int waitforjob(struct job *);
3424
3425 #if !JOBS
3426 enum { doing_jobctl = 0 };
3427 #define setjobctl(on) do {} while (0)
3428 #else
3429 static smallint doing_jobctl; //references:8
3430 static void setjobctl(int);
3431 #endif
3432
3433 /*
3434  * Ignore a signal.
3435  */
3436 static void
3437 ignoresig(int signo)
3438 {
3439         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3440         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3441                 /* No, need to do it */
3442                 signal(signo, SIG_IGN);
3443         }
3444         sigmode[signo - 1] = S_HARD_IGN;
3445 }
3446
3447 /*
3448  * Only one usage site - in setsignal()
3449  */
3450 static void
3451 signal_handler(int signo)
3452 {
3453         if (signo == SIGCHLD) {
3454                 got_sigchld = 1;
3455                 if (!trap[SIGCHLD])
3456                         return;
3457         }
3458
3459         gotsig[signo - 1] = 1;
3460         pending_sig = signo;
3461
3462         if (signo == SIGINT && !trap[SIGINT]) {
3463                 if (!suppress_int) {
3464                         pending_sig = 0;
3465                         raise_interrupt(); /* does not return */
3466                 }
3467                 pending_int = 1;
3468         }
3469 }
3470
3471 /*
3472  * Set the signal handler for the specified signal.  The routine figures
3473  * out what it should be set to.
3474  */
3475 static void
3476 setsignal(int signo)
3477 {
3478         char *t;
3479         char cur_act, new_act;
3480         struct sigaction act;
3481
3482         t = trap[signo];
3483         new_act = S_DFL;
3484         if (t != NULL) { /* trap for this sig is set */
3485                 new_act = S_CATCH;
3486                 if (t[0] == '\0') /* trap is "": ignore this sig */
3487                         new_act = S_IGN;
3488         }
3489
3490         if (rootshell && new_act == S_DFL) {
3491                 switch (signo) {
3492                 case SIGINT:
3493                         if (iflag || minusc || sflag == 0)
3494                                 new_act = S_CATCH;
3495                         break;
3496                 case SIGQUIT:
3497 #if DEBUG
3498                         if (debug)
3499                                 break;
3500 #endif
3501                         /* man bash:
3502                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3503                          * commands run by bash have signal handlers
3504                          * set to the values inherited by the shell
3505                          * from its parent". */
3506                         new_act = S_IGN;
3507                         break;
3508                 case SIGTERM:
3509                         if (iflag)
3510                                 new_act = S_IGN;
3511                         break;
3512 #if JOBS
3513                 case SIGTSTP:
3514                 case SIGTTOU:
3515                         if (mflag)
3516                                 new_act = S_IGN;
3517                         break;
3518 #endif
3519                 }
3520         }
3521 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3522 //whereas we have to restore it to what shell got on entry
3523 //from the parent. See comment above
3524
3525         if (signo == SIGCHLD)
3526                 new_act = S_CATCH;
3527
3528         t = &sigmode[signo - 1];
3529         cur_act = *t;
3530         if (cur_act == 0) {
3531                 /* current setting is not yet known */
3532                 if (sigaction(signo, NULL, &act)) {
3533                         /* pretend it worked; maybe we should give a warning,
3534                          * but other shells don't. We don't alter sigmode,
3535                          * so we retry every time.
3536                          * btw, in Linux it never fails. --vda */
3537                         return;
3538                 }
3539                 if (act.sa_handler == SIG_IGN) {
3540                         cur_act = S_HARD_IGN;
3541                         if (mflag
3542                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3543                         ) {
3544                                 cur_act = S_IGN;   /* don't hard ignore these */
3545                         }
3546                 }
3547         }
3548         if (cur_act == S_HARD_IGN || cur_act == new_act)
3549                 return;
3550
3551         act.sa_handler = SIG_DFL;
3552         switch (new_act) {
3553         case S_CATCH:
3554                 act.sa_handler = signal_handler;
3555                 break;
3556         case S_IGN:
3557                 act.sa_handler = SIG_IGN;
3558                 break;
3559         }
3560
3561         /* flags and mask matter only if !DFL and !IGN, but we do it
3562          * for all cases for more deterministic behavior:
3563          */
3564         act.sa_flags = 0;
3565         sigfillset(&act.sa_mask);
3566
3567         sigaction_set(signo, &act);
3568
3569         *t = new_act;
3570 }
3571
3572 /* mode flags for set_curjob */
3573 #define CUR_DELETE 2
3574 #define CUR_RUNNING 1
3575 #define CUR_STOPPED 0
3576
3577 #if JOBS
3578 /* pgrp of shell on invocation */
3579 static int initialpgrp; //references:2
3580 static int ttyfd = -1; //5
3581 #endif
3582 /* array of jobs */
3583 static struct job *jobtab; //5
3584 /* size of array */
3585 static unsigned njobs; //4
3586 /* current job */
3587 static struct job *curjob; //lots
3588 /* number of presumed living untracked jobs */
3589 static int jobless; //4
3590
3591 #if 0
3592 /* Bash has a feature: it restores termios after a successful wait for
3593  * a foreground job which had at least one stopped or sigkilled member.
3594  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3595  * properly restoring tty state. Should we do this too?
3596  * A reproducer: ^Z an interactive python:
3597  *
3598  * # python
3599  * Python 2.7.12 (...)
3600  * >>> ^Z
3601  *      { python leaves tty in -icanon -echo state. We do survive that... }
3602  *  [1]+  Stopped                    python
3603  *      { ...however, next program (python #2) does not survive it well: }
3604  * # python
3605  * Python 2.7.12 (...)
3606  * >>> Traceback (most recent call last):
3607  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3608  *   File "<stdin>", line 1, in <module>
3609  * NameError: name 'qwerty' is not defined
3610  *
3611  * The implementation below is modeled on bash code and seems to work.
3612  * However, I'm not sure we should do this. For one: what if I'd fg
3613  * the stopped python instead? It'll be confused by "restored" tty state.
3614  */
3615 static struct termios shell_tty_info;
3616 static void
3617 get_tty_state(void)
3618 {
3619         if (rootshell && ttyfd >= 0)
3620                 tcgetattr(ttyfd, &shell_tty_info);
3621 }
3622 static void
3623 set_tty_state(void)
3624 {
3625         /* if (rootshell) - caller ensures this */
3626         if (ttyfd >= 0)
3627                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3628 }
3629 static int
3630 job_signal_status(struct job *jp)
3631 {
3632         int status;
3633         unsigned i;
3634         struct procstat *ps = jp->ps;
3635         for (i = 0; i < jp->nprocs; i++) {
3636                 status = ps[i].ps_status;
3637                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3638                         return status;
3639         }
3640         return 0;
3641 }
3642 static void
3643 restore_tty_if_stopped_or_signaled(struct job *jp)
3644 {
3645 //TODO: check what happens if we come from waitforjob() in expbackq()
3646         if (rootshell) {
3647                 int s = job_signal_status(jp);
3648                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3649                         set_tty_state();
3650         }
3651 }
3652 #else
3653 # define get_tty_state() ((void)0)
3654 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3655 #endif
3656
3657 static void
3658 set_curjob(struct job *jp, unsigned mode)
3659 {
3660         struct job *jp1;
3661         struct job **jpp, **curp;
3662
3663         /* first remove from list */
3664         jpp = curp = &curjob;
3665         while (1) {
3666                 jp1 = *jpp;
3667                 if (jp1 == jp)
3668                         break;
3669                 jpp = &jp1->prev_job;
3670         }
3671         *jpp = jp1->prev_job;
3672
3673         /* Then re-insert in correct position */
3674         jpp = curp;
3675         switch (mode) {
3676         default:
3677 #if DEBUG
3678                 abort();
3679 #endif
3680         case CUR_DELETE:
3681                 /* job being deleted */
3682                 break;
3683         case CUR_RUNNING:
3684                 /* newly created job or backgrounded job,
3685                  * put after all stopped jobs.
3686                  */
3687                 while (1) {
3688                         jp1 = *jpp;
3689 #if JOBS
3690                         if (!jp1 || jp1->state != JOBSTOPPED)
3691 #endif
3692                                 break;
3693                         jpp = &jp1->prev_job;
3694                 }
3695                 /* FALLTHROUGH */
3696 #if JOBS
3697         case CUR_STOPPED:
3698 #endif
3699                 /* newly stopped job - becomes curjob */
3700                 jp->prev_job = *jpp;
3701                 *jpp = jp;
3702                 break;
3703         }
3704 }
3705
3706 #if JOBS || DEBUG
3707 static int
3708 jobno(const struct job *jp)
3709 {
3710         return jp - jobtab + 1;
3711 }
3712 #endif
3713
3714 /*
3715  * Convert a job name to a job structure.
3716  */
3717 #if !JOBS
3718 #define getjob(name, getctl) getjob(name)
3719 #endif
3720 static struct job *
3721 getjob(const char *name, int getctl)
3722 {
3723         struct job *jp;
3724         struct job *found;
3725         const char *err_msg = "%s: no such job";
3726         unsigned num;
3727         int c;
3728         const char *p;
3729         char *(*match)(const char *, const char *);
3730
3731         jp = curjob;
3732         p = name;
3733         if (!p)
3734                 goto currentjob;
3735
3736         if (*p != '%')
3737                 goto err;
3738
3739         c = *++p;
3740         if (!c)
3741                 goto currentjob;
3742
3743         if (!p[1]) {
3744                 if (c == '+' || c == '%') {
3745  currentjob:
3746                         err_msg = "No current job";
3747                         goto check;
3748                 }
3749                 if (c == '-') {
3750                         if (jp)
3751                                 jp = jp->prev_job;
3752                         err_msg = "No previous job";
3753  check:
3754                         if (!jp)
3755                                 goto err;
3756                         goto gotit;
3757                 }
3758         }
3759
3760         if (is_number(p)) {
3761                 num = atoi(p);
3762                 if (num > 0 && num <= njobs) {
3763                         jp = jobtab + num - 1;
3764                         if (jp->used)
3765                                 goto gotit;
3766                         goto err;
3767                 }
3768         }
3769
3770         match = prefix;
3771         if (*p == '?') {
3772                 match = strstr;
3773                 p++;
3774         }
3775
3776         found = NULL;
3777         while (jp) {
3778                 if (match(jp->ps[0].ps_cmd, p)) {
3779                         if (found)
3780                                 goto err;
3781                         found = jp;
3782                         err_msg = "%s: ambiguous";
3783                 }
3784                 jp = jp->prev_job;
3785         }
3786         if (!found)
3787                 goto err;
3788         jp = found;
3789
3790  gotit:
3791 #if JOBS
3792         err_msg = "job %s not created under job control";
3793         if (getctl && jp->jobctl == 0)
3794                 goto err;
3795 #endif
3796         return jp;
3797  err:
3798         ash_msg_and_raise_error(err_msg, name);
3799 }
3800
3801 /*
3802  * Mark a job structure as unused.
3803  */
3804 static void
3805 freejob(struct job *jp)
3806 {
3807         struct procstat *ps;
3808         int i;
3809
3810         INT_OFF;
3811         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3812                 if (ps->ps_cmd != nullstr)
3813                         free(ps->ps_cmd);
3814         }
3815         if (jp->ps != &jp->ps0)
3816                 free(jp->ps);
3817         jp->used = 0;
3818         set_curjob(jp, CUR_DELETE);
3819         INT_ON;
3820 }
3821
3822 #if JOBS
3823 static void
3824 xtcsetpgrp(int fd, pid_t pgrp)
3825 {
3826         if (tcsetpgrp(fd, pgrp))
3827                 ash_msg_and_raise_error("can't set tty process group (%m)");
3828 }
3829
3830 /*
3831  * Turn job control on and off.
3832  *
3833  * Note:  This code assumes that the third arg to ioctl is a character
3834  * pointer, which is true on Berkeley systems but not System V.  Since
3835  * System V doesn't have job control yet, this isn't a problem now.
3836  *
3837  * Called with interrupts off.
3838  */
3839 static void
3840 setjobctl(int on)
3841 {
3842         int fd;
3843         int pgrp;
3844
3845         if (on == doing_jobctl || rootshell == 0)
3846                 return;
3847         if (on) {
3848                 int ofd;
3849                 ofd = fd = open(_PATH_TTY, O_RDWR);
3850                 if (fd < 0) {
3851         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3852          * That sometimes helps to acquire controlling tty.
3853          * Obviously, a workaround for bugs when someone
3854          * failed to provide a controlling tty to bash! :) */
3855                         fd = 2;
3856                         while (!isatty(fd))
3857                                 if (--fd < 0)
3858                                         goto out;
3859                 }
3860                 /* fd is a tty at this point */
3861                 fd = fcntl(fd, F_DUPFD, 10);
3862                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3863                         close(ofd);
3864                 if (fd < 0)
3865                         goto out; /* F_DUPFD failed */
3866                 close_on_exec_on(fd);
3867                 while (1) { /* while we are in the background */
3868                         pgrp = tcgetpgrp(fd);
3869                         if (pgrp < 0) {
3870  out:
3871                                 ash_msg("can't access tty; job control turned off");
3872                                 mflag = on = 0;
3873                                 goto close;
3874                         }
3875                         if (pgrp == getpgrp())
3876                                 break;
3877                         killpg(0, SIGTTIN);
3878                 }
3879                 initialpgrp = pgrp;
3880
3881                 setsignal(SIGTSTP);
3882                 setsignal(SIGTTOU);
3883                 setsignal(SIGTTIN);
3884                 pgrp = rootpid;
3885                 setpgid(0, pgrp);
3886                 xtcsetpgrp(fd, pgrp);
3887         } else {
3888                 /* turning job control off */
3889                 fd = ttyfd;
3890                 pgrp = initialpgrp;
3891                 /* was xtcsetpgrp, but this can make exiting ash
3892                  * loop forever if pty is already deleted */
3893                 tcsetpgrp(fd, pgrp);
3894                 setpgid(0, pgrp);
3895                 setsignal(SIGTSTP);
3896                 setsignal(SIGTTOU);
3897                 setsignal(SIGTTIN);
3898  close:
3899                 if (fd >= 0)
3900                         close(fd);
3901                 fd = -1;
3902         }
3903         ttyfd = fd;
3904         doing_jobctl = on;
3905 }
3906
3907 static int FAST_FUNC
3908 killcmd(int argc, char **argv)
3909 {
3910         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3911                 int i = 1;
3912                 do {
3913                         if (argv[i][0] == '%') {
3914                                 /*
3915                                  * "kill %N" - job kill
3916                                  * Converting to pgrp / pid kill
3917                                  */
3918                                 struct job *jp;
3919                                 char *dst;
3920                                 int j, n;
3921
3922                                 jp = getjob(argv[i], 0);
3923                                 /*
3924                                  * In jobs started under job control, we signal
3925                                  * entire process group by kill -PGRP_ID.
3926                                  * This happens, f.e., in interactive shell.
3927                                  *
3928                                  * Otherwise, we signal each child via
3929                                  * kill PID1 PID2 PID3.
3930                                  * Testcases:
3931                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3932                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3933                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3934                                  */
3935                                 n = jp->nprocs; /* can't be 0 (I hope) */
3936                                 if (jp->jobctl)
3937                                         n = 1;
3938                                 dst = alloca(n * sizeof(int)*4);
3939                                 argv[i] = dst;
3940                                 for (j = 0; j < n; j++) {
3941                                         struct procstat *ps = &jp->ps[j];
3942                                         /* Skip non-running and not-stopped members
3943                                          * (i.e. dead members) of the job
3944                                          */
3945                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3946                                                 continue;
3947                                         /*
3948                                          * kill_main has matching code to expect
3949                                          * leading space. Needed to not confuse
3950                                          * negative pids with "kill -SIGNAL_NO" syntax
3951                                          */
3952                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3953                                 }
3954                                 *dst = '\0';
3955                         }
3956                 } while (argv[++i]);
3957         }
3958         return kill_main(argc, argv);
3959 }
3960
3961 static void
3962 showpipe(struct job *jp /*, FILE *out*/)
3963 {
3964         struct procstat *ps;
3965         struct procstat *psend;
3966
3967         psend = jp->ps + jp->nprocs;
3968         for (ps = jp->ps + 1; ps < psend; ps++)
3969                 printf(" | %s", ps->ps_cmd);
3970         newline_and_flush(stdout);
3971         flush_stdout_stderr();
3972 }
3973
3974
3975 static int
3976 restartjob(struct job *jp, int mode)
3977 {
3978         struct procstat *ps;
3979         int i;
3980         int status;
3981         pid_t pgid;
3982
3983         INT_OFF;
3984         if (jp->state == JOBDONE)
3985                 goto out;
3986         jp->state = JOBRUNNING;
3987         pgid = jp->ps[0].ps_pid;
3988         if (mode == FORK_FG) {
3989                 get_tty_state();
3990                 xtcsetpgrp(ttyfd, pgid);
3991         }
3992         killpg(pgid, SIGCONT);
3993         ps = jp->ps;
3994         i = jp->nprocs;
3995         do {
3996                 if (WIFSTOPPED(ps->ps_status)) {
3997                         ps->ps_status = -1;
3998                 }
3999                 ps++;
4000         } while (--i);
4001  out:
4002         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4003         INT_ON;
4004         return status;
4005 }
4006
4007 static int FAST_FUNC
4008 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4009 {
4010         struct job *jp;
4011         int mode;
4012         int retval;
4013
4014         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4015         nextopt(nullstr);
4016         argv = argptr;
4017         do {
4018                 jp = getjob(*argv, 1);
4019                 if (mode == FORK_BG) {
4020                         set_curjob(jp, CUR_RUNNING);
4021                         printf("[%d] ", jobno(jp));
4022                 }
4023                 out1str(jp->ps[0].ps_cmd);
4024                 showpipe(jp /*, stdout*/);
4025                 retval = restartjob(jp, mode);
4026         } while (*argv && *++argv);
4027         return retval;
4028 }
4029 #endif
4030
4031 static int
4032 sprint_status48(char *s, int status, int sigonly)
4033 {
4034         int col;
4035         int st;
4036
4037         col = 0;
4038         if (!WIFEXITED(status)) {
4039 #if JOBS
4040                 if (WIFSTOPPED(status))
4041                         st = WSTOPSIG(status);
4042                 else
4043 #endif
4044                         st = WTERMSIG(status);
4045                 if (sigonly) {
4046                         if (st == SIGINT || st == SIGPIPE)
4047                                 goto out;
4048 #if JOBS
4049                         if (WIFSTOPPED(status))
4050                                 goto out;
4051 #endif
4052                 }
4053                 st &= 0x7f;
4054 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4055                 col = fmtstr(s, 32, strsignal(st));
4056                 if (WCOREDUMP(status)) {
4057                         strcpy(s + col, " (core dumped)");
4058                         col += sizeof(" (core dumped)")-1;
4059                 }
4060         } else if (!sigonly) {
4061                 st = WEXITSTATUS(status);
4062                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4063         }
4064  out:
4065         return col;
4066 }
4067
4068 static int
4069 wait_block_or_sig(int *status)
4070 {
4071         int pid;
4072
4073         do {
4074                 sigset_t mask;
4075
4076                 /* Poll all children for changes in their state */
4077                 got_sigchld = 0;
4078                 /* if job control is active, accept stopped processes too */
4079                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4080                 if (pid != 0)
4081                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4082
4083                 /* Children exist, but none are ready. Sleep until interesting signal */
4084 #if 1
4085                 sigfillset(&mask);
4086                 sigprocmask(SIG_SETMASK, &mask, &mask);
4087                 while (!got_sigchld && !pending_sig)
4088                         sigsuspend(&mask);
4089                 sigprocmask(SIG_SETMASK, &mask, NULL);
4090 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4091                 while (!got_sigchld && !pending_sig)
4092                         pause();
4093 #endif
4094
4095                 /* If it was SIGCHLD, poll children again */
4096         } while (got_sigchld);
4097
4098         return pid;
4099 }
4100
4101 #define DOWAIT_NONBLOCK 0
4102 #define DOWAIT_BLOCK    1
4103 #define DOWAIT_BLOCK_OR_SIG 2
4104
4105 static int
4106 dowait(int block, struct job *job)
4107 {
4108         int pid;
4109         int status;
4110         struct job *jp;
4111         struct job *thisjob = NULL;
4112
4113         TRACE(("dowait(0x%x) called\n", block));
4114
4115         /* It's wrong to call waitpid() outside of INT_OFF region:
4116          * signal can arrive just after syscall return and handler can
4117          * longjmp away, losing stop/exit notification processing.
4118          * Thus, for "jobs" builtin, and for waiting for a fg job,
4119          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4120          *
4121          * However, for "wait" builtin it is wrong to simply call waitpid()
4122          * in INT_OFF region: "wait" needs to wait for any running job
4123          * to change state, but should exit on any trap too.
4124          * In INT_OFF region, a signal just before syscall entry can set
4125          * pending_sig variables, but we can't check them, and we would
4126          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4127          *
4128          * Because of this, we run inside INT_OFF, but use a special routine
4129          * which combines waitpid() and sigsuspend().
4130          * This is the reason why we need to have a handler for SIGCHLD:
4131          * SIG_DFL handler does not wake sigsuspend().
4132          */
4133         INT_OFF;
4134         if (block == DOWAIT_BLOCK_OR_SIG) {
4135                 pid = wait_block_or_sig(&status);
4136         } else {
4137                 int wait_flags = 0;
4138                 if (block == DOWAIT_NONBLOCK)
4139                         wait_flags = WNOHANG;
4140                 /* if job control is active, accept stopped processes too */
4141                 if (doing_jobctl)
4142                         wait_flags |= WUNTRACED;
4143                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4144                 pid = waitpid(-1, &status, wait_flags);
4145         }
4146         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4147                                 pid, status, errno, strerror(errno)));
4148         if (pid <= 0)
4149                 goto out;
4150
4151         thisjob = NULL;
4152         for (jp = curjob; jp; jp = jp->prev_job) {
4153                 int jobstate;
4154                 struct procstat *ps;
4155                 struct procstat *psend;
4156                 if (jp->state == JOBDONE)
4157                         continue;
4158                 jobstate = JOBDONE;
4159                 ps = jp->ps;
4160                 psend = ps + jp->nprocs;
4161                 do {
4162                         if (ps->ps_pid == pid) {
4163                                 TRACE(("Job %d: changing status of proc %d "
4164                                         "from 0x%x to 0x%x\n",
4165                                         jobno(jp), pid, ps->ps_status, status));
4166                                 ps->ps_status = status;
4167                                 thisjob = jp;
4168                         }
4169                         if (ps->ps_status == -1)
4170                                 jobstate = JOBRUNNING;
4171 #if JOBS
4172                         if (jobstate == JOBRUNNING)
4173                                 continue;
4174                         if (WIFSTOPPED(ps->ps_status)) {
4175                                 jp->stopstatus = ps->ps_status;
4176                                 jobstate = JOBSTOPPED;
4177                         }
4178 #endif
4179                 } while (++ps < psend);
4180                 if (!thisjob)
4181                         continue;
4182
4183                 /* Found the job where one of its processes changed its state.
4184                  * Is there at least one live and running process in this job? */
4185                 if (jobstate != JOBRUNNING) {
4186                         /* No. All live processes in the job are stopped
4187                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4188                          */
4189                         thisjob->changed = 1;
4190                         if (thisjob->state != jobstate) {
4191                                 TRACE(("Job %d: changing state from %d to %d\n",
4192                                         jobno(thisjob), thisjob->state, jobstate));
4193                                 thisjob->state = jobstate;
4194 #if JOBS
4195                                 if (jobstate == JOBSTOPPED)
4196                                         set_curjob(thisjob, CUR_STOPPED);
4197 #endif
4198                         }
4199                 }
4200                 goto out;
4201         }
4202         /* The process wasn't found in job list */
4203 #if JOBS
4204         if (!WIFSTOPPED(status))
4205                 jobless--;
4206 #endif
4207  out:
4208         INT_ON;
4209
4210         if (thisjob && thisjob == job) {
4211                 char s[48 + 1];
4212                 int len;
4213
4214                 len = sprint_status48(s, status, 1);
4215                 if (len) {
4216                         s[len] = '\n';
4217                         s[len + 1] = '\0';
4218                         out2str(s);
4219                 }
4220         }
4221         return pid;
4222 }
4223
4224 #if JOBS
4225 static void
4226 showjob(struct job *jp, int mode)
4227 {
4228         struct procstat *ps;
4229         struct procstat *psend;
4230         int col;
4231         int indent_col;
4232         char s[16 + 16 + 48];
4233         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4234
4235         ps = jp->ps;
4236
4237         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4238                 /* just output process (group) id of pipeline */
4239                 fprintf(out, "%d\n", ps->ps_pid);
4240                 return;
4241         }
4242
4243         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4244         indent_col = col;
4245
4246         if (jp == curjob)
4247                 s[col - 3] = '+';
4248         else if (curjob && jp == curjob->prev_job)
4249                 s[col - 3] = '-';
4250
4251         if (mode & SHOW_PIDS)
4252                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4253
4254         psend = ps + jp->nprocs;
4255
4256         if (jp->state == JOBRUNNING) {
4257                 strcpy(s + col, "Running");
4258                 col += sizeof("Running") - 1;
4259         } else {
4260                 int status = psend[-1].ps_status;
4261                 if (jp->state == JOBSTOPPED)
4262                         status = jp->stopstatus;
4263                 col += sprint_status48(s + col, status, 0);
4264         }
4265         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4266
4267         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4268          * or prints several "PID             | <cmdN>" lines,
4269          * depending on SHOW_PIDS bit.
4270          * We do not print status of individual processes
4271          * between PID and <cmdN>. bash does it, but not very well:
4272          * first line shows overall job status, not process status,
4273          * making it impossible to know 1st process status.
4274          */
4275         goto start;
4276         do {
4277                 /* for each process */
4278                 s[0] = '\0';
4279                 col = 33;
4280                 if (mode & SHOW_PIDS)
4281                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4282  start:
4283                 fprintf(out, "%s%*c%s%s",
4284                                 s,
4285                                 33 - col >= 0 ? 33 - col : 0, ' ',
4286                                 ps == jp->ps ? "" : "| ",
4287                                 ps->ps_cmd
4288                 );
4289         } while (++ps != psend);
4290         newline_and_flush(out);
4291
4292         jp->changed = 0;
4293
4294         if (jp->state == JOBDONE) {
4295                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4296                 freejob(jp);
4297         }
4298 }
4299
4300 /*
4301  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4302  * statuses have changed since the last call to showjobs.
4303  */
4304 static void
4305 showjobs(int mode)
4306 {
4307         struct job *jp;
4308
4309         TRACE(("showjobs(0x%x) called\n", mode));
4310
4311         /* Handle all finished jobs */
4312         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4313                 continue;
4314
4315         for (jp = curjob; jp; jp = jp->prev_job) {
4316                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4317                         showjob(jp, mode);
4318                 }
4319         }
4320 }
4321
4322 static int FAST_FUNC
4323 jobscmd(int argc UNUSED_PARAM, char **argv)
4324 {
4325         int mode, m;
4326
4327         mode = 0;
4328         while ((m = nextopt("lp")) != '\0') {
4329                 if (m == 'l')
4330                         mode |= SHOW_PIDS;
4331                 else
4332                         mode |= SHOW_ONLY_PGID;
4333         }
4334
4335         argv = argptr;
4336         if (*argv) {
4337                 do
4338                         showjob(getjob(*argv, 0), mode);
4339                 while (*++argv);
4340         } else {
4341                 showjobs(mode);
4342         }
4343
4344         return 0;
4345 }
4346 #endif /* JOBS */
4347
4348 /* Called only on finished or stopped jobs (no members are running) */
4349 static int
4350 getstatus(struct job *job)
4351 {
4352         int status;
4353         int retval;
4354         struct procstat *ps;
4355
4356         /* Fetch last member's status */
4357         ps = job->ps + job->nprocs - 1;
4358         status = ps->ps_status;
4359         if (pipefail) {
4360                 /* "set -o pipefail" mode: use last _nonzero_ status */
4361                 while (status == 0 && --ps >= job->ps)
4362                         status = ps->ps_status;
4363         }
4364
4365         retval = WEXITSTATUS(status);
4366         if (!WIFEXITED(status)) {
4367 #if JOBS
4368                 retval = WSTOPSIG(status);
4369                 if (!WIFSTOPPED(status))
4370 #endif
4371                 {
4372                         /* XXX: limits number of signals */
4373                         retval = WTERMSIG(status);
4374 #if JOBS
4375                         if (retval == SIGINT)
4376                                 job->sigint = 1;
4377 #endif
4378                 }
4379                 retval += 128;
4380         }
4381         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4382                 jobno(job), job->nprocs, status, retval));
4383         return retval;
4384 }
4385
4386 static int FAST_FUNC
4387 waitcmd(int argc UNUSED_PARAM, char **argv)
4388 {
4389         struct job *job;
4390         int retval;
4391         struct job *jp;
4392
4393         nextopt(nullstr);
4394         retval = 0;
4395
4396         argv = argptr;
4397         if (!*argv) {
4398                 /* wait for all jobs */
4399                 for (;;) {
4400                         jp = curjob;
4401                         while (1) {
4402                                 if (!jp) /* no running procs */
4403                                         goto ret;
4404                                 if (jp->state == JOBRUNNING)
4405                                         break;
4406                                 jp->waited = 1;
4407                                 jp = jp->prev_job;
4408                         }
4409         /* man bash:
4410          * "When bash is waiting for an asynchronous command via
4411          * the wait builtin, the reception of a signal for which a trap
4412          * has been set will cause the wait builtin to return immediately
4413          * with an exit status greater than 128, immediately after which
4414          * the trap is executed."
4415          */
4416                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4417         /* if child sends us a signal *and immediately exits*,
4418          * dowait() returns pid > 0. Check this case,
4419          * not "if (dowait() < 0)"!
4420          */
4421                         if (pending_sig)
4422                                 goto sigout;
4423                 }
4424         }
4425
4426         retval = 127;
4427         do {
4428                 if (**argv != '%') {
4429                         pid_t pid = number(*argv);
4430                         job = curjob;
4431                         while (1) {
4432                                 if (!job)
4433                                         goto repeat;
4434                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4435                                         break;
4436                                 job = job->prev_job;
4437                         }
4438                 } else {
4439                         job = getjob(*argv, 0);
4440                 }
4441                 /* loop until process terminated or stopped */
4442                 while (job->state == JOBRUNNING) {
4443                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4444                         if (pending_sig)
4445                                 goto sigout;
4446                 }
4447                 job->waited = 1;
4448                 retval = getstatus(job);
4449  repeat: ;
4450         } while (*++argv);
4451
4452  ret:
4453         return retval;
4454  sigout:
4455         retval = 128 + pending_sig;
4456         return retval;
4457 }
4458
4459 static struct job *
4460 growjobtab(void)
4461 {
4462         size_t len;
4463         ptrdiff_t offset;
4464         struct job *jp, *jq;
4465
4466         len = njobs * sizeof(*jp);
4467         jq = jobtab;
4468         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4469
4470         offset = (char *)jp - (char *)jq;
4471         if (offset) {
4472                 /* Relocate pointers */
4473                 size_t l = len;
4474
4475                 jq = (struct job *)((char *)jq + l);
4476                 while (l) {
4477                         l -= sizeof(*jp);
4478                         jq--;
4479 #define joff(p) ((struct job *)((char *)(p) + l))
4480 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4481                         if (joff(jp)->ps == &jq->ps0)
4482                                 jmove(joff(jp)->ps);
4483                         if (joff(jp)->prev_job)
4484                                 jmove(joff(jp)->prev_job);
4485                 }
4486                 if (curjob)
4487                         jmove(curjob);
4488 #undef joff
4489 #undef jmove
4490         }
4491
4492         njobs += 4;
4493         jobtab = jp;
4494         jp = (struct job *)((char *)jp + len);
4495         jq = jp + 3;
4496         do {
4497                 jq->used = 0;
4498         } while (--jq >= jp);
4499         return jp;
4500 }
4501
4502 /*
4503  * Return a new job structure.
4504  * Called with interrupts off.
4505  */
4506 static struct job *
4507 makejob(/*union node *node,*/ int nprocs)
4508 {
4509         int i;
4510         struct job *jp;
4511
4512         for (i = njobs, jp = jobtab; ; jp++) {
4513                 if (--i < 0) {
4514                         jp = growjobtab();
4515                         break;
4516                 }
4517                 if (jp->used == 0)
4518                         break;
4519                 if (jp->state != JOBDONE || !jp->waited)
4520                         continue;
4521 #if JOBS
4522                 if (doing_jobctl)
4523                         continue;
4524 #endif
4525                 freejob(jp);
4526                 break;
4527         }
4528         memset(jp, 0, sizeof(*jp));
4529 #if JOBS
4530         /* jp->jobctl is a bitfield.
4531          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4532         if (doing_jobctl)
4533                 jp->jobctl = 1;
4534 #endif
4535         jp->prev_job = curjob;
4536         curjob = jp;
4537         jp->used = 1;
4538         jp->ps = &jp->ps0;
4539         if (nprocs > 1) {
4540                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4541         }
4542         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4543                                 jobno(jp)));
4544         return jp;
4545 }
4546
4547 #if JOBS
4548 /*
4549  * Return a string identifying a command (to be printed by the
4550  * jobs command).
4551  */
4552 static char *cmdnextc;
4553
4554 static void
4555 cmdputs(const char *s)
4556 {
4557         static const char vstype[VSTYPE + 1][3] = {
4558                 "", "}", "-", "+", "?", "=",
4559                 "%", "%%", "#", "##"
4560                 IF_BASH_SUBSTR(, ":")
4561                 IF_BASH_PATTERN_SUBST(, "/", "//")
4562         };
4563
4564         const char *p, *str;
4565         char cc[2];
4566         char *nextc;
4567         unsigned char c;
4568         unsigned char subtype = 0;
4569         int quoted = 0;
4570
4571         cc[1] = '\0';
4572         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4573         p = s;
4574         while ((c = *p++) != '\0') {
4575                 str = NULL;
4576                 switch (c) {
4577                 case CTLESC:
4578                         c = *p++;
4579                         break;
4580                 case CTLVAR:
4581                         subtype = *p++;
4582                         if ((subtype & VSTYPE) == VSLENGTH)
4583                                 str = "${#";
4584                         else
4585                                 str = "${";
4586                         goto dostr;
4587                 case CTLENDVAR:
4588                         str = "\"}" + !(quoted & 1);
4589                         quoted >>= 1;
4590                         subtype = 0;
4591                         goto dostr;
4592                 case CTLBACKQ:
4593                         str = "$(...)";
4594                         goto dostr;
4595 #if ENABLE_FEATURE_SH_MATH
4596                 case CTLARI:
4597                         str = "$((";
4598                         goto dostr;
4599                 case CTLENDARI:
4600                         str = "))";
4601                         goto dostr;
4602 #endif
4603                 case CTLQUOTEMARK:
4604                         quoted ^= 1;
4605                         c = '"';
4606                         break;
4607                 case '=':
4608                         if (subtype == 0)
4609                                 break;
4610                         if ((subtype & VSTYPE) != VSNORMAL)
4611                                 quoted <<= 1;
4612                         str = vstype[subtype & VSTYPE];
4613                         if (subtype & VSNUL)
4614                                 c = ':';
4615                         else
4616                                 goto checkstr;
4617                         break;
4618                 case '\'':
4619                 case '\\':
4620                 case '"':
4621                 case '$':
4622                         /* These can only happen inside quotes */
4623                         cc[0] = c;
4624                         str = cc;
4625                         c = '\\';
4626                         break;
4627                 default:
4628                         break;
4629                 }
4630                 USTPUTC(c, nextc);
4631  checkstr:
4632                 if (!str)
4633                         continue;
4634  dostr:
4635                 while ((c = *str++) != '\0') {
4636                         USTPUTC(c, nextc);
4637                 }
4638         } /* while *p++ not NUL */
4639
4640         if (quoted & 1) {
4641                 USTPUTC('"', nextc);
4642         }
4643         *nextc = 0;
4644         cmdnextc = nextc;
4645 }
4646
4647 /* cmdtxt() and cmdlist() call each other */
4648 static void cmdtxt(union node *n);
4649
4650 static void
4651 cmdlist(union node *np, int sep)
4652 {
4653         for (; np; np = np->narg.next) {
4654                 if (!sep)
4655                         cmdputs(" ");
4656                 cmdtxt(np);
4657                 if (sep && np->narg.next)
4658                         cmdputs(" ");
4659         }
4660 }
4661
4662 static void
4663 cmdtxt(union node *n)
4664 {
4665         union node *np;
4666         struct nodelist *lp;
4667         const char *p;
4668
4669         if (!n)
4670                 return;
4671         switch (n->type) {
4672         default:
4673 #if DEBUG
4674                 abort();
4675 #endif
4676         case NPIPE:
4677                 lp = n->npipe.cmdlist;
4678                 for (;;) {
4679                         cmdtxt(lp->n);
4680                         lp = lp->next;
4681                         if (!lp)
4682                                 break;
4683                         cmdputs(" | ");
4684                 }
4685                 break;
4686         case NSEMI:
4687                 p = "; ";
4688                 goto binop;
4689         case NAND:
4690                 p = " && ";
4691                 goto binop;
4692         case NOR:
4693                 p = " || ";
4694  binop:
4695                 cmdtxt(n->nbinary.ch1);
4696                 cmdputs(p);
4697                 n = n->nbinary.ch2;
4698                 goto donode;
4699         case NREDIR:
4700         case NBACKGND:
4701                 n = n->nredir.n;
4702                 goto donode;
4703         case NNOT:
4704                 cmdputs("!");
4705                 n = n->nnot.com;
4706  donode:
4707                 cmdtxt(n);
4708                 break;
4709         case NIF:
4710                 cmdputs("if ");
4711                 cmdtxt(n->nif.test);
4712                 cmdputs("; then ");
4713                 if (n->nif.elsepart) {
4714                         cmdtxt(n->nif.ifpart);
4715                         cmdputs("; else ");
4716                         n = n->nif.elsepart;
4717                 } else {
4718                         n = n->nif.ifpart;
4719                 }
4720                 p = "; fi";
4721                 goto dotail;
4722         case NSUBSHELL:
4723                 cmdputs("(");
4724                 n = n->nredir.n;
4725                 p = ")";
4726                 goto dotail;
4727         case NWHILE:
4728                 p = "while ";
4729                 goto until;
4730         case NUNTIL:
4731                 p = "until ";
4732  until:
4733                 cmdputs(p);
4734                 cmdtxt(n->nbinary.ch1);
4735                 n = n->nbinary.ch2;
4736                 p = "; done";
4737  dodo:
4738                 cmdputs("; do ");
4739  dotail:
4740                 cmdtxt(n);
4741                 goto dotail2;
4742         case NFOR:
4743                 cmdputs("for ");
4744                 cmdputs(n->nfor.var);
4745                 cmdputs(" in ");
4746                 cmdlist(n->nfor.args, 1);
4747                 n = n->nfor.body;
4748                 p = "; done";
4749                 goto dodo;
4750         case NDEFUN:
4751                 cmdputs(n->narg.text);
4752                 p = "() { ... }";
4753                 goto dotail2;
4754         case NCMD:
4755                 cmdlist(n->ncmd.args, 1);
4756                 cmdlist(n->ncmd.redirect, 0);
4757                 break;
4758         case NARG:
4759                 p = n->narg.text;
4760  dotail2:
4761                 cmdputs(p);
4762                 break;
4763         case NHERE:
4764         case NXHERE:
4765                 p = "<<...";
4766                 goto dotail2;
4767         case NCASE:
4768                 cmdputs("case ");
4769                 cmdputs(n->ncase.expr->narg.text);
4770                 cmdputs(" in ");
4771                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4772                         cmdtxt(np->nclist.pattern);
4773                         cmdputs(") ");
4774                         cmdtxt(np->nclist.body);
4775                         cmdputs(";; ");
4776                 }
4777                 p = "esac";
4778                 goto dotail2;
4779         case NTO:
4780                 p = ">";
4781                 goto redir;
4782         case NCLOBBER:
4783                 p = ">|";
4784                 goto redir;
4785         case NAPPEND:
4786                 p = ">>";
4787                 goto redir;
4788 #if BASH_REDIR_OUTPUT
4789         case NTO2:
4790 #endif
4791         case NTOFD:
4792                 p = ">&";
4793                 goto redir;
4794         case NFROM:
4795                 p = "<";
4796                 goto redir;
4797         case NFROMFD:
4798                 p = "<&";
4799                 goto redir;
4800         case NFROMTO:
4801                 p = "<>";
4802  redir:
4803                 cmdputs(utoa(n->nfile.fd));
4804                 cmdputs(p);
4805                 if (n->type == NTOFD || n->type == NFROMFD) {
4806                         cmdputs(utoa(n->ndup.dupfd));
4807                         break;
4808                 }
4809                 n = n->nfile.fname;
4810                 goto donode;
4811         }
4812 }
4813
4814 static char *
4815 commandtext(union node *n)
4816 {
4817         char *name;
4818
4819         STARTSTACKSTR(cmdnextc);
4820         cmdtxt(n);
4821         name = stackblock();
4822         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4823         return ckstrdup(name);
4824 }
4825 #endif /* JOBS */
4826
4827 /*
4828  * Fork off a subshell.  If we are doing job control, give the subshell its
4829  * own process group.  Jp is a job structure that the job is to be added to.
4830  * N is the command that will be evaluated by the child.  Both jp and n may
4831  * be NULL.  The mode parameter can be one of the following:
4832  *      FORK_FG - Fork off a foreground process.
4833  *      FORK_BG - Fork off a background process.
4834  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4835  *                   process group even if job control is on.
4836  *
4837  * When job control is turned off, background processes have their standard
4838  * input redirected to /dev/null (except for the second and later processes
4839  * in a pipeline).
4840  *
4841  * Called with interrupts off.
4842  */
4843 /*
4844  * Clear traps on a fork.
4845  */
4846 static void
4847 clear_traps(void)
4848 {
4849         char **tp;
4850
4851         INT_OFF;
4852         for (tp = trap; tp < &trap[NSIG]; tp++) {
4853                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4854                         if (trap_ptr == trap)
4855                                 free(*tp);
4856                         /* else: it "belongs" to trap_ptr vector, don't free */
4857                         *tp = NULL;
4858                         if ((tp - trap) != 0)
4859                                 setsignal(tp - trap);
4860                 }
4861         }
4862         may_have_traps = 0;
4863         INT_ON;
4864 }
4865
4866 /* Lives far away from here, needed for forkchild */
4867 static void closescript(void);
4868
4869 /* Called after fork(), in child */
4870 /* jp and n are NULL when called by openhere() for heredoc support */
4871 static NOINLINE void
4872 forkchild(struct job *jp, union node *n, int mode)
4873 {
4874         int oldlvl;
4875
4876         TRACE(("Child shell %d\n", getpid()));
4877         oldlvl = shlvl;
4878         shlvl++;
4879
4880         /* man bash: "Non-builtin commands run by bash have signal handlers
4881          * set to the values inherited by the shell from its parent".
4882          * Do we do it correctly? */
4883
4884         closescript();
4885
4886         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4887          && n && n->type == NCMD        /* is it single cmd? */
4888         /* && n->ncmd.args->type == NARG - always true? */
4889          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4890          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4891         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4892         ) {
4893                 TRACE(("Trap hack\n"));
4894                 /* Awful hack for `trap` or $(trap).
4895                  *
4896                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4897                  * contains an example where "trap" is executed in a subshell:
4898                  *
4899                  * save_traps=$(trap)
4900                  * ...
4901                  * eval "$save_traps"
4902                  *
4903                  * Standard does not say that "trap" in subshell shall print
4904                  * parent shell's traps. It only says that its output
4905                  * must have suitable form, but then, in the above example
4906                  * (which is not supposed to be normative), it implies that.
4907                  *
4908                  * bash (and probably other shell) does implement it
4909                  * (traps are reset to defaults, but "trap" still shows them),
4910                  * but as a result, "trap" logic is hopelessly messed up:
4911                  *
4912                  * # trap
4913                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4914                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4915                  * # true | trap   <--- trap is in subshell - no output (ditto)
4916                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4917                  * trap -- 'echo Ho' SIGWINCH
4918                  * # echo `(trap)`         <--- in subshell in subshell - output
4919                  * trap -- 'echo Ho' SIGWINCH
4920                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4921                  * trap -- 'echo Ho' SIGWINCH
4922                  *
4923                  * The rules when to forget and when to not forget traps
4924                  * get really complex and nonsensical.
4925                  *
4926                  * Our solution: ONLY bare $(trap) or `trap` is special.
4927                  */
4928                 /* Save trap handler strings for trap builtin to print */
4929                 trap_ptr = xmemdup(trap, sizeof(trap));
4930                 /* Fall through into clearing traps */
4931         }
4932         clear_traps();
4933 #if JOBS
4934         /* do job control only in root shell */
4935         doing_jobctl = 0;
4936         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4937                 pid_t pgrp;
4938
4939                 if (jp->nprocs == 0)
4940                         pgrp = getpid();
4941                 else
4942                         pgrp = jp->ps[0].ps_pid;
4943                 /* this can fail because we are doing it in the parent also */
4944                 setpgid(0, pgrp);
4945                 if (mode == FORK_FG)
4946                         xtcsetpgrp(ttyfd, pgrp);
4947                 setsignal(SIGTSTP);
4948                 setsignal(SIGTTOU);
4949         } else
4950 #endif
4951         if (mode == FORK_BG) {
4952                 /* man bash: "When job control is not in effect,
4953                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4954                 ignoresig(SIGINT);
4955                 ignoresig(SIGQUIT);
4956                 if (jp->nprocs == 0) {
4957                         close(0);
4958                         if (open(bb_dev_null, O_RDONLY) != 0)
4959                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4960                 }
4961         }
4962         if (oldlvl == 0) {
4963                 if (iflag) { /* why if iflag only? */
4964                         setsignal(SIGINT);
4965                         setsignal(SIGTERM);
4966                 }
4967                 /* man bash:
4968                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4969                  * commands run by bash have signal handlers
4970                  * set to the values inherited by the shell
4971                  * from its parent".
4972                  * Take care of the second rule: */
4973                 setsignal(SIGQUIT);
4974         }
4975 #if JOBS
4976         if (n && n->type == NCMD
4977          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4978         ) {
4979                 TRACE(("Job hack\n"));
4980                 /* "jobs": we do not want to clear job list for it,
4981                  * instead we remove only _its_ own_ job from job list.
4982                  * This makes "jobs .... | cat" more useful.
4983                  */
4984                 freejob(curjob);
4985                 return;
4986         }
4987 #endif
4988         for (jp = curjob; jp; jp = jp->prev_job)
4989                 freejob(jp);
4990         jobless = 0;
4991 }
4992
4993 /* Called after fork(), in parent */
4994 #if !JOBS
4995 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4996 #endif
4997 static void
4998 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4999 {
5000         TRACE(("In parent shell: child = %d\n", pid));
5001         if (!jp) {
5002                 /* jp is NULL when called by openhere() for heredoc support */
5003                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5004                         continue;
5005                 jobless++;
5006                 return;
5007         }
5008 #if JOBS
5009         if (mode != FORK_NOJOB && jp->jobctl) {
5010                 int pgrp;
5011
5012                 if (jp->nprocs == 0)
5013                         pgrp = pid;
5014                 else
5015                         pgrp = jp->ps[0].ps_pid;
5016                 /* This can fail because we are doing it in the child also */
5017                 setpgid(pid, pgrp);
5018         }
5019 #endif
5020         if (mode == FORK_BG) {
5021                 backgndpid = pid;               /* set $! */
5022                 set_curjob(jp, CUR_RUNNING);
5023         }
5024         if (jp) {
5025                 struct procstat *ps = &jp->ps[jp->nprocs++];
5026                 ps->ps_pid = pid;
5027                 ps->ps_status = -1;
5028                 ps->ps_cmd = nullstr;
5029 #if JOBS
5030                 if (doing_jobctl && n)
5031                         ps->ps_cmd = commandtext(n);
5032 #endif
5033         }
5034 }
5035
5036 /* jp and n are NULL when called by openhere() for heredoc support */
5037 static int
5038 forkshell(struct job *jp, union node *n, int mode)
5039 {
5040         int pid;
5041
5042         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5043         pid = fork();
5044         if (pid < 0) {
5045                 TRACE(("Fork failed, errno=%d", errno));
5046                 if (jp)
5047                         freejob(jp);
5048                 ash_msg_and_raise_error("can't fork");
5049         }
5050         if (pid == 0) {
5051                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5052                 forkchild(jp, n, mode);
5053         } else {
5054                 forkparent(jp, n, mode, pid);
5055         }
5056         return pid;
5057 }
5058
5059 /*
5060  * Wait for job to finish.
5061  *
5062  * Under job control we have the problem that while a child process
5063  * is running interrupts generated by the user are sent to the child
5064  * but not to the shell.  This means that an infinite loop started by
5065  * an interactive user may be hard to kill.  With job control turned off,
5066  * an interactive user may place an interactive program inside a loop.
5067  * If the interactive program catches interrupts, the user doesn't want
5068  * these interrupts to also abort the loop.  The approach we take here
5069  * is to have the shell ignore interrupt signals while waiting for a
5070  * foreground process to terminate, and then send itself an interrupt
5071  * signal if the child process was terminated by an interrupt signal.
5072  * Unfortunately, some programs want to do a bit of cleanup and then
5073  * exit on interrupt; unless these processes terminate themselves by
5074  * sending a signal to themselves (instead of calling exit) they will
5075  * confuse this approach.
5076  *
5077  * Called with interrupts off.
5078  */
5079 static int
5080 waitforjob(struct job *jp)
5081 {
5082         int st;
5083
5084         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5085
5086         INT_OFF;
5087         while (jp->state == JOBRUNNING) {
5088                 /* In non-interactive shells, we _can_ get
5089                  * a keyboard signal here and be EINTRed,
5090                  * but we just loop back, waiting for command to complete.
5091                  *
5092                  * man bash:
5093                  * "If bash is waiting for a command to complete and receives
5094                  * a signal for which a trap has been set, the trap
5095                  * will not be executed until the command completes."
5096                  *
5097                  * Reality is that even if trap is not set, bash
5098                  * will not act on the signal until command completes.
5099                  * Try this. sleep5intoff.c:
5100                  * #include <signal.h>
5101                  * #include <unistd.h>
5102                  * int main() {
5103                  *         sigset_t set;
5104                  *         sigemptyset(&set);
5105                  *         sigaddset(&set, SIGINT);
5106                  *         sigaddset(&set, SIGQUIT);
5107                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5108                  *         sleep(5);
5109                  *         return 0;
5110                  * }
5111                  * $ bash -c './sleep5intoff; echo hi'
5112                  * ^C^C^C^C <--- pressing ^C once a second
5113                  * $ _
5114                  * $ bash -c './sleep5intoff; echo hi'
5115                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5116                  * $ _
5117                  */
5118                 dowait(DOWAIT_BLOCK, jp);
5119         }
5120         INT_ON;
5121
5122         st = getstatus(jp);
5123 #if JOBS
5124         if (jp->jobctl) {
5125                 xtcsetpgrp(ttyfd, rootpid);
5126                 restore_tty_if_stopped_or_signaled(jp);
5127
5128                 /*
5129                  * This is truly gross.
5130                  * If we're doing job control, then we did a TIOCSPGRP which
5131                  * caused us (the shell) to no longer be in the controlling
5132                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5133                  * intuit from the subprocess exit status whether a SIGINT
5134                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5135                  */
5136                 if (jp->sigint) /* TODO: do the same with all signals */
5137                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5138         }
5139         if (jp->state == JOBDONE)
5140 #endif
5141                 freejob(jp);
5142         return st;
5143 }
5144
5145 /*
5146  * return 1 if there are stopped jobs, otherwise 0
5147  */
5148 static int
5149 stoppedjobs(void)
5150 {
5151         struct job *jp;
5152         int retval;
5153
5154         retval = 0;
5155         if (job_warning)
5156                 goto out;
5157         jp = curjob;
5158         if (jp && jp->state == JOBSTOPPED) {
5159                 out2str("You have stopped jobs.\n");
5160                 job_warning = 2;
5161                 retval++;
5162         }
5163  out:
5164         return retval;
5165 }
5166
5167
5168 /*
5169  * Code for dealing with input/output redirection.
5170  */
5171
5172 #undef EMPTY
5173 #undef CLOSED
5174 #define EMPTY -2                /* marks an unused slot in redirtab */
5175 #define CLOSED -3               /* marks a slot of previously-closed fd */
5176
5177 /*
5178  * Handle here documents.  Normally we fork off a process to write the
5179  * data to a pipe.  If the document is short, we can stuff the data in
5180  * the pipe without forking.
5181  */
5182 /* openhere needs this forward reference */
5183 static void expandhere(union node *arg, int fd);
5184 static int
5185 openhere(union node *redir)
5186 {
5187         int pip[2];
5188         size_t len = 0;
5189
5190         if (pipe(pip) < 0)
5191                 ash_msg_and_raise_error("pipe call failed");
5192         if (redir->type == NHERE) {
5193                 len = strlen(redir->nhere.doc->narg.text);
5194                 if (len <= PIPE_BUF) {
5195                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5196                         goto out;
5197                 }
5198         }
5199         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5200                 /* child */
5201                 close(pip[0]);
5202                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5203                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5204                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5205                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5206                 signal(SIGPIPE, SIG_DFL);
5207                 if (redir->type == NHERE)
5208                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5209                 else /* NXHERE */
5210                         expandhere(redir->nhere.doc, pip[1]);
5211                 _exit(EXIT_SUCCESS);
5212         }
5213  out:
5214         close(pip[1]);
5215         return pip[0];
5216 }
5217
5218 static int
5219 openredirect(union node *redir)
5220 {
5221         struct stat sb;
5222         char *fname;
5223         int f;
5224
5225         switch (redir->nfile.type) {
5226 /* Can't happen, our single caller does this itself */
5227 //      case NTOFD:
5228 //      case NFROMFD:
5229 //              return -1;
5230         case NHERE:
5231         case NXHERE:
5232                 return openhere(redir);
5233         }
5234
5235         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5236          * allocated space. Do it only when we know it is safe.
5237          */
5238         fname = redir->nfile.expfname;
5239
5240         switch (redir->nfile.type) {
5241         default:
5242 #if DEBUG
5243                 abort();
5244 #endif
5245         case NFROM:
5246                 f = open(fname, O_RDONLY);
5247                 if (f < 0)
5248                         goto eopen;
5249                 break;
5250         case NFROMTO:
5251                 f = open(fname, O_RDWR|O_CREAT, 0666);
5252                 if (f < 0)
5253                         goto ecreate;
5254                 break;
5255         case NTO:
5256 #if BASH_REDIR_OUTPUT
5257         case NTO2:
5258 #endif
5259                 /* Take care of noclobber mode. */
5260                 if (Cflag) {
5261                         if (stat(fname, &sb) < 0) {
5262                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5263                                 if (f < 0)
5264                                         goto ecreate;
5265                         } else if (!S_ISREG(sb.st_mode)) {
5266                                 f = open(fname, O_WRONLY, 0666);
5267                                 if (f < 0)
5268                                         goto ecreate;
5269                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5270                                         close(f);
5271                                         errno = EEXIST;
5272                                         goto ecreate;
5273                                 }
5274                         } else {
5275                                 errno = EEXIST;
5276                                 goto ecreate;
5277                         }
5278                         break;
5279                 }
5280                 /* FALLTHROUGH */
5281         case NCLOBBER:
5282                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5283                 if (f < 0)
5284                         goto ecreate;
5285                 break;
5286         case NAPPEND:
5287                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5288                 if (f < 0)
5289                         goto ecreate;
5290                 break;
5291         }
5292
5293         return f;
5294  ecreate:
5295         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5296  eopen:
5297         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5298 }
5299
5300 /*
5301  * Copy a file descriptor to be >= 10. Throws exception on error.
5302  */
5303 static int
5304 savefd(int from)
5305 {
5306         int newfd;
5307         int err;
5308
5309         newfd = fcntl(from, F_DUPFD, 10);
5310         err = newfd < 0 ? errno : 0;
5311         if (err != EBADF) {
5312                 if (err)
5313                         ash_msg_and_raise_error("%d: %m", from);
5314                 close(from);
5315                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5316         }
5317
5318         return newfd;
5319 }
5320 static int
5321 dup2_or_raise(int from, int to)
5322 {
5323         int newfd;
5324
5325         newfd = (from != to) ? dup2(from, to) : to;
5326         if (newfd < 0) {
5327                 /* Happens when source fd is not open: try "echo >&99" */
5328                 ash_msg_and_raise_error("%d: %m", from);
5329         }
5330         return newfd;
5331 }
5332
5333 /* Struct def and variable are moved down to the first usage site */
5334 struct two_fd_t {
5335         int orig, copy;
5336 };
5337 struct redirtab {
5338         struct redirtab *next;
5339         int pair_count;
5340         struct two_fd_t two_fd[];
5341 };
5342 #define redirlist (G_var.redirlist)
5343 enum {
5344         COPYFD_RESTORE = (int)~(INT_MAX),
5345 };
5346
5347 static int
5348 need_to_remember(struct redirtab *rp, int fd)
5349 {
5350         int i;
5351
5352         if (!rp) /* remembering was not requested */
5353                 return 0;
5354
5355         for (i = 0; i < rp->pair_count; i++) {
5356                 if (rp->two_fd[i].orig == fd) {
5357                         /* already remembered */
5358                         return 0;
5359                 }
5360         }
5361         return 1;
5362 }
5363
5364 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5365 static int
5366 is_hidden_fd(struct redirtab *rp, int fd)
5367 {
5368         int i;
5369         struct parsefile *pf;
5370
5371         if (fd == -1)
5372                 return 0;
5373         /* Check open scripts' fds */
5374         pf = g_parsefile;
5375         while (pf) {
5376                 /* We skip pf_fd == 0 case because of the following case:
5377                  * $ ash  # running ash interactively
5378                  * $ . ./script.sh
5379                  * and in script.sh: "exec 9>&0".
5380                  * Even though top-level pf_fd _is_ 0,
5381                  * it's still ok to use it: "read" builtin uses it,
5382                  * why should we cripple "exec" builtin?
5383                  */
5384                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5385                         return 1;
5386                 }
5387                 pf = pf->prev;
5388         }
5389
5390         if (!rp)
5391                 return 0;
5392         /* Check saved fds of redirects */
5393         fd |= COPYFD_RESTORE;
5394         for (i = 0; i < rp->pair_count; i++) {
5395                 if (rp->two_fd[i].copy == fd) {
5396                         return 1;
5397                 }
5398         }
5399         return 0;
5400 }
5401
5402 /*
5403  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5404  * old file descriptors are stashed away so that the redirection can be
5405  * undone by calling popredir.
5406  */
5407 /* flags passed to redirect */
5408 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5409 #define REDIR_SAVEFD2 03        /* set preverrout */
5410 static void
5411 redirect(union node *redir, int flags)
5412 {
5413         struct redirtab *sv;
5414         int sv_pos;
5415         int i;
5416         int fd;
5417         int newfd;
5418         int copied_fd2 = -1;
5419
5420         if (!redir) {
5421                 return;
5422         }
5423
5424         sv = NULL;
5425         sv_pos = 0;
5426         INT_OFF;
5427         if (flags & REDIR_PUSH) {
5428                 union node *tmp = redir;
5429                 do {
5430                         sv_pos++;
5431 #if BASH_REDIR_OUTPUT
5432                         if (tmp->nfile.type == NTO2)
5433                                 sv_pos++;
5434 #endif
5435                         tmp = tmp->nfile.next;
5436                 } while (tmp);
5437                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5438                 sv->next = redirlist;
5439                 sv->pair_count = sv_pos;
5440                 redirlist = sv;
5441                 while (sv_pos > 0) {
5442                         sv_pos--;
5443                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5444                 }
5445         }
5446
5447         do {
5448                 int right_fd = -1;
5449                 fd = redir->nfile.fd;
5450                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5451                         right_fd = redir->ndup.dupfd;
5452                         //bb_error_msg("doing %d > %d", fd, right_fd);
5453                         /* redirect from/to same file descriptor? */
5454                         if (right_fd == fd)
5455                                 continue;
5456                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5457                         if (is_hidden_fd(sv, right_fd)) {
5458                                 errno = EBADF; /* as if it is closed */
5459                                 ash_msg_and_raise_error("%d: %m", right_fd);
5460                         }
5461                         newfd = -1;
5462                 } else {
5463                         newfd = openredirect(redir); /* always >= 0 */
5464                         if (fd == newfd) {
5465                                 /* Descriptor wasn't open before redirect.
5466                                  * Mark it for close in the future */
5467                                 if (need_to_remember(sv, fd)) {
5468                                         goto remember_to_close;
5469                                 }
5470                                 continue;
5471                         }
5472                 }
5473 #if BASH_REDIR_OUTPUT
5474  redirect_more:
5475 #endif
5476                 if (need_to_remember(sv, fd)) {
5477                         /* Copy old descriptor */
5478                         /* Careful to not accidentally "save"
5479                          * to the same fd as right side fd in N>&M */
5480                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5481 #if defined(F_DUPFD_CLOEXEC)
5482                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5483 #else
5484                         i = fcntl(fd, F_DUPFD, minfd);
5485 #endif
5486                         if (i == -1) {
5487                                 i = errno;
5488                                 if (i != EBADF) {
5489                                         /* Strange error (e.g. "too many files" EMFILE?) */
5490                                         if (newfd >= 0)
5491                                                 close(newfd);
5492                                         errno = i;
5493                                         ash_msg_and_raise_error("%d: %m", fd);
5494                                         /* NOTREACHED */
5495                                 }
5496                                 /* EBADF: it is not open - good, remember to close it */
5497  remember_to_close:
5498                                 i = CLOSED;
5499                         } else { /* fd is open, save its copy */
5500 #if !defined(F_DUPFD_CLOEXEC)
5501                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5502 #endif
5503                                 /* "exec fd>&-" should not close fds
5504                                  * which point to script file(s).
5505                                  * Force them to be restored afterwards */
5506                                 if (is_hidden_fd(sv, fd))
5507                                         i |= COPYFD_RESTORE;
5508                         }
5509                         if (fd == 2)
5510                                 copied_fd2 = i;
5511                         sv->two_fd[sv_pos].orig = fd;
5512                         sv->two_fd[sv_pos].copy = i;
5513                         sv_pos++;
5514                 }
5515                 if (newfd < 0) {
5516                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5517                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5518                                 /* Don't want to trigger debugging */
5519                                 if (fd != -1)
5520                                         close(fd);
5521                         } else {
5522                                 dup2_or_raise(redir->ndup.dupfd, fd);
5523                         }
5524                 } else if (fd != newfd) { /* move newfd to fd */
5525                         dup2_or_raise(newfd, fd);
5526 #if BASH_REDIR_OUTPUT
5527                         if (!(redir->nfile.type == NTO2 && fd == 2))
5528 #endif
5529                                 close(newfd);
5530                 }
5531 #if BASH_REDIR_OUTPUT
5532                 if (redir->nfile.type == NTO2 && fd == 1) {
5533                         /* We already redirected it to fd 1, now copy it to 2 */
5534                         newfd = 1;
5535                         fd = 2;
5536                         goto redirect_more;
5537                 }
5538 #endif
5539         } while ((redir = redir->nfile.next) != NULL);
5540
5541         INT_ON;
5542         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5543                 preverrout_fd = copied_fd2;
5544 }
5545
5546 /*
5547  * Undo the effects of the last redirection.
5548  */
5549 static void
5550 popredir(int drop, int restore)
5551 {
5552         struct redirtab *rp;
5553         int i;
5554
5555         if (redirlist == NULL)
5556                 return;
5557         INT_OFF;
5558         rp = redirlist;
5559         for (i = 0; i < rp->pair_count; i++) {
5560                 int fd = rp->two_fd[i].orig;
5561                 int copy = rp->two_fd[i].copy;
5562                 if (copy == CLOSED) {
5563                         if (!drop)
5564                                 close(fd);
5565                         continue;
5566                 }
5567                 if (copy != EMPTY) {
5568                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5569                                 copy &= ~COPYFD_RESTORE;
5570                                 /*close(fd);*/
5571                                 dup2_or_raise(copy, fd);
5572                         }
5573                         close(copy & ~COPYFD_RESTORE);
5574                 }
5575         }
5576         redirlist = rp->next;
5577         free(rp);
5578         INT_ON;
5579 }
5580
5581 /*
5582  * Undo all redirections.  Called on error or interrupt.
5583  */
5584
5585 static int
5586 redirectsafe(union node *redir, int flags)
5587 {
5588         int err;
5589         volatile int saveint;
5590         struct jmploc *volatile savehandler = exception_handler;
5591         struct jmploc jmploc;
5592
5593         SAVE_INT(saveint);
5594         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5595         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5596         if (!err) {
5597                 exception_handler = &jmploc;
5598                 redirect(redir, flags);
5599         }
5600         exception_handler = savehandler;
5601         if (err && exception_type != EXERROR)
5602                 longjmp(exception_handler->loc, 1);
5603         RESTORE_INT(saveint);
5604         return err;
5605 }
5606
5607
5608 /* ============ Routines to expand arguments to commands
5609  *
5610  * We have to deal with backquotes, shell variables, and file metacharacters.
5611  */
5612
5613 #if ENABLE_FEATURE_SH_MATH
5614 static arith_t
5615 ash_arith(const char *s)
5616 {
5617         arith_state_t math_state;
5618         arith_t result;
5619
5620         math_state.lookupvar = lookupvar;
5621         math_state.setvar    = setvar0;
5622         //math_state.endofname = endofname;
5623
5624         INT_OFF;
5625         result = arith(&math_state, s);
5626         if (math_state.errmsg)
5627                 ash_msg_and_raise_error(math_state.errmsg);
5628         INT_ON;
5629
5630         return result;
5631 }
5632 #endif
5633
5634 /*
5635  * expandarg flags
5636  */
5637 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5638 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5639 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5640 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5641 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5642  * POSIX says for this case:
5643  *  Pathname expansion shall not be performed on the word by a
5644  *  non-interactive shell; an interactive shell may perform it, but shall
5645  *  do so only when the expansion would result in one word.
5646  * Currently, our code complies to the above rule by never globbing
5647  * redirection filenames.
5648  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5649  * (this means that on a typical Linux distro, bash almost always
5650  * performs globbing, and thus diverges from what we do).
5651  */
5652 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5653 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5654 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5655 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5656 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5657 /*
5658  * rmescape() flags
5659  */
5660 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5661 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5662 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5663 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5664 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5665
5666 /* Add CTLESC when necessary. */
5667 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5668 /* Do not skip NUL characters. */
5669 #define QUOTES_KEEPNUL EXP_TILDE
5670
5671 /*
5672  * Structure specifying which parts of the string should be searched
5673  * for IFS characters.
5674  */
5675 struct ifsregion {
5676         struct ifsregion *next; /* next region in list */
5677         int begoff;             /* offset of start of region */
5678         int endoff;             /* offset of end of region */
5679         int nulonly;            /* search for nul bytes only */
5680 };
5681
5682 struct arglist {
5683         struct strlist *list;
5684         struct strlist **lastp;
5685 };
5686
5687 /* output of current string */
5688 static char *expdest;
5689 /* list of back quote expressions */
5690 static struct nodelist *argbackq;
5691 /* first struct in list of ifs regions */
5692 static struct ifsregion ifsfirst;
5693 /* last struct in list */
5694 static struct ifsregion *ifslastp;
5695 /* holds expanded arg list */
5696 static struct arglist exparg;
5697
5698 /*
5699  * Our own itoa().
5700  */
5701 #if !ENABLE_FEATURE_SH_MATH
5702 /* cvtnum() is used even if math support is off (to prepare $? values and such) */
5703 typedef long arith_t;
5704 # define ARITH_FMT "%ld"
5705 #endif
5706 static int
5707 cvtnum(arith_t num)
5708 {
5709         int len;
5710
5711         expdest = makestrspace(sizeof(arith_t)*3 + 2, expdest);
5712         len = fmtstr(expdest, sizeof(arith_t)*3 + 2, ARITH_FMT, num);
5713         STADJUST(len, expdest);
5714         return len;
5715 }
5716
5717 /*
5718  * Break the argument string into pieces based upon IFS and add the
5719  * strings to the argument list.  The regions of the string to be
5720  * searched for IFS characters have been stored by recordregion.
5721  */
5722 static void
5723 ifsbreakup(char *string, struct arglist *arglist)
5724 {
5725         struct ifsregion *ifsp;
5726         struct strlist *sp;
5727         char *start;
5728         char *p;
5729         char *q;
5730         const char *ifs, *realifs;
5731         int ifsspc;
5732         int nulonly;
5733
5734         start = string;
5735         if (ifslastp != NULL) {
5736                 ifsspc = 0;
5737                 nulonly = 0;
5738                 realifs = ifsset() ? ifsval() : defifs;
5739                 ifsp = &ifsfirst;
5740                 do {
5741                         p = string + ifsp->begoff;
5742                         nulonly = ifsp->nulonly;
5743                         ifs = nulonly ? nullstr : realifs;
5744                         ifsspc = 0;
5745                         while (p < string + ifsp->endoff) {
5746                                 q = p;
5747                                 if ((unsigned char)*p == CTLESC)
5748                                         p++;
5749                                 if (!strchr(ifs, *p)) {
5750                                         p++;
5751                                         continue;
5752                                 }
5753                                 if (!nulonly)
5754                                         ifsspc = (strchr(defifs, *p) != NULL);
5755                                 /* Ignore IFS whitespace at start */
5756                                 if (q == start && ifsspc) {
5757                                         p++;
5758                                         start = p;
5759                                         continue;
5760                                 }
5761                                 *q = '\0';
5762                                 sp = stzalloc(sizeof(*sp));
5763                                 sp->text = start;
5764                                 *arglist->lastp = sp;
5765                                 arglist->lastp = &sp->next;
5766                                 p++;
5767                                 if (!nulonly) {
5768                                         for (;;) {
5769                                                 if (p >= string + ifsp->endoff) {
5770                                                         break;
5771                                                 }
5772                                                 q = p;
5773                                                 if ((unsigned char)*p == CTLESC)
5774                                                         p++;
5775                                                 if (strchr(ifs, *p) == NULL) {
5776                                                         p = q;
5777                                                         break;
5778                                                 }
5779                                                 if (strchr(defifs, *p) == NULL) {
5780                                                         if (ifsspc) {
5781                                                                 p++;
5782                                                                 ifsspc = 0;
5783                                                         } else {
5784                                                                 p = q;
5785                                                                 break;
5786                                                         }
5787                                                 } else
5788                                                         p++;
5789                                         }
5790                                 }
5791                                 start = p;
5792                         } /* while */
5793                         ifsp = ifsp->next;
5794                 } while (ifsp != NULL);
5795                 if (nulonly)
5796                         goto add;
5797         }
5798
5799         if (!*start)
5800                 return;
5801
5802  add:
5803         sp = stzalloc(sizeof(*sp));
5804         sp->text = start;
5805         *arglist->lastp = sp;
5806         arglist->lastp = &sp->next;
5807 }
5808
5809 static void
5810 ifsfree(void)
5811 {
5812         struct ifsregion *p = ifsfirst.next;
5813
5814         if (!p)
5815                 goto out;
5816
5817         INT_OFF;
5818         do {
5819                 struct ifsregion *ifsp;
5820                 ifsp = p->next;
5821                 free(p);
5822                 p = ifsp;
5823         } while (p);
5824         ifsfirst.next = NULL;
5825         INT_ON;
5826  out:
5827         ifslastp = NULL;
5828 }
5829
5830 static size_t
5831 esclen(const char *start, const char *p)
5832 {
5833         size_t esc = 0;
5834
5835         while (p > start && (unsigned char)*--p == CTLESC) {
5836                 esc++;
5837         }
5838         return esc;
5839 }
5840
5841 /*
5842  * Remove any CTLESC characters from a string.
5843  */
5844 static char *
5845 rmescapes(char *str, int flag)
5846 {
5847         static const char qchars[] ALIGN1 = {
5848                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5849
5850         char *p, *q, *r;
5851         unsigned inquotes;
5852         unsigned protect_against_glob;
5853         unsigned globbing;
5854         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5855
5856         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5857         if (!p)
5858                 return str;
5859
5860         q = p;
5861         r = str;
5862         if (flag & RMESCAPE_ALLOC) {
5863                 size_t len = p - str;
5864                 size_t fulllen = len + strlen(p) + 1;
5865
5866                 if (flag & RMESCAPE_GROW) {
5867                         int strloc = str - (char *)stackblock();
5868                         r = makestrspace(fulllen, expdest);
5869                         /* p and str may be invalidated by makestrspace */
5870                         str = (char *)stackblock() + strloc;
5871                         p = str + len;
5872                 } else if (flag & RMESCAPE_HEAP) {
5873                         r = ckmalloc(fulllen);
5874                 } else {
5875                         r = stalloc(fulllen);
5876                 }
5877                 q = r;
5878                 if (len > 0) {
5879                         q = (char *)mempcpy(q, str, len);
5880                 }
5881         }
5882
5883         inquotes = 0;
5884         globbing = flag & RMESCAPE_GLOB;
5885         protect_against_glob = globbing;
5886         while (*p) {
5887                 if ((unsigned char)*p == CTLQUOTEMARK) {
5888 // Note: both inquotes and protect_against_glob only affect whether
5889 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5890                         inquotes = ~inquotes;
5891                         p++;
5892                         protect_against_glob = globbing;
5893                         continue;
5894                 }
5895                 if ((unsigned char)*p == CTLESC) {
5896                         p++;
5897 #if DEBUG
5898                         if (*p == '\0')
5899                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5900 #endif
5901                         if (protect_against_glob) {
5902                                 /*
5903                                  * We used to trust glob() and fnmatch() to eat
5904                                  * superfluous escapes (\z where z has no
5905                                  * special meaning anyway). But this causes
5906                                  * bugs such as string of one greek letter rho
5907                                  * (unicode-encoded as two bytes "cf,81")
5908                                  * getting encoded as "cf,CTLESC,81"
5909                                  * and here, converted to "cf,\,81" -
5910                                  * which does not go well with some flavors
5911                                  * of fnmatch() in unicode locales
5912                                  * (for example, glibc <= 2.22).
5913                                  *
5914                                  * Lets add "\" only on the chars which need it.
5915                                  * Testcases for less obvious chars are shown.
5916                                  */
5917                                 if (*p == '*'
5918                                  || *p == '?'
5919                                  || *p == '['
5920                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5921                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5922                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5923                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5924                                 /* Some libc support [^negate], that's why "^" also needs love */
5925                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5926                                 ) {
5927                                         *q++ = '\\';
5928                                 }
5929                         }
5930                 } else if (*p == '\\' && !inquotes) {
5931                         /* naked back slash */
5932                         protect_against_glob = 0;
5933                         goto copy;
5934                 }
5935 #if BASH_PATTERN_SUBST
5936                 else if (*p == '/' && slash) {
5937                         /* stop handling globbing and mark location of slash */
5938                         globbing = slash = 0;
5939                         *p = CTLESC;
5940                 }
5941 #endif
5942                 protect_against_glob = globbing;
5943  copy:
5944                 *q++ = *p++;
5945         }
5946         *q = '\0';
5947         if (flag & RMESCAPE_GROW) {
5948                 expdest = r;
5949                 STADJUST(q - r + 1, expdest);
5950         }
5951         return r;
5952 }
5953 #define pmatch(a, b) !fnmatch((a), (b), 0)
5954
5955 /*
5956  * Prepare a pattern for a expmeta (internal glob(3)) call.
5957  *
5958  * Returns an stalloced string.
5959  */
5960 static char *
5961 preglob(const char *pattern, int flag)
5962 {
5963         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5964 }
5965
5966 /*
5967  * Put a string on the stack.
5968  */
5969 static void
5970 memtodest(const char *p, size_t len, int syntax, int quotes)
5971 {
5972         char *q;
5973
5974         if (!len)
5975                 return;
5976
5977         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5978
5979         do {
5980                 unsigned char c = *p++;
5981                 if (c) {
5982                         if (quotes & QUOTES_ESC) {
5983                                 int n = SIT(c, syntax);
5984                                 if (n == CCTL
5985                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5986                                      && n == CBACK
5987                                     )
5988                                 ) {
5989                                         USTPUTC(CTLESC, q);
5990                                 }
5991                         }
5992                 } else if (!(quotes & QUOTES_KEEPNUL))
5993                         continue;
5994                 USTPUTC(c, q);
5995         } while (--len);
5996
5997         expdest = q;
5998 }
5999
6000 static size_t
6001 strtodest(const char *p, int syntax, int quotes)
6002 {
6003         size_t len = strlen(p);
6004         memtodest(p, len, syntax, quotes);
6005         return len;
6006 }
6007
6008 /*
6009  * Record the fact that we have to scan this region of the
6010  * string for IFS characters.
6011  */
6012 static void
6013 recordregion(int start, int end, int nulonly)
6014 {
6015         struct ifsregion *ifsp;
6016
6017         if (ifslastp == NULL) {
6018                 ifsp = &ifsfirst;
6019         } else {
6020                 INT_OFF;
6021                 ifsp = ckzalloc(sizeof(*ifsp));
6022                 /*ifsp->next = NULL; - ckzalloc did it */
6023                 ifslastp->next = ifsp;
6024                 INT_ON;
6025         }
6026         ifslastp = ifsp;
6027         ifslastp->begoff = start;
6028         ifslastp->endoff = end;
6029         ifslastp->nulonly = nulonly;
6030 }
6031
6032 static void
6033 removerecordregions(int endoff)
6034 {
6035         if (ifslastp == NULL)
6036                 return;
6037
6038         if (ifsfirst.endoff > endoff) {
6039                 while (ifsfirst.next) {
6040                         struct ifsregion *ifsp;
6041                         INT_OFF;
6042                         ifsp = ifsfirst.next->next;
6043                         free(ifsfirst.next);
6044                         ifsfirst.next = ifsp;
6045                         INT_ON;
6046                 }
6047                 if (ifsfirst.begoff > endoff) {
6048                         ifslastp = NULL;
6049                 } else {
6050                         ifslastp = &ifsfirst;
6051                         ifsfirst.endoff = endoff;
6052                 }
6053                 return;
6054         }
6055
6056         ifslastp = &ifsfirst;
6057         while (ifslastp->next && ifslastp->next->begoff < endoff)
6058                 ifslastp = ifslastp->next;
6059         while (ifslastp->next) {
6060                 struct ifsregion *ifsp;
6061                 INT_OFF;
6062                 ifsp = ifslastp->next->next;
6063                 free(ifslastp->next);
6064                 ifslastp->next = ifsp;
6065                 INT_ON;
6066         }
6067         if (ifslastp->endoff > endoff)
6068                 ifslastp->endoff = endoff;
6069 }
6070
6071 static char *
6072 exptilde(char *startp, char *p, int flags)
6073 {
6074         unsigned char c;
6075         char *name;
6076         struct passwd *pw;
6077         const char *home;
6078         int quotes = flags & QUOTES_ESC;
6079
6080         name = p + 1;
6081
6082         while ((c = *++p) != '\0') {
6083                 switch (c) {
6084                 case CTLESC:
6085                         return startp;
6086                 case CTLQUOTEMARK:
6087                         return startp;
6088                 case ':':
6089                         if (flags & EXP_VARTILDE)
6090                                 goto done;
6091                         break;
6092                 case '/':
6093                 case CTLENDVAR:
6094                         goto done;
6095                 }
6096         }
6097  done:
6098         *p = '\0';
6099         if (*name == '\0') {
6100                 home = lookupvar("HOME");
6101         } else {
6102                 pw = getpwnam(name);
6103                 if (pw == NULL)
6104                         goto lose;
6105                 home = pw->pw_dir;
6106         }
6107         if (!home || !*home)
6108                 goto lose;
6109         *p = c;
6110         strtodest(home, SQSYNTAX, quotes);
6111         return p;
6112  lose:
6113         *p = c;
6114         return startp;
6115 }
6116
6117 /*
6118  * Execute a command inside back quotes.  If it's a builtin command, we
6119  * want to save its output in a block obtained from malloc.  Otherwise
6120  * we fork off a subprocess and get the output of the command via a pipe.
6121  * Should be called with interrupts off.
6122  */
6123 struct backcmd {                /* result of evalbackcmd */
6124         int fd;                 /* file descriptor to read from */
6125         int nleft;              /* number of chars in buffer */
6126         char *buf;              /* buffer */
6127         struct job *jp;         /* job structure for command */
6128 };
6129
6130 /* These forward decls are needed to use "eval" code for backticks handling: */
6131 #define EV_EXIT 01              /* exit after evaluating tree */
6132 static int evaltree(union node *, int);
6133
6134 static void FAST_FUNC
6135 evalbackcmd(union node *n, struct backcmd *result)
6136 {
6137         int pip[2];
6138         struct job *jp;
6139
6140         result->fd = -1;
6141         result->buf = NULL;
6142         result->nleft = 0;
6143         result->jp = NULL;
6144         if (n == NULL) {
6145                 goto out;
6146         }
6147
6148         if (pipe(pip) < 0)
6149                 ash_msg_and_raise_error("pipe call failed");
6150         jp = makejob(/*n,*/ 1);
6151         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6152                 /* child */
6153                 FORCE_INT_ON;
6154                 close(pip[0]);
6155                 if (pip[1] != 1) {
6156                         /*close(1);*/
6157                         dup2_or_raise(pip[1], 1);
6158                         close(pip[1]);
6159                 }
6160 /* TODO: eflag clearing makes the following not abort:
6161  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6162  * which is what bash does (unless it is in POSIX mode).
6163  * dash deleted "eflag = 0" line in the commit
6164  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6165  *  [EVAL] Don't clear eflag in evalbackcmd
6166  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6167  */
6168                 eflag = 0;
6169                 ifsfree();
6170                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6171                 /* NOTREACHED */
6172         }
6173         /* parent */
6174         close(pip[1]);
6175         result->fd = pip[0];
6176         result->jp = jp;
6177
6178  out:
6179         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6180                 result->fd, result->buf, result->nleft, result->jp));
6181 }
6182
6183 /*
6184  * Expand stuff in backwards quotes.
6185  */
6186 static void
6187 expbackq(union node *cmd, int flag)
6188 {
6189         struct backcmd in;
6190         int i;
6191         char buf[128];
6192         char *p;
6193         char *dest;
6194         int startloc;
6195         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6196         struct stackmark smark;
6197
6198         INT_OFF;
6199         startloc = expdest - (char *)stackblock();
6200         pushstackmark(&smark, startloc);
6201         evalbackcmd(cmd, &in);
6202         popstackmark(&smark);
6203
6204         p = in.buf;
6205         i = in.nleft;
6206         if (i == 0)
6207                 goto read;
6208         for (;;) {
6209                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6210  read:
6211                 if (in.fd < 0)
6212                         break;
6213                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6214                 TRACE(("expbackq: read returns %d\n", i));
6215                 if (i <= 0)
6216                         break;
6217                 p = buf;
6218         }
6219
6220         free(in.buf);
6221         if (in.fd >= 0) {
6222                 close(in.fd);
6223                 back_exitstatus = waitforjob(in.jp);
6224         }
6225         INT_ON;
6226
6227         /* Eat all trailing newlines */
6228         dest = expdest;
6229         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6230                 STUNPUTC(dest);
6231         expdest = dest;
6232
6233         if (!(flag & EXP_QUOTED))
6234                 recordregion(startloc, dest - (char *)stackblock(), 0);
6235         TRACE(("evalbackq: size:%d:'%.*s'\n",
6236                 (int)((dest - (char *)stackblock()) - startloc),
6237                 (int)((dest - (char *)stackblock()) - startloc),
6238                 stackblock() + startloc));
6239 }
6240
6241 #if ENABLE_FEATURE_SH_MATH
6242 /*
6243  * Expand arithmetic expression.  Backup to start of expression,
6244  * evaluate, place result in (backed up) result, adjust string position.
6245  */
6246 static void
6247 expari(int flag)
6248 {
6249         char *p, *start;
6250         int begoff;
6251         int len;
6252
6253         /* ifsfree(); */
6254
6255         /*
6256          * This routine is slightly over-complicated for
6257          * efficiency.  Next we scan backwards looking for the
6258          * start of arithmetic.
6259          */
6260         start = stackblock();
6261         p = expdest - 1;
6262         *p = '\0';
6263         p--;
6264         while (1) {
6265                 int esc;
6266
6267                 while ((unsigned char)*p != CTLARI) {
6268                         p--;
6269 #if DEBUG
6270                         if (p < start) {
6271                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6272                         }
6273 #endif
6274                 }
6275
6276                 esc = esclen(start, p);
6277                 if (!(esc % 2)) {
6278                         break;
6279                 }
6280
6281                 p -= esc + 1;
6282         }
6283
6284         begoff = p - start;
6285
6286         removerecordregions(begoff);
6287
6288         expdest = p;
6289
6290         if (flag & QUOTES_ESC)
6291                 rmescapes(p + 1, 0);
6292
6293         len = cvtnum(ash_arith(p + 1));
6294
6295         if (!(flag & EXP_QUOTED))
6296                 recordregion(begoff, begoff + len, 0);
6297 }
6298 #endif
6299
6300 /* argstr needs it */
6301 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6302
6303 /*
6304  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6305  * characters to allow for further processing.  Otherwise treat
6306  * $@ like $* since no splitting will be performed.
6307  *
6308  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6309  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6310  * for correct expansion of "B=$A" word.
6311  */
6312 static void
6313 argstr(char *p, int flags, struct strlist *var_str_list)
6314 {
6315         static const char spclchars[] ALIGN1 = {
6316                 '=',
6317                 ':',
6318                 CTLQUOTEMARK,
6319                 CTLENDVAR,
6320                 CTLESC,
6321                 CTLVAR,
6322                 CTLBACKQ,
6323 #if ENABLE_FEATURE_SH_MATH
6324                 CTLENDARI,
6325 #endif
6326                 '\0'
6327         };
6328         const char *reject = spclchars;
6329         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6330         int inquotes;
6331         size_t length;
6332         int startloc;
6333
6334         if (!(flags & EXP_VARTILDE)) {
6335                 reject += 2;
6336         } else if (flags & EXP_VARTILDE2) {
6337                 reject++;
6338         }
6339         inquotes = 0;
6340         length = 0;
6341         if (flags & EXP_TILDE) {
6342                 char *q;
6343
6344                 flags &= ~EXP_TILDE;
6345  tilde:
6346                 q = p;
6347                 if (*q == '~')
6348                         p = exptilde(p, q, flags);
6349         }
6350  start:
6351         startloc = expdest - (char *)stackblock();
6352         for (;;) {
6353                 unsigned char c;
6354
6355                 length += strcspn(p + length, reject);
6356                 c = p[length];
6357                 if (c) {
6358                         if (!(c & 0x80)
6359                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6360                         ) {
6361                                 /* c == '=' || c == ':' || c == CTLENDARI */
6362                                 length++;
6363                         }
6364                 }
6365                 if (length > 0) {
6366                         int newloc;
6367                         expdest = stack_nputstr(p, length, expdest);
6368                         newloc = expdest - (char *)stackblock();
6369                         if (breakall && !inquotes && newloc > startloc) {
6370                                 recordregion(startloc, newloc, 0);
6371                         }
6372                         startloc = newloc;
6373                 }
6374                 p += length + 1;
6375                 length = 0;
6376
6377                 switch (c) {
6378                 case '\0':
6379                         goto breakloop;
6380                 case '=':
6381                         if (flags & EXP_VARTILDE2) {
6382                                 p--;
6383                                 continue;
6384                         }
6385                         flags |= EXP_VARTILDE2;
6386                         reject++;
6387                         /* fall through */
6388                 case ':':
6389                         /*
6390                          * sort of a hack - expand tildes in variable
6391                          * assignments (after the first '=' and after ':'s).
6392                          */
6393                         if (*--p == '~') {
6394                                 goto tilde;
6395                         }
6396                         continue;
6397                 }
6398
6399                 switch (c) {
6400                 case CTLENDVAR: /* ??? */
6401                         goto breakloop;
6402                 case CTLQUOTEMARK:
6403                         inquotes ^= EXP_QUOTED;
6404                         /* "$@" syntax adherence hack */
6405                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6406                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6407                                 goto start;
6408                         }
6409  addquote:
6410                         if (flags & QUOTES_ESC) {
6411                                 p--;
6412                                 length++;
6413                                 startloc++;
6414                         }
6415                         break;
6416                 case CTLESC:
6417                         startloc++;
6418                         length++;
6419
6420                         /*
6421                          * Quoted parameter expansion pattern: remove quote
6422                          * unless inside inner quotes or we have a literal
6423                          * backslash.
6424                          */
6425                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6426                             EXP_QPAT && *p != '\\')
6427                                 break;
6428
6429                         goto addquote;
6430                 case CTLVAR:
6431                         TRACE(("argstr: evalvar('%s')\n", p));
6432                         p = evalvar(p, flags | inquotes, var_str_list);
6433                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6434                         goto start;
6435                 case CTLBACKQ:
6436                         expbackq(argbackq->n, flags | inquotes);
6437                         argbackq = argbackq->next;
6438                         goto start;
6439 #if ENABLE_FEATURE_SH_MATH
6440                 case CTLENDARI:
6441                         p--;
6442                         expari(flags | inquotes);
6443                         goto start;
6444 #endif
6445                 }
6446         }
6447  breakloop: ;
6448 }
6449
6450 static char *
6451 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6452                 char *pattern, int quotes, int zero)
6453 {
6454         char *loc, *loc2;
6455         char c;
6456
6457         loc = startp;
6458         loc2 = rmesc;
6459         do {
6460                 int match;
6461                 const char *s = loc2;
6462
6463                 c = *loc2;
6464                 if (zero) {
6465                         *loc2 = '\0';
6466                         s = rmesc;
6467                 }
6468                 match = pmatch(pattern, s);
6469
6470                 *loc2 = c;
6471                 if (match)
6472                         return loc;
6473                 if (quotes && (unsigned char)*loc == CTLESC)
6474                         loc++;
6475                 loc++;
6476                 loc2++;
6477         } while (c);
6478         return NULL;
6479 }
6480
6481 static char *
6482 scanright(char *startp, char *rmesc, char *rmescend,
6483                 char *pattern, int quotes, int match_at_start)
6484 {
6485 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6486         int try2optimize = match_at_start;
6487 #endif
6488         int esc = 0;
6489         char *loc;
6490         char *loc2;
6491
6492         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6493          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6494          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6495          * Logic:
6496          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6497          * and on each iteration they go back two/one char until they reach the beginning.
6498          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6499          */
6500         /* TODO: document in what other circumstances we are called. */
6501
6502         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6503                 int match;
6504                 char c = *loc2;
6505                 const char *s = loc2;
6506                 if (match_at_start) {
6507                         *loc2 = '\0';
6508                         s = rmesc;
6509                 }
6510                 match = pmatch(pattern, s);
6511                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6512                 *loc2 = c;
6513                 if (match)
6514                         return loc;
6515 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6516                 if (try2optimize) {
6517                         /* Maybe we can optimize this:
6518                          * if pattern ends with unescaped *, we can avoid checking
6519                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6520                          * it won't match truncated "raw_value_of_" strings too.
6521                          */
6522                         unsigned plen = strlen(pattern);
6523                         /* Does it end with "*"? */
6524                         if (plen != 0 && pattern[--plen] == '*') {
6525                                 /* "xxxx*" is not escaped */
6526                                 /* "xxx\*" is escaped */
6527                                 /* "xx\\*" is not escaped */
6528                                 /* "x\\\*" is escaped */
6529                                 int slashes = 0;
6530                                 while (plen != 0 && pattern[--plen] == '\\')
6531                                         slashes++;
6532                                 if (!(slashes & 1))
6533                                         break; /* ends with unescaped "*" */
6534                         }
6535                         try2optimize = 0;
6536                 }
6537 #endif
6538                 loc--;
6539                 if (quotes) {
6540                         if (--esc < 0) {
6541                                 esc = esclen(startp, loc);
6542                         }
6543                         if (esc % 2) {
6544                                 esc--;
6545                                 loc--;
6546                         }
6547                 }
6548         }
6549         return NULL;
6550 }
6551
6552 static void varunset(const char *, const char *, const char *, int) NORETURN;
6553 static void
6554 varunset(const char *end, const char *var, const char *umsg, int varflags)
6555 {
6556         const char *msg;
6557         const char *tail;
6558
6559         tail = nullstr;
6560         msg = "parameter not set";
6561         if (umsg) {
6562                 if ((unsigned char)*end == CTLENDVAR) {
6563                         if (varflags & VSNUL)
6564                                 tail = " or null";
6565                 } else {
6566                         msg = umsg;
6567                 }
6568         }
6569         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6570 }
6571
6572 static const char *
6573 subevalvar(char *p, char *varname, int strloc, int subtype,
6574                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6575 {
6576         struct nodelist *saveargbackq = argbackq;
6577         int quotes = flag & QUOTES_ESC;
6578         char *startp;
6579         char *loc;
6580         char *rmesc, *rmescend;
6581         char *str;
6582         int amount, resetloc;
6583         IF_BASH_PATTERN_SUBST(int workloc;)
6584         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6585         int zero;
6586         char *(*scan)(char*, char*, char*, char*, int, int);
6587
6588         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6589         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6590
6591         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6592                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6593                         var_str_list);
6594         STPUTC('\0', expdest);
6595         argbackq = saveargbackq;
6596         startp = (char *)stackblock() + startloc;
6597
6598         switch (subtype) {
6599         case VSASSIGN:
6600                 setvar0(varname, startp);
6601                 amount = startp - expdest;
6602                 STADJUST(amount, expdest);
6603                 return startp;
6604
6605         case VSQUESTION:
6606                 varunset(p, varname, startp, varflags);
6607                 /* NOTREACHED */
6608
6609 #if BASH_SUBSTR
6610         case VSSUBSTR: {
6611                 int pos, len, orig_len;
6612                 char *colon;
6613
6614                 loc = str = stackblock() + strloc;
6615
6616 # if !ENABLE_FEATURE_SH_MATH
6617 #  define ash_arith number
6618 # endif
6619                 /* Read POS in ${var:POS:LEN} */
6620                 colon = strchr(loc, ':');
6621                 if (colon) *colon = '\0';
6622                 pos = ash_arith(loc);
6623                 if (colon) *colon = ':';
6624
6625                 /* Read LEN in ${var:POS:LEN} */
6626                 len = str - startp - 1;
6627                 /* *loc != '\0', guaranteed by parser */
6628                 if (quotes) {
6629                         char *ptr;
6630
6631                         /* Adjust the length by the number of escapes */
6632                         for (ptr = startp; ptr < (str - 1); ptr++) {
6633                                 if ((unsigned char)*ptr == CTLESC) {
6634                                         len--;
6635                                         ptr++;
6636                                 }
6637                         }
6638                 }
6639                 orig_len = len;
6640                 if (*loc++ == ':') {
6641                         /* ${var::LEN} */
6642                         len = ash_arith(loc);
6643                 } else {
6644                         /* Skip POS in ${var:POS:LEN} */
6645                         len = orig_len;
6646                         while (*loc && *loc != ':') {
6647                                 loc++;
6648                         }
6649                         if (*loc++ == ':') {
6650                                 len = ash_arith(loc);
6651                         }
6652                 }
6653 #  undef ash_arith
6654
6655                 if (pos < 0) {
6656                         /* ${VAR:$((-n)):l} starts n chars from the end */
6657                         pos = orig_len + pos;
6658                 }
6659                 if ((unsigned)pos >= orig_len) {
6660                         /* apart from obvious ${VAR:999999:l},
6661                          * covers ${VAR:$((-9999999)):l} - result is ""
6662                          * (bash compat)
6663                          */
6664                         pos = 0;
6665                         len = 0;
6666                 }
6667                 if (len < 0) {
6668                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6669                         len = (orig_len - pos) + len;
6670                 }
6671                 if ((unsigned)len > (orig_len - pos))
6672                         len = orig_len - pos;
6673
6674                 for (str = startp; pos; str++, pos--) {
6675                         if (quotes && (unsigned char)*str == CTLESC)
6676                                 str++;
6677                 }
6678                 for (loc = startp; len; len--) {
6679                         if (quotes && (unsigned char)*str == CTLESC)
6680                                 *loc++ = *str++;
6681                         *loc++ = *str++;
6682                 }
6683                 *loc = '\0';
6684                 amount = loc - expdest;
6685                 STADJUST(amount, expdest);
6686                 return loc;
6687         }
6688 #endif /* BASH_SUBSTR */
6689         }
6690
6691         resetloc = expdest - (char *)stackblock();
6692
6693 #if BASH_PATTERN_SUBST
6694         /* We'll comeback here if we grow the stack while handling
6695          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6696          * stack will need rebasing, and we'll need to remove our work
6697          * areas each time
6698          */
6699  restart:
6700 #endif
6701
6702         amount = expdest - ((char *)stackblock() + resetloc);
6703         STADJUST(-amount, expdest);
6704         startp = (char *)stackblock() + startloc;
6705
6706         rmesc = startp;
6707         rmescend = (char *)stackblock() + strloc;
6708         if (quotes) {
6709                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6710                 if (rmesc != startp) {
6711                         rmescend = expdest;
6712                         startp = (char *)stackblock() + startloc;
6713                 }
6714         }
6715         rmescend--;
6716         str = (char *)stackblock() + strloc;
6717         /*
6718          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6719          * The result is a_\_z_c (not a\_\_z_c)!
6720          *
6721          * The search pattern and replace string treat backslashes differently!
6722          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6723          * and string.  It's only used on the first call.
6724          */
6725         preglob(str, IF_BASH_PATTERN_SUBST(
6726                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6727                         RMESCAPE_SLASH : ) 0);
6728
6729 #if BASH_PATTERN_SUBST
6730         workloc = expdest - (char *)stackblock();
6731         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6732                 int len;
6733                 char *idx, *end;
6734
6735                 if (!repl) {
6736                         repl = strchr(str, CTLESC);
6737                         if (repl)
6738                                 *repl++ = '\0';
6739                         else
6740                                 repl = nullstr;
6741                 }
6742                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6743
6744                 /* If there's no pattern to match, return the expansion unmolested */
6745                 if (str[0] == '\0')
6746                         return NULL;
6747
6748                 len = 0;
6749                 idx = startp;
6750                 end = str - 1;
6751                 while (idx < end) {
6752  try_to_match:
6753                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6754                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6755                         if (!loc) {
6756                                 /* No match, advance */
6757                                 char *restart_detect = stackblock();
6758  skip_matching:
6759                                 STPUTC(*idx, expdest);
6760                                 if (quotes && (unsigned char)*idx == CTLESC) {
6761                                         idx++;
6762                                         len++;
6763                                         STPUTC(*idx, expdest);
6764                                 }
6765                                 if (stackblock() != restart_detect)
6766                                         goto restart;
6767                                 idx++;
6768                                 len++;
6769                                 rmesc++;
6770                                 /* continue; - prone to quadratic behavior, smarter code: */
6771                                 if (idx >= end)
6772                                         break;
6773                                 if (str[0] == '*') {
6774                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6775                                          * it would never match "ong_string" etc, no point in trying.
6776                                          */
6777                                         goto skip_matching;
6778                                 }
6779                                 goto try_to_match;
6780                         }
6781
6782                         if (subtype == VSREPLACEALL) {
6783                                 while (idx < loc) {
6784                                         if (quotes && (unsigned char)*idx == CTLESC)
6785                                                 idx++;
6786                                         idx++;
6787                                         rmesc++;
6788                                 }
6789                         } else {
6790                                 idx = loc;
6791                         }
6792
6793                         //bb_error_msg("repl:'%s'", repl);
6794                         for (loc = (char*)repl; *loc; loc++) {
6795                                 char *restart_detect = stackblock();
6796                                 if (quotes && *loc == '\\') {
6797                                         STPUTC(CTLESC, expdest);
6798                                         len++;
6799                                 }
6800                                 STPUTC(*loc, expdest);
6801                                 if (stackblock() != restart_detect)
6802                                         goto restart;
6803                                 len++;
6804                         }
6805
6806                         if (subtype == VSREPLACE) {
6807                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6808                                 while (*idx) {
6809                                         char *restart_detect = stackblock();
6810                                         STPUTC(*idx, expdest);
6811                                         if (stackblock() != restart_detect)
6812                                                 goto restart;
6813                                         len++;
6814                                         idx++;
6815                                 }
6816                                 break;
6817                         }
6818                 }
6819
6820                 /* We've put the replaced text into a buffer at workloc, now
6821                  * move it to the right place and adjust the stack.
6822                  */
6823                 STPUTC('\0', expdest);
6824                 startp = (char *)stackblock() + startloc;
6825                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6826                 //bb_error_msg("startp:'%s'", startp);
6827                 amount = expdest - (startp + len);
6828                 STADJUST(-amount, expdest);
6829                 return startp;
6830         }
6831 #endif /* BASH_PATTERN_SUBST */
6832
6833         subtype -= VSTRIMRIGHT;
6834 #if DEBUG
6835         if (subtype < 0 || subtype > 7)
6836                 abort();
6837 #endif
6838         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6839         zero = subtype >> 1;
6840         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6841         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6842
6843         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6844         if (loc) {
6845                 if (zero) {
6846                         memmove(startp, loc, str - loc);
6847                         loc = startp + (str - loc) - 1;
6848                 }
6849                 *loc = '\0';
6850                 amount = loc - expdest;
6851                 STADJUST(amount, expdest);
6852         }
6853         return loc;
6854 }
6855
6856 /*
6857  * Add the value of a specialized variable to the stack string.
6858  * name parameter (examples):
6859  * ash -c 'echo $1'      name:'1='
6860  * ash -c 'echo $qwe'    name:'qwe='
6861  * ash -c 'echo $$'      name:'$='
6862  * ash -c 'echo ${$}'    name:'$='
6863  * ash -c 'echo ${$##q}' name:'$=q'
6864  * ash -c 'echo ${#$}'   name:'$='
6865  * note: examples with bad shell syntax:
6866  * ash -c 'echo ${#$1}'  name:'$=1'
6867  * ash -c 'echo ${#1#}'  name:'1=#'
6868  */
6869 static NOINLINE ssize_t
6870 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6871 {
6872         const char *p;
6873         int num;
6874         int i;
6875         ssize_t len = 0;
6876         int sep;
6877         int quoted = *quotedp;
6878         int subtype = varflags & VSTYPE;
6879         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6880         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6881         int syntax;
6882
6883         sep = (flags & EXP_FULL) << CHAR_BIT;
6884         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6885
6886         switch (*name) {
6887         case '$':
6888                 num = rootpid;
6889                 goto numvar;
6890         case '?':
6891                 num = exitstatus;
6892                 goto numvar;
6893         case '#':
6894                 num = shellparam.nparam;
6895                 goto numvar;
6896         case '!':
6897                 num = backgndpid;
6898                 if (num == 0)
6899                         return -1;
6900  numvar:
6901                 len = cvtnum(num);
6902                 goto check_1char_name;
6903         case '-':
6904                 expdest = makestrspace(NOPTS, expdest);
6905                 for (i = NOPTS - 1; i >= 0; i--) {
6906                         if (optlist[i]) {
6907                                 USTPUTC(optletters(i), expdest);
6908                                 len++;
6909                         }
6910                 }
6911  check_1char_name:
6912 #if 0
6913                 /* handles cases similar to ${#$1} */
6914                 if (name[2] != '\0')
6915                         raise_error_syntax("bad substitution");
6916 #endif
6917                 break;
6918         case '@':
6919                 if (quoted && sep)
6920                         goto param;
6921                 /* fall through */
6922         case '*': {
6923                 char **ap;
6924                 char sepc;
6925
6926                 if (quoted)
6927                         sep = 0;
6928                 sep |= ifsset() ? ifsval()[0] : ' ';
6929  param:
6930                 sepc = sep;
6931                 *quotedp = !sepc;
6932                 ap = shellparam.p;
6933                 if (!ap)
6934                         return -1;
6935                 while ((p = *ap++) != NULL) {
6936                         len += strtodest(p, syntax, quotes);
6937
6938                         if (*ap && sep) {
6939                                 len++;
6940                                 memtodest(&sepc, 1, syntax, quotes);
6941                         }
6942                 }
6943                 break;
6944         } /* case '*' */
6945         case '0':
6946         case '1':
6947         case '2':
6948         case '3':
6949         case '4':
6950         case '5':
6951         case '6':
6952         case '7':
6953         case '8':
6954         case '9':
6955                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6956                 if (num < 0 || num > shellparam.nparam)
6957                         return -1;
6958                 p = num ? shellparam.p[num - 1] : arg0;
6959                 goto value;
6960         default:
6961                 /* NB: name has form "VAR=..." */
6962
6963                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6964                  * which should be considered before we check variables. */
6965                 if (var_str_list) {
6966                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6967                         p = NULL;
6968                         do {
6969                                 char *str, *eq;
6970                                 str = var_str_list->text;
6971                                 eq = strchr(str, '=');
6972                                 if (!eq) /* stop at first non-assignment */
6973                                         break;
6974                                 eq++;
6975                                 if (name_len == (unsigned)(eq - str)
6976                                  && strncmp(str, name, name_len) == 0
6977                                 ) {
6978                                         p = eq;
6979                                         /* goto value; - WRONG! */
6980                                         /* think "A=1 A=2 B=$A" */
6981                                 }
6982                                 var_str_list = var_str_list->next;
6983                         } while (var_str_list);
6984                         if (p)
6985                                 goto value;
6986                 }
6987                 p = lookupvar(name);
6988  value:
6989                 if (!p)
6990                         return -1;
6991
6992                 len = strtodest(p, syntax, quotes);
6993 #if ENABLE_UNICODE_SUPPORT
6994                 if (subtype == VSLENGTH && len > 0) {
6995                         reinit_unicode_for_ash();
6996                         if (unicode_status == UNICODE_ON) {
6997                                 STADJUST(-len, expdest);
6998                                 discard = 0;
6999                                 len = unicode_strlen(p);
7000                         }
7001                 }
7002 #endif
7003                 break;
7004         }
7005
7006         if (discard)
7007                 STADJUST(-len, expdest);
7008         return len;
7009 }
7010
7011 /*
7012  * Expand a variable, and return a pointer to the next character in the
7013  * input string.
7014  */
7015 static char *
7016 evalvar(char *p, int flag, struct strlist *var_str_list)
7017 {
7018         char varflags;
7019         char subtype;
7020         int quoted;
7021         char easy;
7022         char *var;
7023         int patloc;
7024         int startloc;
7025         ssize_t varlen;
7026
7027         varflags = (unsigned char) *p++;
7028         subtype = varflags & VSTYPE;
7029
7030         if (!subtype)
7031                 raise_error_syntax("bad substitution");
7032
7033         quoted = flag & EXP_QUOTED;
7034         var = p;
7035         easy = (!quoted || (*var == '@' && shellparam.nparam));
7036         startloc = expdest - (char *)stackblock();
7037         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7038
7039  again:
7040         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7041         if (varflags & VSNUL)
7042                 varlen--;
7043
7044         if (subtype == VSPLUS) {
7045                 varlen = -1 - varlen;
7046                 goto vsplus;
7047         }
7048
7049         if (subtype == VSMINUS) {
7050  vsplus:
7051                 if (varlen < 0) {
7052                         argstr(
7053                                 p,
7054                                 flag | EXP_TILDE | EXP_WORD,
7055                                 var_str_list
7056                         );
7057                         goto end;
7058                 }
7059                 goto record;
7060         }
7061
7062         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7063                 if (varlen >= 0)
7064                         goto record;
7065
7066                 subevalvar(p, var, 0, subtype, startloc, varflags,
7067                            flag & ~QUOTES_ESC, var_str_list);
7068                 varflags &= ~VSNUL;
7069                 /*
7070                  * Remove any recorded regions beyond
7071                  * start of variable
7072                  */
7073                 removerecordregions(startloc);
7074                 goto again;
7075         }
7076
7077         if (varlen < 0 && uflag)
7078                 varunset(p, var, 0, 0);
7079
7080         if (subtype == VSLENGTH) {
7081                 cvtnum(varlen > 0 ? varlen : 0);
7082                 goto record;
7083         }
7084
7085         if (subtype == VSNORMAL) {
7086  record:
7087                 if (!easy)
7088                         goto end;
7089                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7090                 goto end;
7091         }
7092
7093 #if DEBUG
7094         switch (subtype) {
7095         case VSTRIMLEFT:
7096         case VSTRIMLEFTMAX:
7097         case VSTRIMRIGHT:
7098         case VSTRIMRIGHTMAX:
7099 #if BASH_SUBSTR
7100         case VSSUBSTR:
7101 #endif
7102 #if BASH_PATTERN_SUBST
7103         case VSREPLACE:
7104         case VSREPLACEALL:
7105 #endif
7106                 break;
7107         default:
7108                 abort();
7109         }
7110 #endif
7111
7112         if (varlen >= 0) {
7113                 /*
7114                  * Terminate the string and start recording the pattern
7115                  * right after it
7116                  */
7117                 STPUTC('\0', expdest);
7118                 patloc = expdest - (char *)stackblock();
7119                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7120                                 startloc, varflags, flag, var_str_list)) {
7121                         int amount = expdest - (
7122                                 (char *)stackblock() + patloc - 1
7123                         );
7124                         STADJUST(-amount, expdest);
7125                 }
7126                 /* Remove any recorded regions beyond start of variable */
7127                 removerecordregions(startloc);
7128                 goto record;
7129         }
7130
7131  end:
7132         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7133                 int nesting = 1;
7134                 for (;;) {
7135                         unsigned char c = *p++;
7136                         if (c == CTLESC)
7137                                 p++;
7138                         else if (c == CTLBACKQ) {
7139                                 if (varlen >= 0)
7140                                         argbackq = argbackq->next;
7141                         } else if (c == CTLVAR) {
7142                                 if ((*p++ & VSTYPE) != VSNORMAL)
7143                                         nesting++;
7144                         } else if (c == CTLENDVAR) {
7145                                 if (--nesting == 0)
7146                                         break;
7147                         }
7148                 }
7149         }
7150         return p;
7151 }
7152
7153 /*
7154  * Add a file name to the list.
7155  */
7156 static void
7157 addfname(const char *name)
7158 {
7159         struct strlist *sp;
7160
7161         sp = stzalloc(sizeof(*sp));
7162         sp->text = sstrdup(name);
7163         *exparg.lastp = sp;
7164         exparg.lastp = &sp->next;
7165 }
7166
7167 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7168 static int
7169 hasmeta(const char *p)
7170 {
7171         static const char chars[] ALIGN1 = {
7172                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7173         };
7174
7175         for (;;) {
7176                 p = strpbrk(p, chars);
7177                 if (!p)
7178                         break;
7179                 switch ((unsigned char) *p) {
7180                 case CTLQUOTEMARK:
7181                         for (;;) {
7182                                 p++;
7183                                 if (*p == CTLQUOTEMARK)
7184                                         break;
7185                                 if (*p == CTLESC)
7186                                         p++;
7187                                 if (*p == '\0') /* huh? */
7188                                         return 0;
7189                         }
7190                         break;
7191                 case '\\':
7192                 case CTLESC:
7193                         p++;
7194                         if (*p == '\0')
7195                                 return 0;
7196                         break;
7197                 case '[':
7198                         if (!strchr(p + 1, ']')) {
7199                                 /* It's not a properly closed [] pattern,
7200                                  * but other metas may follow. Continue checking.
7201                                  * my[file* _is_ globbed by bash
7202                                  * and matches filenames like "my[file1".
7203                                  */
7204                                 break;
7205                         }
7206                         /* fallthrough */
7207                 default:
7208                 /* case '*': */
7209                 /* case '?': */
7210                         return 1;
7211                 }
7212                 p++;
7213         }
7214
7215         return 0;
7216 }
7217
7218 /* If we want to use glob() from libc... */
7219 #if !ENABLE_ASH_INTERNAL_GLOB
7220
7221 /* Add the result of glob() to the list */
7222 static void
7223 addglob(const glob_t *pglob)
7224 {
7225         char **p = pglob->gl_pathv;
7226
7227         do {
7228                 addfname(*p);
7229         } while (*++p);
7230 }
7231 static void
7232 expandmeta(struct strlist *str /*, int flag*/)
7233 {
7234         /* TODO - EXP_REDIR */
7235
7236         while (str) {
7237                 char *p;
7238                 glob_t pglob;
7239                 int i;
7240
7241                 if (fflag)
7242                         goto nometa;
7243
7244                 if (!hasmeta(str->text))
7245                         goto nometa;
7246
7247                 INT_OFF;
7248                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7249 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7250 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7251 //
7252 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7253 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7254 // Which means you need to unescape the string, right? Not so fast:
7255 // if there _is_ a file named "file\?" (with backslash), it is returned
7256 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7257 // You DON'T KNOW by looking at the result whether you need to unescape it.
7258 //
7259 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7260 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7261 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7262 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7263 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7264 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7265                 i = glob(p, 0, NULL, &pglob);
7266                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7267                 if (p != str->text)
7268                         free(p);
7269                 switch (i) {
7270                 case 0:
7271 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7272                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7273                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7274                                 goto nometa2;
7275 #endif
7276                         addglob(&pglob);
7277                         globfree(&pglob);
7278                         INT_ON;
7279                         break;
7280                 case GLOB_NOMATCH:
7281  //nometa2:
7282                         globfree(&pglob);
7283                         INT_ON;
7284  nometa:
7285                         *exparg.lastp = str;
7286                         rmescapes(str->text, 0);
7287                         exparg.lastp = &str->next;
7288                         break;
7289                 default:        /* GLOB_NOSPACE */
7290                         globfree(&pglob);
7291                         INT_ON;
7292                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7293                 }
7294                 str = str->next;
7295         }
7296 }
7297
7298 #else
7299 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7300
7301 /*
7302  * Do metacharacter (i.e. *, ?, [...]) expansion.
7303  */
7304 static void
7305 expmeta(char *expdir, char *enddir, char *name)
7306 {
7307         char *p;
7308         const char *cp;
7309         char *start;
7310         char *endname;
7311         int metaflag;
7312         struct stat statb;
7313         DIR *dirp;
7314         struct dirent *dp;
7315         int atend;
7316         int matchdot;
7317         int esc;
7318
7319         metaflag = 0;
7320         start = name;
7321         for (p = name; esc = 0, *p; p += esc + 1) {
7322                 if (*p == '*' || *p == '?')
7323                         metaflag = 1;
7324                 else if (*p == '[') {
7325                         char *q = p + 1;
7326                         if (*q == '!')
7327                                 q++;
7328                         for (;;) {
7329                                 if (*q == '\\')
7330                                         q++;
7331                                 if (*q == '/' || *q == '\0')
7332                                         break;
7333                                 if (*++q == ']') {
7334                                         metaflag = 1;
7335                                         break;
7336                                 }
7337                         }
7338                 } else {
7339                         if (*p == '\\')
7340                                 esc++;
7341                         if (p[esc] == '/') {
7342                                 if (metaflag)
7343                                         break;
7344                                 start = p + esc + 1;
7345                         }
7346                 }
7347         }
7348         if (metaflag == 0) {    /* we've reached the end of the file name */
7349                 if (enddir != expdir)
7350                         metaflag++;
7351                 p = name;
7352                 do {
7353                         if (*p == '\\')
7354                                 p++;
7355                         *enddir++ = *p;
7356                 } while (*p++);
7357                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7358                         addfname(expdir);
7359                 return;
7360         }
7361         endname = p;
7362         if (name < start) {
7363                 p = name;
7364                 do {
7365                         if (*p == '\\')
7366                                 p++;
7367                         *enddir++ = *p++;
7368                 } while (p < start);
7369         }
7370         if (enddir == expdir) {
7371                 cp = ".";
7372         } else if (enddir == expdir + 1 && *expdir == '/') {
7373                 cp = "/";
7374         } else {
7375                 cp = expdir;
7376                 enddir[-1] = '\0';
7377         }
7378         dirp = opendir(cp);
7379         if (dirp == NULL)
7380                 return;
7381         if (enddir != expdir)
7382                 enddir[-1] = '/';
7383         if (*endname == 0) {
7384                 atend = 1;
7385         } else {
7386                 atend = 0;
7387                 *endname = '\0';
7388                 endname += esc + 1;
7389         }
7390         matchdot = 0;
7391         p = start;
7392         if (*p == '\\')
7393                 p++;
7394         if (*p == '.')
7395                 matchdot++;
7396         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7397                 if (dp->d_name[0] == '.' && !matchdot)
7398                         continue;
7399                 if (pmatch(start, dp->d_name)) {
7400                         if (atend) {
7401                                 strcpy(enddir, dp->d_name);
7402                                 addfname(expdir);
7403                         } else {
7404                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7405                                         continue;
7406                                 p[-1] = '/';
7407                                 expmeta(expdir, p, endname);
7408                         }
7409                 }
7410         }
7411         closedir(dirp);
7412         if (!atend)
7413                 endname[-esc - 1] = esc ? '\\' : '/';
7414 }
7415
7416 static struct strlist *
7417 msort(struct strlist *list, int len)
7418 {
7419         struct strlist *p, *q = NULL;
7420         struct strlist **lpp;
7421         int half;
7422         int n;
7423
7424         if (len <= 1)
7425                 return list;
7426         half = len >> 1;
7427         p = list;
7428         for (n = half; --n >= 0;) {
7429                 q = p;
7430                 p = p->next;
7431         }
7432         q->next = NULL;                 /* terminate first half of list */
7433         q = msort(list, half);          /* sort first half of list */
7434         p = msort(p, len - half);               /* sort second half */
7435         lpp = &list;
7436         for (;;) {
7437 #if ENABLE_LOCALE_SUPPORT
7438                 if (strcoll(p->text, q->text) < 0)
7439 #else
7440                 if (strcmp(p->text, q->text) < 0)
7441 #endif
7442                                                 {
7443                         *lpp = p;
7444                         lpp = &p->next;
7445                         p = *lpp;
7446                         if (p == NULL) {
7447                                 *lpp = q;
7448                                 break;
7449                         }
7450                 } else {
7451                         *lpp = q;
7452                         lpp = &q->next;
7453                         q = *lpp;
7454                         if (q == NULL) {
7455                                 *lpp = p;
7456                                 break;
7457                         }
7458                 }
7459         }
7460         return list;
7461 }
7462
7463 /*
7464  * Sort the results of file name expansion.  It calculates the number of
7465  * strings to sort and then calls msort (short for merge sort) to do the
7466  * work.
7467  */
7468 static struct strlist *
7469 expsort(struct strlist *str)
7470 {
7471         int len;
7472         struct strlist *sp;
7473
7474         len = 0;
7475         for (sp = str; sp; sp = sp->next)
7476                 len++;
7477         return msort(str, len);
7478 }
7479
7480 static void
7481 expandmeta(struct strlist *str /*, int flag*/)
7482 {
7483         /* TODO - EXP_REDIR */
7484
7485         while (str) {
7486                 char *expdir;
7487                 struct strlist **savelastp;
7488                 struct strlist *sp;
7489                 char *p;
7490
7491                 if (fflag)
7492                         goto nometa;
7493                 if (!hasmeta(str->text))
7494                         goto nometa;
7495                 savelastp = exparg.lastp;
7496
7497                 INT_OFF;
7498                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7499                 {
7500                         int i = strlen(str->text);
7501 //BUGGY estimation of how long expanded name can be
7502                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7503                 }
7504                 expmeta(expdir, expdir, p);
7505                 free(expdir);
7506                 if (p != str->text)
7507                         free(p);
7508                 INT_ON;
7509                 if (exparg.lastp == savelastp) {
7510                         /*
7511                          * no matches
7512                          */
7513  nometa:
7514                         *exparg.lastp = str;
7515                         rmescapes(str->text, 0);
7516                         exparg.lastp = &str->next;
7517                 } else {
7518                         *exparg.lastp = NULL;
7519                         *savelastp = sp = expsort(*savelastp);
7520                         while (sp->next != NULL)
7521                                 sp = sp->next;
7522                         exparg.lastp = &sp->next;
7523                 }
7524                 str = str->next;
7525         }
7526 }
7527 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7528
7529 /*
7530  * Perform variable substitution and command substitution on an argument,
7531  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7532  * perform splitting and file name expansion.  When arglist is NULL, perform
7533  * here document expansion.
7534  */
7535 static void
7536 expandarg(union node *arg, struct arglist *arglist, int flag)
7537 {
7538         struct strlist *sp;
7539         char *p;
7540
7541         argbackq = arg->narg.backquote;
7542         STARTSTACKSTR(expdest);
7543         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7544         argstr(arg->narg.text, flag,
7545                         /* var_str_list: */ arglist ? arglist->list : NULL);
7546         p = _STPUTC('\0', expdest);
7547         expdest = p - 1;
7548         if (arglist == NULL) {
7549                 /* here document expanded */
7550                 goto out;
7551         }
7552         p = grabstackstr(p);
7553         TRACE(("expandarg: p:'%s'\n", p));
7554         exparg.lastp = &exparg.list;
7555         /*
7556          * TODO - EXP_REDIR
7557          */
7558         if (flag & EXP_FULL) {
7559                 ifsbreakup(p, &exparg);
7560                 *exparg.lastp = NULL;
7561                 exparg.lastp = &exparg.list;
7562                 expandmeta(exparg.list /*, flag*/);
7563         } else {
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         char *p = preglob(pattern, 0);
7596         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7597         return pmatch(p, string);
7598 }
7599
7600 /*
7601  * See if a pattern matches in a case statement.
7602  */
7603 static int
7604 casematch(union node *pattern, char *val)
7605 {
7606         struct stackmark smark;
7607         int result;
7608
7609         setstackmark(&smark);
7610         argbackq = pattern->narg.backquote;
7611         STARTSTACKSTR(expdest);
7612         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7613                         /* var_str_list: */ NULL);
7614         STACKSTRNUL(expdest);
7615         ifsfree();
7616         result = patmatch(stackblock(), val);
7617         popstackmark(&smark);
7618         return result;
7619 }
7620
7621
7622 /* ============ find_command */
7623
7624 struct builtincmd {
7625         const char *name;
7626         int (*builtin)(int, char **) FAST_FUNC;
7627         /* unsigned flags; */
7628 };
7629 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7630 /* "regular" builtins always take precedence over commands,
7631  * regardless of PATH=....%builtin... position */
7632 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7633 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7634
7635 struct cmdentry {
7636         smallint cmdtype;       /* CMDxxx */
7637         union param {
7638                 int index;
7639                 /* index >= 0 for commands without path (slashes) */
7640                 /* (TODO: what exactly does the value mean? PATH position?) */
7641                 /* index == -1 for commands with slashes */
7642                 /* index == (-2 - applet_no) for NOFORK applets */
7643                 const struct builtincmd *cmd;
7644                 struct funcnode *func;
7645         } u;
7646 };
7647 /* values of cmdtype */
7648 #define CMDUNKNOWN      -1      /* no entry in table for command */
7649 #define CMDNORMAL       0       /* command is an executable program */
7650 #define CMDFUNCTION     1       /* command is a shell function */
7651 #define CMDBUILTIN      2       /* command is a shell builtin */
7652
7653 /* action to find_command() */
7654 #define DO_ERR          0x01    /* prints errors */
7655 #define DO_ABS          0x02    /* checks absolute paths */
7656 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7657 #define DO_ALTPATH      0x08    /* using alternate path */
7658 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7659
7660 static void find_command(char *, struct cmdentry *, int, const char *);
7661
7662
7663 /* ============ Hashing commands */
7664
7665 /*
7666  * When commands are first encountered, they are entered in a hash table.
7667  * This ensures that a full path search will not have to be done for them
7668  * on each invocation.
7669  *
7670  * We should investigate converting to a linear search, even though that
7671  * would make the command name "hash" a misnomer.
7672  */
7673
7674 struct tblentry {
7675         struct tblentry *next;  /* next entry in hash chain */
7676         union param param;      /* definition of builtin function */
7677         smallint cmdtype;       /* CMDxxx */
7678         char rehash;            /* if set, cd done since entry created */
7679         char cmdname[1];        /* name of command */
7680 };
7681
7682 static struct tblentry **cmdtable;
7683 #define INIT_G_cmdtable() do { \
7684         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7685 } while (0)
7686
7687 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7688
7689
7690 static void
7691 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7692 {
7693 #if ENABLE_FEATURE_SH_STANDALONE
7694         if (applet_no >= 0) {
7695                 if (APPLET_IS_NOEXEC(applet_no)) {
7696                         clearenv();
7697                         while (*envp)
7698                                 putenv(*envp++);
7699                         run_applet_no_and_exit(applet_no, cmd, argv);
7700                 }
7701                 /* re-exec ourselves with the new arguments */
7702                 execve(bb_busybox_exec_path, argv, envp);
7703                 /* If they called chroot or otherwise made the binary no longer
7704                  * executable, fall through */
7705         }
7706 #endif
7707
7708  repeat:
7709 #ifdef SYSV
7710         do {
7711                 execve(cmd, argv, envp);
7712         } while (errno == EINTR);
7713 #else
7714         execve(cmd, argv, envp);
7715 #endif
7716         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7717                 /* Run "cmd" as a shell script:
7718                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7719                  * "If the execve() function fails with ENOEXEC, the shell
7720                  * shall execute a command equivalent to having a shell invoked
7721                  * with the command name as its first operand,
7722                  * with any remaining arguments passed to the new shell"
7723                  *
7724                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7725                  * just call ourselves.
7726                  *
7727                  * Note that bash reads ~80 chars of the file, and if it sees
7728                  * a zero byte before it sees newline, it doesn't try to
7729                  * interpret it, but fails with "cannot execute binary file"
7730                  * message and exit code 126. For one, this prevents attempts
7731                  * to interpret foreign ELF binaries as shell scripts.
7732                  */
7733                 argv[0] = cmd;
7734                 cmd = (char*) bb_busybox_exec_path;
7735                 /* NB: this is only possible because all callers of shellexec()
7736                  * ensure that the argv[-1] slot exists!
7737                  */
7738                 argv--;
7739                 argv[0] = (char*) "ash";
7740                 goto repeat;
7741         }
7742 }
7743
7744 /*
7745  * Exec a program.  Never returns.  If you change this routine, you may
7746  * have to change the find_command routine as well.
7747  * argv[-1] must exist and be writable! See tryexec() for why.
7748  */
7749 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7750 static void shellexec(char *prog, char **argv, const char *path, int idx)
7751 {
7752         char *cmdname;
7753         int e;
7754         char **envp;
7755         int exerrno;
7756         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7757
7758         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7759         if (strchr(prog, '/') != NULL
7760 #if ENABLE_FEATURE_SH_STANDALONE
7761          || (applet_no = find_applet_by_name(prog)) >= 0
7762 #endif
7763         ) {
7764                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7765                 if (applet_no >= 0) {
7766                         /* We tried execing ourself, but it didn't work.
7767                          * Maybe /proc/self/exe doesn't exist?
7768                          * Try $PATH search.
7769                          */
7770                         goto try_PATH;
7771                 }
7772                 e = errno;
7773         } else {
7774  try_PATH:
7775                 e = ENOENT;
7776                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7777                         if (--idx < 0 && pathopt == NULL) {
7778                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7779                                 if (errno != ENOENT && errno != ENOTDIR)
7780                                         e = errno;
7781                         }
7782                         stunalloc(cmdname);
7783                 }
7784         }
7785
7786         /* Map to POSIX errors */
7787         switch (e) {
7788         case EACCES:
7789                 exerrno = 126;
7790                 break;
7791         case ENOENT:
7792                 exerrno = 127;
7793                 break;
7794         default:
7795                 exerrno = 2;
7796                 break;
7797         }
7798         exitstatus = exerrno;
7799         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7800                 prog, e, suppress_int));
7801         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7802         /* NOTREACHED */
7803 }
7804
7805 static void
7806 printentry(struct tblentry *cmdp)
7807 {
7808         int idx;
7809         const char *path;
7810         char *name;
7811
7812         idx = cmdp->param.index;
7813         path = pathval();
7814         do {
7815                 name = path_advance(&path, cmdp->cmdname);
7816                 stunalloc(name);
7817         } while (--idx >= 0);
7818         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7819 }
7820
7821 /*
7822  * Clear out command entries.  The argument specifies the first entry in
7823  * PATH which has changed.
7824  */
7825 static void
7826 clearcmdentry(int firstchange)
7827 {
7828         struct tblentry **tblp;
7829         struct tblentry **pp;
7830         struct tblentry *cmdp;
7831
7832         INT_OFF;
7833         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7834                 pp = tblp;
7835                 while ((cmdp = *pp) != NULL) {
7836                         if ((cmdp->cmdtype == CMDNORMAL &&
7837                              cmdp->param.index >= firstchange)
7838                          || (cmdp->cmdtype == CMDBUILTIN &&
7839                              builtinloc >= firstchange)
7840                         ) {
7841                                 *pp = cmdp->next;
7842                                 free(cmdp);
7843                         } else {
7844                                 pp = &cmdp->next;
7845                         }
7846                 }
7847         }
7848         INT_ON;
7849 }
7850
7851 /*
7852  * Locate a command in the command hash table.  If "add" is nonzero,
7853  * add the command to the table if it is not already present.  The
7854  * variable "lastcmdentry" is set to point to the address of the link
7855  * pointing to the entry, so that delete_cmd_entry can delete the
7856  * entry.
7857  *
7858  * Interrupts must be off if called with add != 0.
7859  */
7860 static struct tblentry **lastcmdentry;
7861
7862 static struct tblentry *
7863 cmdlookup(const char *name, int add)
7864 {
7865         unsigned int hashval;
7866         const char *p;
7867         struct tblentry *cmdp;
7868         struct tblentry **pp;
7869
7870         p = name;
7871         hashval = (unsigned char)*p << 4;
7872         while (*p)
7873                 hashval += (unsigned char)*p++;
7874         hashval &= 0x7FFF;
7875         pp = &cmdtable[hashval % CMDTABLESIZE];
7876         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7877                 if (strcmp(cmdp->cmdname, name) == 0)
7878                         break;
7879                 pp = &cmdp->next;
7880         }
7881         if (add && cmdp == NULL) {
7882                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7883                                 + strlen(name)
7884                                 /* + 1 - already done because
7885                                  * tblentry::cmdname is char[1] */);
7886                 /*cmdp->next = NULL; - ckzalloc did it */
7887                 cmdp->cmdtype = CMDUNKNOWN;
7888                 strcpy(cmdp->cmdname, name);
7889         }
7890         lastcmdentry = pp;
7891         return cmdp;
7892 }
7893
7894 /*
7895  * Delete the command entry returned on the last lookup.
7896  */
7897 static void
7898 delete_cmd_entry(void)
7899 {
7900         struct tblentry *cmdp;
7901
7902         INT_OFF;
7903         cmdp = *lastcmdentry;
7904         *lastcmdentry = cmdp->next;
7905         if (cmdp->cmdtype == CMDFUNCTION)
7906                 freefunc(cmdp->param.func);
7907         free(cmdp);
7908         INT_ON;
7909 }
7910
7911 /*
7912  * Add a new command entry, replacing any existing command entry for
7913  * the same name - except special builtins.
7914  */
7915 static void
7916 addcmdentry(char *name, struct cmdentry *entry)
7917 {
7918         struct tblentry *cmdp;
7919
7920         cmdp = cmdlookup(name, 1);
7921         if (cmdp->cmdtype == CMDFUNCTION) {
7922                 freefunc(cmdp->param.func);
7923         }
7924         cmdp->cmdtype = entry->cmdtype;
7925         cmdp->param = entry->u;
7926         cmdp->rehash = 0;
7927 }
7928
7929 static int FAST_FUNC
7930 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7931 {
7932         struct tblentry **pp;
7933         struct tblentry *cmdp;
7934         int c;
7935         struct cmdentry entry;
7936         char *name;
7937
7938         if (nextopt("r") != '\0') {
7939                 clearcmdentry(0);
7940                 return 0;
7941         }
7942
7943         if (*argptr == NULL) {
7944                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7945                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7946                                 if (cmdp->cmdtype == CMDNORMAL)
7947                                         printentry(cmdp);
7948                         }
7949                 }
7950                 return 0;
7951         }
7952
7953         c = 0;
7954         while ((name = *argptr) != NULL) {
7955                 cmdp = cmdlookup(name, 0);
7956                 if (cmdp != NULL
7957                  && (cmdp->cmdtype == CMDNORMAL
7958                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7959                 ) {
7960                         delete_cmd_entry();
7961                 }
7962                 find_command(name, &entry, DO_ERR, pathval());
7963                 if (entry.cmdtype == CMDUNKNOWN)
7964                         c = 1;
7965                 argptr++;
7966         }
7967         return c;
7968 }
7969
7970 /*
7971  * Called when a cd is done.  Marks all commands so the next time they
7972  * are executed they will be rehashed.
7973  */
7974 static void
7975 hashcd(void)
7976 {
7977         struct tblentry **pp;
7978         struct tblentry *cmdp;
7979
7980         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7981                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7982                         if (cmdp->cmdtype == CMDNORMAL
7983                          || (cmdp->cmdtype == CMDBUILTIN
7984                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7985                              && builtinloc > 0)
7986                         ) {
7987                                 cmdp->rehash = 1;
7988                         }
7989                 }
7990         }
7991 }
7992
7993 /*
7994  * Fix command hash table when PATH changed.
7995  * Called before PATH is changed.  The argument is the new value of PATH;
7996  * pathval() still returns the old value at this point.
7997  * Called with interrupts off.
7998  */
7999 static void FAST_FUNC
8000 changepath(const char *new)
8001 {
8002         const char *old;
8003         int firstchange;
8004         int idx;
8005         int idx_bltin;
8006
8007         old = pathval();
8008         firstchange = 9999;     /* assume no change */
8009         idx = 0;
8010         idx_bltin = -1;
8011         for (;;) {
8012                 if (*old != *new) {
8013                         firstchange = idx;
8014                         if ((*old == '\0' && *new == ':')
8015                          || (*old == ':' && *new == '\0')
8016                         ) {
8017                                 firstchange++;
8018                         }
8019                         old = new;      /* ignore subsequent differences */
8020                 }
8021                 if (*new == '\0')
8022                         break;
8023                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8024                         idx_bltin = idx;
8025                 if (*new == ':')
8026                         idx++;
8027                 new++;
8028                 old++;
8029         }
8030         if (builtinloc < 0 && idx_bltin >= 0)
8031                 builtinloc = idx_bltin;             /* zap builtins */
8032         if (builtinloc >= 0 && idx_bltin < 0)
8033                 firstchange = 0;
8034         clearcmdentry(firstchange);
8035         builtinloc = idx_bltin;
8036 }
8037 enum {
8038         TEOF,
8039         TNL,
8040         TREDIR,
8041         TWORD,
8042         TSEMI,
8043         TBACKGND,
8044         TAND,
8045         TOR,
8046         TPIPE,
8047         TLP,
8048         TRP,
8049         TENDCASE,
8050         TENDBQUOTE,
8051         TNOT,
8052         TCASE,
8053         TDO,
8054         TDONE,
8055         TELIF,
8056         TELSE,
8057         TESAC,
8058         TFI,
8059         TFOR,
8060 #if BASH_FUNCTION
8061         TFUNCTION,
8062 #endif
8063         TIF,
8064         TIN,
8065         TTHEN,
8066         TUNTIL,
8067         TWHILE,
8068         TBEGIN,
8069         TEND
8070 };
8071 typedef smallint token_id_t;
8072
8073 /* Nth bit indicates if token marks the end of a list */
8074 enum {
8075         tokendlist = 0
8076         /*  0 */ | (1u << TEOF)
8077         /*  1 */ | (0u << TNL)
8078         /*  2 */ | (0u << TREDIR)
8079         /*  3 */ | (0u << TWORD)
8080         /*  4 */ | (0u << TSEMI)
8081         /*  5 */ | (0u << TBACKGND)
8082         /*  6 */ | (0u << TAND)
8083         /*  7 */ | (0u << TOR)
8084         /*  8 */ | (0u << TPIPE)
8085         /*  9 */ | (0u << TLP)
8086         /* 10 */ | (1u << TRP)
8087         /* 11 */ | (1u << TENDCASE)
8088         /* 12 */ | (1u << TENDBQUOTE)
8089         /* 13 */ | (0u << TNOT)
8090         /* 14 */ | (0u << TCASE)
8091         /* 15 */ | (1u << TDO)
8092         /* 16 */ | (1u << TDONE)
8093         /* 17 */ | (1u << TELIF)
8094         /* 18 */ | (1u << TELSE)
8095         /* 19 */ | (1u << TESAC)
8096         /* 20 */ | (1u << TFI)
8097         /* 21 */ | (0u << TFOR)
8098 #if BASH_FUNCTION
8099         /* 22 */ | (0u << TFUNCTION)
8100 #endif
8101         /* 23 */ | (0u << TIF)
8102         /* 24 */ | (0u << TIN)
8103         /* 25 */ | (1u << TTHEN)
8104         /* 26 */ | (0u << TUNTIL)
8105         /* 27 */ | (0u << TWHILE)
8106         /* 28 */ | (0u << TBEGIN)
8107         /* 29 */ | (1u << TEND)
8108         , /* thus far 29 bits used */
8109 };
8110
8111 static const char *const tokname_array[] = {
8112         "end of file",
8113         "newline",
8114         "redirection",
8115         "word",
8116         ";",
8117         "&",
8118         "&&",
8119         "||",
8120         "|",
8121         "(",
8122         ")",
8123         ";;",
8124         "`",
8125 #define KWDOFFSET 13
8126         /* the following are keywords */
8127         "!",
8128         "case",
8129         "do",
8130         "done",
8131         "elif",
8132         "else",
8133         "esac",
8134         "fi",
8135         "for",
8136 #if BASH_FUNCTION
8137         "function",
8138 #endif
8139         "if",
8140         "in",
8141         "then",
8142         "until",
8143         "while",
8144         "{",
8145         "}",
8146 };
8147
8148 /* Wrapper around strcmp for qsort/bsearch/... */
8149 static int
8150 pstrcmp(const void *a, const void *b)
8151 {
8152         return strcmp((char*)a, *(char**)b);
8153 }
8154
8155 static const char *const *
8156 findkwd(const char *s)
8157 {
8158         return bsearch(s, tokname_array + KWDOFFSET,
8159                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8160                         sizeof(tokname_array[0]), pstrcmp);
8161 }
8162
8163 /*
8164  * Locate and print what a word is...
8165  */
8166 static int
8167 describe_command(char *command, const char *path, int describe_command_verbose)
8168 {
8169         struct cmdentry entry;
8170 #if ENABLE_ASH_ALIAS
8171         const struct alias *ap;
8172 #endif
8173
8174         path = path ? path : pathval();
8175
8176         if (describe_command_verbose) {
8177                 out1str(command);
8178         }
8179
8180         /* First look at the keywords */
8181         if (findkwd(command)) {
8182                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8183                 goto out;
8184         }
8185
8186 #if ENABLE_ASH_ALIAS
8187         /* Then look at the aliases */
8188         ap = lookupalias(command, 0);
8189         if (ap != NULL) {
8190                 if (!describe_command_verbose) {
8191                         out1str("alias ");
8192                         printalias(ap);
8193                         return 0;
8194                 }
8195                 out1fmt(" is an alias for %s", ap->val);
8196                 goto out;
8197         }
8198 #endif
8199         /* Brute force */
8200         find_command(command, &entry, DO_ABS, path);
8201
8202         switch (entry.cmdtype) {
8203         case CMDNORMAL: {
8204                 int j = entry.u.index;
8205                 char *p;
8206                 if (j < 0) {
8207                         p = command;
8208                 } else {
8209                         do {
8210                                 p = path_advance(&path, command);
8211                                 stunalloc(p);
8212                         } while (--j >= 0);
8213                 }
8214                 if (describe_command_verbose) {
8215                         out1fmt(" is %s", p);
8216                 } else {
8217                         out1str(p);
8218                 }
8219                 break;
8220         }
8221
8222         case CMDFUNCTION:
8223                 if (describe_command_verbose) {
8224                         out1str(" is a shell function");
8225                 } else {
8226                         out1str(command);
8227                 }
8228                 break;
8229
8230         case CMDBUILTIN:
8231                 if (describe_command_verbose) {
8232                         out1fmt(" is a %sshell builtin",
8233                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8234                                         "special " : nullstr
8235                         );
8236                 } else {
8237                         out1str(command);
8238                 }
8239                 break;
8240
8241         default:
8242                 if (describe_command_verbose) {
8243                         out1str(": not found\n");
8244                 }
8245                 return 127;
8246         }
8247  out:
8248         out1str("\n");
8249         return 0;
8250 }
8251
8252 static int FAST_FUNC
8253 typecmd(int argc UNUSED_PARAM, char **argv)
8254 {
8255         int i = 1;
8256         int err = 0;
8257         int verbose = 1;
8258
8259         /* type -p ... ? (we don't bother checking for 'p') */
8260         if (argv[1] && argv[1][0] == '-') {
8261                 i++;
8262                 verbose = 0;
8263         }
8264         while (argv[i]) {
8265                 err |= describe_command(argv[i++], NULL, verbose);
8266         }
8267         return err;
8268 }
8269
8270 #if ENABLE_ASH_CMDCMD
8271 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8272 static char **
8273 parse_command_args(char **argv, const char **path)
8274 {
8275         char *cp, c;
8276
8277         for (;;) {
8278                 cp = *++argv;
8279                 if (!cp)
8280                         return NULL;
8281                 if (*cp++ != '-')
8282                         break;
8283                 c = *cp++;
8284                 if (!c)
8285                         break;
8286                 if (c == '-' && !*cp) {
8287                         if (!*++argv)
8288                                 return NULL;
8289                         break;
8290                 }
8291                 do {
8292                         switch (c) {
8293                         case 'p':
8294                                 *path = bb_default_path;
8295                                 break;
8296                         default:
8297                                 /* run 'typecmd' for other options */
8298                                 return NULL;
8299                         }
8300                         c = *cp++;
8301                 } while (c);
8302         }
8303         return argv;
8304 }
8305
8306 static int FAST_FUNC
8307 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8308 {
8309         char *cmd;
8310         int c;
8311         enum {
8312                 VERIFY_BRIEF = 1,
8313                 VERIFY_VERBOSE = 2,
8314         } verify = 0;
8315         const char *path = NULL;
8316
8317         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8318          * never reaches this function.
8319          */
8320
8321         while ((c = nextopt("pvV")) != '\0')
8322                 if (c == 'V')
8323                         verify |= VERIFY_VERBOSE;
8324                 else if (c == 'v')
8325                         /*verify |= VERIFY_BRIEF*/;
8326 #if DEBUG
8327                 else if (c != 'p')
8328                         abort();
8329 #endif
8330                 else
8331                         path = bb_default_path;
8332
8333         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8334         cmd = *argptr;
8335         if (/*verify && */ cmd)
8336                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8337
8338         return 0;
8339 }
8340 #endif
8341
8342
8343 /*static int funcblocksize;     // size of structures in function */
8344 /*static int funcstringsize;    // size of strings in node */
8345 static void *funcblock;         /* block to allocate function from */
8346 static char *funcstring_end;    /* end of block to allocate strings from */
8347
8348 /* flags in argument to evaltree */
8349 #define EV_EXIT    01           /* exit after evaluating tree */
8350 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
8351
8352 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8353         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8354         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8355         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8356         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8357         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8358         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8359         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8360         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8361         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8362         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8363         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8364         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8365         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8366         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8367         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8368         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8369         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8370 #if BASH_REDIR_OUTPUT
8371         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8372 #endif
8373         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8374         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8375         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8376         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8377         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8378         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8379         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8380         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8381         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8382 };
8383
8384 static int calcsize(int funcblocksize, union node *n);
8385
8386 static int
8387 sizenodelist(int funcblocksize, struct nodelist *lp)
8388 {
8389         while (lp) {
8390                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8391                 funcblocksize = calcsize(funcblocksize, lp->n);
8392                 lp = lp->next;
8393         }
8394         return funcblocksize;
8395 }
8396
8397 static int
8398 calcsize(int funcblocksize, union node *n)
8399 {
8400         if (n == NULL)
8401                 return funcblocksize;
8402         funcblocksize += nodesize[n->type];
8403         switch (n->type) {
8404         case NCMD:
8405                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8406                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8407                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8408                 break;
8409         case NPIPE:
8410                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8411                 break;
8412         case NREDIR:
8413         case NBACKGND:
8414         case NSUBSHELL:
8415                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8416                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8417                 break;
8418         case NAND:
8419         case NOR:
8420         case NSEMI:
8421         case NWHILE:
8422         case NUNTIL:
8423                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8424                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8425                 break;
8426         case NIF:
8427                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8428                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8429                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8430                 break;
8431         case NFOR:
8432                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8433                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8434                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8435                 break;
8436         case NCASE:
8437                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8438                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8439                 break;
8440         case NCLIST:
8441                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8442                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8443                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8444                 break;
8445         case NDEFUN:
8446         case NARG:
8447                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8448                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8449                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8450                 break;
8451         case NTO:
8452 #if BASH_REDIR_OUTPUT
8453         case NTO2:
8454 #endif
8455         case NCLOBBER:
8456         case NFROM:
8457         case NFROMTO:
8458         case NAPPEND:
8459                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8460                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8461                 break;
8462         case NTOFD:
8463         case NFROMFD:
8464                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8465                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8466         break;
8467         case NHERE:
8468         case NXHERE:
8469                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8470                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8471                 break;
8472         case NNOT:
8473                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8474                 break;
8475         };
8476         return funcblocksize;
8477 }
8478
8479 static char *
8480 nodeckstrdup(char *s)
8481 {
8482         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8483         return strcpy(funcstring_end, s);
8484 }
8485
8486 static union node *copynode(union node *);
8487
8488 static struct nodelist *
8489 copynodelist(struct nodelist *lp)
8490 {
8491         struct nodelist *start;
8492         struct nodelist **lpp;
8493
8494         lpp = &start;
8495         while (lp) {
8496                 *lpp = funcblock;
8497                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8498                 (*lpp)->n = copynode(lp->n);
8499                 lp = lp->next;
8500                 lpp = &(*lpp)->next;
8501         }
8502         *lpp = NULL;
8503         return start;
8504 }
8505
8506 static union node *
8507 copynode(union node *n)
8508 {
8509         union node *new;
8510
8511         if (n == NULL)
8512                 return NULL;
8513         new = funcblock;
8514         funcblock = (char *) funcblock + nodesize[n->type];
8515
8516         switch (n->type) {
8517         case NCMD:
8518                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8519                 new->ncmd.args = copynode(n->ncmd.args);
8520                 new->ncmd.assign = copynode(n->ncmd.assign);
8521                 break;
8522         case NPIPE:
8523                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8524                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8525                 break;
8526         case NREDIR:
8527         case NBACKGND:
8528         case NSUBSHELL:
8529                 new->nredir.redirect = copynode(n->nredir.redirect);
8530                 new->nredir.n = copynode(n->nredir.n);
8531                 break;
8532         case NAND:
8533         case NOR:
8534         case NSEMI:
8535         case NWHILE:
8536         case NUNTIL:
8537                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8538                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8539                 break;
8540         case NIF:
8541                 new->nif.elsepart = copynode(n->nif.elsepart);
8542                 new->nif.ifpart = copynode(n->nif.ifpart);
8543                 new->nif.test = copynode(n->nif.test);
8544                 break;
8545         case NFOR:
8546                 new->nfor.var = nodeckstrdup(n->nfor.var);
8547                 new->nfor.body = copynode(n->nfor.body);
8548                 new->nfor.args = copynode(n->nfor.args);
8549                 break;
8550         case NCASE:
8551                 new->ncase.cases = copynode(n->ncase.cases);
8552                 new->ncase.expr = copynode(n->ncase.expr);
8553                 break;
8554         case NCLIST:
8555                 new->nclist.body = copynode(n->nclist.body);
8556                 new->nclist.pattern = copynode(n->nclist.pattern);
8557                 new->nclist.next = copynode(n->nclist.next);
8558                 break;
8559         case NDEFUN:
8560         case NARG:
8561                 new->narg.backquote = copynodelist(n->narg.backquote);
8562                 new->narg.text = nodeckstrdup(n->narg.text);
8563                 new->narg.next = copynode(n->narg.next);
8564                 break;
8565         case NTO:
8566 #if BASH_REDIR_OUTPUT
8567         case NTO2:
8568 #endif
8569         case NCLOBBER:
8570         case NFROM:
8571         case NFROMTO:
8572         case NAPPEND:
8573                 new->nfile.fname = copynode(n->nfile.fname);
8574                 new->nfile.fd = n->nfile.fd;
8575                 new->nfile.next = copynode(n->nfile.next);
8576                 break;
8577         case NTOFD:
8578         case NFROMFD:
8579                 new->ndup.vname = copynode(n->ndup.vname);
8580                 new->ndup.dupfd = n->ndup.dupfd;
8581                 new->ndup.fd = n->ndup.fd;
8582                 new->ndup.next = copynode(n->ndup.next);
8583                 break;
8584         case NHERE:
8585         case NXHERE:
8586                 new->nhere.doc = copynode(n->nhere.doc);
8587                 new->nhere.fd = n->nhere.fd;
8588                 new->nhere.next = copynode(n->nhere.next);
8589                 break;
8590         case NNOT:
8591                 new->nnot.com = copynode(n->nnot.com);
8592                 break;
8593         };
8594         new->type = n->type;
8595         return new;
8596 }
8597
8598 /*
8599  * Make a copy of a parse tree.
8600  */
8601 static struct funcnode *
8602 copyfunc(union node *n)
8603 {
8604         struct funcnode *f;
8605         size_t blocksize;
8606
8607         /*funcstringsize = 0;*/
8608         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8609         f = ckzalloc(blocksize /* + funcstringsize */);
8610         funcblock = (char *) f + offsetof(struct funcnode, n);
8611         funcstring_end = (char *) f + blocksize;
8612         copynode(n);
8613         /* f->count = 0; - ckzalloc did it */
8614         return f;
8615 }
8616
8617 /*
8618  * Define a shell function.
8619  */
8620 static void
8621 defun(union node *func)
8622 {
8623         struct cmdentry entry;
8624
8625         INT_OFF;
8626         entry.cmdtype = CMDFUNCTION;
8627         entry.u.func = copyfunc(func);
8628         addcmdentry(func->narg.text, &entry);
8629         INT_ON;
8630 }
8631
8632 /* Reasons for skipping commands (see comment on breakcmd routine) */
8633 #define SKIPBREAK      (1 << 0)
8634 #define SKIPCONT       (1 << 1)
8635 #define SKIPFUNC       (1 << 2)
8636 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8637 static int skipcount;           /* number of levels to skip */
8638 static int funcnest;            /* depth of function calls */
8639 static int loopnest;            /* current loop nesting level */
8640
8641 /* Forward decl way out to parsing code - dotrap needs it */
8642 static int evalstring(char *s, int flags);
8643
8644 /* Called to execute a trap.
8645  * Single callsite - at the end of evaltree().
8646  * If we return non-zero, evaltree raises EXEXIT exception.
8647  *
8648  * Perhaps we should avoid entering new trap handlers
8649  * while we are executing a trap handler. [is it a TODO?]
8650  */
8651 static void
8652 dotrap(void)
8653 {
8654         uint8_t *g;
8655         int sig;
8656         uint8_t last_status;
8657
8658         if (!pending_sig)
8659                 return;
8660
8661         last_status = exitstatus;
8662         pending_sig = 0;
8663         barrier();
8664
8665         TRACE(("dotrap entered\n"));
8666         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8667                 char *p;
8668
8669                 if (!*g)
8670                         continue;
8671
8672                 if (evalskip) {
8673                         pending_sig = sig;
8674                         break;
8675                 }
8676
8677                 p = trap[sig];
8678                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8679                  * don't upset it by resetting gotsig[SIGINT-1] */
8680                 if (sig == SIGINT && !p)
8681                         continue;
8682
8683                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8684                 *g = 0;
8685                 if (!p)
8686                         continue;
8687                 evalstring(p, 0);
8688         }
8689         exitstatus = last_status;
8690         TRACE(("dotrap returns\n"));
8691 }
8692
8693 /* forward declarations - evaluation is fairly recursive business... */
8694 static int evalloop(union node *, int);
8695 static int evalfor(union node *, int);
8696 static int evalcase(union node *, int);
8697 static int evalsubshell(union node *, int);
8698 static void expredir(union node *);
8699 static int evalpipe(union node *, int);
8700 static int evalcommand(union node *, int);
8701 static int evalbltin(const struct builtincmd *, int, char **, int);
8702 static void prehash(union node *);
8703
8704 /*
8705  * Evaluate a parse tree.  The value is left in the global variable
8706  * exitstatus.
8707  */
8708 static int
8709 evaltree(union node *n, int flags)
8710 {
8711         int checkexit = 0;
8712         int (*evalfn)(union node *, int);
8713         int status = 0;
8714
8715         if (n == NULL) {
8716                 TRACE(("evaltree(NULL) called\n"));
8717                 goto out;
8718         }
8719         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8720
8721         dotrap();
8722
8723         switch (n->type) {
8724         default:
8725 #if DEBUG
8726                 out1fmt("Node type = %d\n", n->type);
8727                 fflush_all();
8728                 break;
8729 #endif
8730         case NNOT:
8731                 status = !evaltree(n->nnot.com, EV_TESTED);
8732                 goto setstatus;
8733         case NREDIR:
8734                 expredir(n->nredir.redirect);
8735                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8736                 if (!status) {
8737                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8738                 }
8739                 if (n->nredir.redirect)
8740                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8741                 goto setstatus;
8742         case NCMD:
8743                 evalfn = evalcommand;
8744  checkexit:
8745                 if (eflag && !(flags & EV_TESTED))
8746                         checkexit = ~0;
8747                 goto calleval;
8748         case NFOR:
8749                 evalfn = evalfor;
8750                 goto calleval;
8751         case NWHILE:
8752         case NUNTIL:
8753                 evalfn = evalloop;
8754                 goto calleval;
8755         case NSUBSHELL:
8756         case NBACKGND:
8757                 evalfn = evalsubshell;
8758                 goto checkexit;
8759         case NPIPE:
8760                 evalfn = evalpipe;
8761                 goto checkexit;
8762         case NCASE:
8763                 evalfn = evalcase;
8764                 goto calleval;
8765         case NAND:
8766         case NOR:
8767         case NSEMI: {
8768
8769 #if NAND + 1 != NOR
8770 #error NAND + 1 != NOR
8771 #endif
8772 #if NOR + 1 != NSEMI
8773 #error NOR + 1 != NSEMI
8774 #endif
8775                 unsigned is_or = n->type - NAND;
8776                 status = evaltree(
8777                         n->nbinary.ch1,
8778                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8779                 );
8780                 if ((!status) == is_or || evalskip)
8781                         break;
8782                 n = n->nbinary.ch2;
8783  evaln:
8784                 evalfn = evaltree;
8785  calleval:
8786                 status = evalfn(n, flags);
8787                 goto setstatus;
8788         }
8789         case NIF:
8790                 status = evaltree(n->nif.test, EV_TESTED);
8791                 if (evalskip)
8792                         break;
8793                 if (!status) {
8794                         n = n->nif.ifpart;
8795                         goto evaln;
8796                 }
8797                 if (n->nif.elsepart) {
8798                         n = n->nif.elsepart;
8799                         goto evaln;
8800                 }
8801                 status = 0;
8802                 goto setstatus;
8803         case NDEFUN:
8804                 defun(n);
8805                 /* Not necessary. To test it:
8806                  * "false; f() { qwerty; }; echo $?" should print 0.
8807                  */
8808                 /* status = 0; */
8809  setstatus:
8810                 exitstatus = status;
8811                 break;
8812         }
8813  out:
8814         /* Order of checks below is important:
8815          * signal handlers trigger before exit caused by "set -e".
8816          */
8817         dotrap();
8818
8819         if (checkexit & status)
8820                 raise_exception(EXEXIT);
8821         if (flags & EV_EXIT)
8822                 raise_exception(EXEXIT);
8823
8824         TRACE(("leaving evaltree (no interrupts)\n"));
8825         return exitstatus;
8826 }
8827
8828 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8829 static
8830 #endif
8831 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8832
8833 static int
8834 skiploop(void)
8835 {
8836         int skip = evalskip;
8837
8838         switch (skip) {
8839         case 0:
8840                 break;
8841         case SKIPBREAK:
8842         case SKIPCONT:
8843                 if (--skipcount <= 0) {
8844                         evalskip = 0;
8845                         break;
8846                 }
8847                 skip = SKIPBREAK;
8848                 break;
8849         }
8850         return skip;
8851 }
8852
8853 static int
8854 evalloop(union node *n, int flags)
8855 {
8856         int skip;
8857         int status;
8858
8859         loopnest++;
8860         status = 0;
8861         flags &= EV_TESTED;
8862         do {
8863                 int i;
8864
8865                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8866                 skip = skiploop();
8867                 if (skip == SKIPFUNC)
8868                         status = i;
8869                 if (skip)
8870                         continue;
8871                 if (n->type != NWHILE)
8872                         i = !i;
8873                 if (i != 0)
8874                         break;
8875                 status = evaltree(n->nbinary.ch2, flags);
8876                 skip = skiploop();
8877         } while (!(skip & ~SKIPCONT));
8878         loopnest--;
8879
8880         return status;
8881 }
8882
8883 static int
8884 evalfor(union node *n, int flags)
8885 {
8886         struct arglist arglist;
8887         union node *argp;
8888         struct strlist *sp;
8889         struct stackmark smark;
8890         int status = 0;
8891
8892         setstackmark(&smark);
8893         arglist.list = NULL;
8894         arglist.lastp = &arglist.list;
8895         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8896                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8897         }
8898         *arglist.lastp = NULL;
8899
8900         loopnest++;
8901         flags &= EV_TESTED;
8902         for (sp = arglist.list; sp; sp = sp->next) {
8903                 setvar0(n->nfor.var, sp->text);
8904                 status = evaltree(n->nfor.body, flags);
8905                 if (skiploop() & ~SKIPCONT)
8906                         break;
8907         }
8908         loopnest--;
8909         popstackmark(&smark);
8910
8911         return status;
8912 }
8913
8914 static int
8915 evalcase(union node *n, int flags)
8916 {
8917         union node *cp;
8918         union node *patp;
8919         struct arglist arglist;
8920         struct stackmark smark;
8921         int status = 0;
8922
8923         setstackmark(&smark);
8924         arglist.list = NULL;
8925         arglist.lastp = &arglist.list;
8926         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8927         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8928                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8929                         if (casematch(patp, arglist.list->text)) {
8930                                 /* Ensure body is non-empty as otherwise
8931                                  * EV_EXIT may prevent us from setting the
8932                                  * exit status.
8933                                  */
8934                                 if (evalskip == 0 && cp->nclist.body) {
8935                                         status = evaltree(cp->nclist.body, flags);
8936                                 }
8937                                 goto out;
8938                         }
8939                 }
8940         }
8941  out:
8942         popstackmark(&smark);
8943
8944         return status;
8945 }
8946
8947 /*
8948  * Kick off a subshell to evaluate a tree.
8949  */
8950 static int
8951 evalsubshell(union node *n, int flags)
8952 {
8953         struct job *jp;
8954         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8955         int status;
8956
8957         expredir(n->nredir.redirect);
8958         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8959                 goto nofork;
8960         INT_OFF;
8961         if (backgnd == FORK_FG)
8962                 get_tty_state();
8963         jp = makejob(/*n,*/ 1);
8964         if (forkshell(jp, n, backgnd) == 0) {
8965                 /* child */
8966                 INT_ON;
8967                 flags |= EV_EXIT;
8968                 if (backgnd)
8969                         flags &= ~EV_TESTED;
8970  nofork:
8971                 redirect(n->nredir.redirect, 0);
8972                 evaltreenr(n->nredir.n, flags);
8973                 /* never returns */
8974         }
8975         /* parent */
8976         status = 0;
8977         if (backgnd == FORK_FG)
8978                 status = waitforjob(jp);
8979         INT_ON;
8980         return status;
8981 }
8982
8983 /*
8984  * Compute the names of the files in a redirection list.
8985  */
8986 static void fixredir(union node *, const char *, int);
8987 static void
8988 expredir(union node *n)
8989 {
8990         union node *redir;
8991
8992         for (redir = n; redir; redir = redir->nfile.next) {
8993                 struct arglist fn;
8994
8995                 fn.list = NULL;
8996                 fn.lastp = &fn.list;
8997                 switch (redir->type) {
8998                 case NFROMTO:
8999                 case NFROM:
9000                 case NTO:
9001 #if BASH_REDIR_OUTPUT
9002                 case NTO2:
9003 #endif
9004                 case NCLOBBER:
9005                 case NAPPEND:
9006                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9007                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9008 #if BASH_REDIR_OUTPUT
9009  store_expfname:
9010 #endif
9011 #if 0
9012 // By the design of stack allocator, the loop of this kind:
9013 //      while true; do while true; do break; done </dev/null; done
9014 // will look like a memory leak: ash plans to free expfname's
9015 // of "/dev/null" as soon as it finishes running the loop
9016 // (in this case, never).
9017 // This "fix" is wrong:
9018                         if (redir->nfile.expfname)
9019                                 stunalloc(redir->nfile.expfname);
9020 // It results in corrupted state of stacked allocations.
9021 #endif
9022                         redir->nfile.expfname = fn.list->text;
9023                         break;
9024                 case NFROMFD:
9025                 case NTOFD: /* >& */
9026                         if (redir->ndup.vname) {
9027                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9028                                 if (fn.list == NULL)
9029                                         ash_msg_and_raise_error("redir error");
9030 #if BASH_REDIR_OUTPUT
9031 //FIXME: we used expandarg with different args!
9032                                 if (!isdigit_str9(fn.list->text)) {
9033                                         /* >&file, not >&fd */
9034                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9035                                                 ash_msg_and_raise_error("redir error");
9036                                         redir->type = NTO2;
9037                                         goto store_expfname;
9038                                 }
9039 #endif
9040                                 fixredir(redir, fn.list->text, 1);
9041                         }
9042                         break;
9043                 }
9044         }
9045 }
9046
9047 /*
9048  * Evaluate a pipeline.  All the processes in the pipeline are children
9049  * of the process creating the pipeline.  (This differs from some versions
9050  * of the shell, which make the last process in a pipeline the parent
9051  * of all the rest.)
9052  */
9053 static int
9054 evalpipe(union node *n, int flags)
9055 {
9056         struct job *jp;
9057         struct nodelist *lp;
9058         int pipelen;
9059         int prevfd;
9060         int pip[2];
9061         int status = 0;
9062
9063         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9064         pipelen = 0;
9065         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9066                 pipelen++;
9067         flags |= EV_EXIT;
9068         INT_OFF;
9069         if (n->npipe.pipe_backgnd == 0)
9070                 get_tty_state();
9071         jp = makejob(/*n,*/ pipelen);
9072         prevfd = -1;
9073         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9074                 prehash(lp->n);
9075                 pip[1] = -1;
9076                 if (lp->next) {
9077                         if (pipe(pip) < 0) {
9078                                 close(prevfd);
9079                                 ash_msg_and_raise_error("pipe call failed");
9080                         }
9081                 }
9082                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9083                         /* child */
9084                         INT_ON;
9085                         if (pip[1] >= 0) {
9086                                 close(pip[0]);
9087                         }
9088                         if (prevfd > 0) {
9089                                 dup2(prevfd, 0);
9090                                 close(prevfd);
9091                         }
9092                         if (pip[1] > 1) {
9093                                 dup2(pip[1], 1);
9094                                 close(pip[1]);
9095                         }
9096                         evaltreenr(lp->n, flags);
9097                         /* never returns */
9098                 }
9099                 /* parent */
9100                 if (prevfd >= 0)
9101                         close(prevfd);
9102                 prevfd = pip[0];
9103                 /* Don't want to trigger debugging */
9104                 if (pip[1] != -1)
9105                         close(pip[1]);
9106         }
9107         if (n->npipe.pipe_backgnd == 0) {
9108                 status = waitforjob(jp);
9109                 TRACE(("evalpipe:  job done exit status %d\n", status));
9110         }
9111         INT_ON;
9112
9113         return status;
9114 }
9115
9116 /*
9117  * Controls whether the shell is interactive or not.
9118  */
9119 static void
9120 setinteractive(int on)
9121 {
9122         static smallint is_interactive;
9123
9124         if (++on == is_interactive)
9125                 return;
9126         is_interactive = on;
9127         setsignal(SIGINT);
9128         setsignal(SIGQUIT);
9129         setsignal(SIGTERM);
9130 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9131         if (is_interactive > 1) {
9132                 /* Looks like they want an interactive shell */
9133                 static smallint did_banner;
9134
9135                 if (!did_banner) {
9136                         /* note: ash and hush share this string */
9137                         out1fmt("\n\n%s %s\n"
9138                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9139                                 "\n",
9140                                 bb_banner,
9141                                 "built-in shell (ash)"
9142                         );
9143                         did_banner = 1;
9144                 }
9145         }
9146 #endif
9147 }
9148
9149 static void
9150 optschanged(void)
9151 {
9152 #if DEBUG
9153         opentrace();
9154 #endif
9155         setinteractive(iflag);
9156         setjobctl(mflag);
9157 #if ENABLE_FEATURE_EDITING_VI
9158         if (viflag)
9159                 line_input_state->flags |= VI_MODE;
9160         else
9161                 line_input_state->flags &= ~VI_MODE;
9162 #else
9163         viflag = 0; /* forcibly keep the option off */
9164 #endif
9165 }
9166
9167 static struct localvar *localvars;
9168
9169 /*
9170  * Called after a function returns.
9171  * Interrupts must be off.
9172  */
9173 static void
9174 poplocalvars(void)
9175 {
9176         struct localvar *lvp;
9177         struct var *vp;
9178
9179         while ((lvp = localvars) != NULL) {
9180                 localvars = lvp->next;
9181                 vp = lvp->vp;
9182                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9183                 if (vp == NULL) {       /* $- saved */
9184                         memcpy(optlist, lvp->text, sizeof(optlist));
9185                         free((char*)lvp->text);
9186                         optschanged();
9187                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
9188                         unsetvar(vp->var_text);
9189                 } else {
9190                         if (vp->var_func)
9191                                 vp->var_func(var_end(lvp->text));
9192                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9193                                 free((char*)vp->var_text);
9194                         vp->flags = lvp->flags;
9195                         vp->var_text = lvp->text;
9196                 }
9197                 free(lvp);
9198         }
9199 }
9200
9201 static int
9202 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9203 {
9204         volatile struct shparam saveparam;
9205         struct localvar *volatile savelocalvars;
9206         struct jmploc *volatile savehandler;
9207         struct jmploc jmploc;
9208         int e;
9209
9210         saveparam = shellparam;
9211         savelocalvars = localvars;
9212         savehandler = exception_handler;
9213         e = setjmp(jmploc.loc);
9214         if (e) {
9215                 goto funcdone;
9216         }
9217         INT_OFF;
9218         exception_handler = &jmploc;
9219         localvars = NULL;
9220         shellparam.malloced = 0;
9221         func->count++;
9222         funcnest++;
9223         INT_ON;
9224         shellparam.nparam = argc - 1;
9225         shellparam.p = argv + 1;
9226 #if ENABLE_ASH_GETOPTS
9227         shellparam.optind = 1;
9228         shellparam.optoff = -1;
9229 #endif
9230         evaltree(func->n.narg.next, flags & EV_TESTED);
9231  funcdone:
9232         INT_OFF;
9233         funcnest--;
9234         freefunc(func);
9235         poplocalvars();
9236         localvars = savelocalvars;
9237         freeparam(&shellparam);
9238         shellparam = saveparam;
9239         exception_handler = savehandler;
9240         INT_ON;
9241         evalskip &= ~SKIPFUNC;
9242         return e;
9243 }
9244
9245 /*
9246  * Make a variable a local variable.  When a variable is made local, it's
9247  * value and flags are saved in a localvar structure.  The saved values
9248  * will be restored when the shell function returns.  We handle the name
9249  * "-" as a special case: it makes changes to "set +-options" local
9250  * (options will be restored on return from the function).
9251  */
9252 static void
9253 mklocal(char *name)
9254 {
9255         struct localvar *lvp;
9256         struct var **vpp;
9257         struct var *vp;
9258         char *eq = strchr(name, '=');
9259
9260         INT_OFF;
9261         /* Cater for duplicate "local". Examples:
9262          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9263          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9264          */
9265         lvp = localvars;
9266         while (lvp) {
9267                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9268                         if (eq)
9269                                 setvareq(name, 0);
9270                         /* else:
9271                          * it's a duplicate "local VAR" declaration, do nothing
9272                          */
9273                         goto ret;
9274                 }
9275                 lvp = lvp->next;
9276         }
9277
9278         lvp = ckzalloc(sizeof(*lvp));
9279         if (LONE_DASH(name)) {
9280                 char *p;
9281                 p = ckmalloc(sizeof(optlist));
9282                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9283                 vp = NULL;
9284         } else {
9285                 vpp = hashvar(name);
9286                 vp = *findvar(vpp, name);
9287                 if (vp == NULL) {
9288                         /* variable did not exist yet */
9289                         if (eq)
9290                                 setvareq(name, VSTRFIXED);
9291                         else
9292                                 setvar(name, NULL, VSTRFIXED);
9293                         vp = *vpp;      /* the new variable */
9294                         lvp->flags = VUNSET;
9295                 } else {
9296                         lvp->text = vp->var_text;
9297                         lvp->flags = vp->flags;
9298                         /* make sure neither "struct var" nor string gets freed
9299                          * during (un)setting:
9300                          */
9301                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9302                         if (eq)
9303                                 setvareq(name, 0);
9304                         else
9305                                 /* "local VAR" unsets VAR: */
9306                                 setvar0(name, NULL);
9307                 }
9308         }
9309         lvp->vp = vp;
9310         lvp->next = localvars;
9311         localvars = lvp;
9312  ret:
9313         INT_ON;
9314 }
9315
9316 /*
9317  * The "local" command.
9318  */
9319 static int FAST_FUNC
9320 localcmd(int argc UNUSED_PARAM, char **argv)
9321 {
9322         char *name;
9323
9324         if (!funcnest)
9325                 ash_msg_and_raise_error("not in a function");
9326
9327         argv = argptr;
9328         while ((name = *argv++) != NULL) {
9329                 mklocal(name);
9330         }
9331         return 0;
9332 }
9333
9334 static int FAST_FUNC
9335 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9336 {
9337         return 1;
9338 }
9339
9340 static int FAST_FUNC
9341 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9342 {
9343         return 0;
9344 }
9345
9346 static int FAST_FUNC
9347 execcmd(int argc UNUSED_PARAM, char **argv)
9348 {
9349         optionarg = NULL;
9350         while (nextopt("a:") != '\0')
9351                 /* nextopt() sets optionarg to "-a ARGV0" */;
9352
9353         argv = argptr;
9354         if (argv[0]) {
9355                 char *prog;
9356
9357                 iflag = 0;              /* exit on error */
9358                 mflag = 0;
9359                 optschanged();
9360                 /* We should set up signals for "exec CMD"
9361                  * the same way as for "CMD" without "exec".
9362                  * But optschanged->setinteractive->setsignal
9363                  * still thought we are a root shell. Therefore, for example,
9364                  * SIGQUIT is still set to IGN. Fix it:
9365                  */
9366                 shlvl++;
9367                 setsignal(SIGQUIT);
9368                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9369                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9370                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9371
9372                 prog = argv[0];
9373                 if (optionarg)
9374                         argv[0] = optionarg;
9375                 shellexec(prog, argv, pathval(), 0);
9376                 /* NOTREACHED */
9377         }
9378         return 0;
9379 }
9380
9381 /*
9382  * The return command.
9383  */
9384 static int FAST_FUNC
9385 returncmd(int argc UNUSED_PARAM, char **argv)
9386 {
9387         /*
9388          * If called outside a function, do what ksh does;
9389          * skip the rest of the file.
9390          */
9391         evalskip = SKIPFUNC;
9392         return argv[1] ? number(argv[1]) : exitstatus;
9393 }
9394
9395 /* Forward declarations for builtintab[] */
9396 static int breakcmd(int, char **) FAST_FUNC;
9397 static int dotcmd(int, char **) FAST_FUNC;
9398 static int evalcmd(int, char **, int) FAST_FUNC;
9399 static int exitcmd(int, char **) FAST_FUNC;
9400 static int exportcmd(int, char **) FAST_FUNC;
9401 #if ENABLE_ASH_GETOPTS
9402 static int getoptscmd(int, char **) FAST_FUNC;
9403 #endif
9404 #if ENABLE_ASH_HELP
9405 static int helpcmd(int, char **) FAST_FUNC;
9406 #endif
9407 #if MAX_HISTORY
9408 static int historycmd(int, char **) FAST_FUNC;
9409 #endif
9410 #if ENABLE_FEATURE_SH_MATH
9411 static int letcmd(int, char **) FAST_FUNC;
9412 #endif
9413 static int readcmd(int, char **) FAST_FUNC;
9414 static int setcmd(int, char **) FAST_FUNC;
9415 static int shiftcmd(int, char **) FAST_FUNC;
9416 static int timescmd(int, char **) FAST_FUNC;
9417 static int trapcmd(int, char **) FAST_FUNC;
9418 static int umaskcmd(int, char **) FAST_FUNC;
9419 static int unsetcmd(int, char **) FAST_FUNC;
9420 static int ulimitcmd(int, char **) FAST_FUNC;
9421
9422 #define BUILTIN_NOSPEC          "0"
9423 #define BUILTIN_SPECIAL         "1"
9424 #define BUILTIN_REGULAR         "2"
9425 #define BUILTIN_SPEC_REG        "3"
9426 #define BUILTIN_ASSIGN          "4"
9427 #define BUILTIN_SPEC_ASSG       "5"
9428 #define BUILTIN_REG_ASSG        "6"
9429 #define BUILTIN_SPEC_REG_ASSG   "7"
9430
9431 /* Stubs for calling non-FAST_FUNC's */
9432 #if ENABLE_ASH_ECHO
9433 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9434 #endif
9435 #if ENABLE_ASH_PRINTF
9436 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9437 #endif
9438 #if ENABLE_ASH_TEST || BASH_TEST2
9439 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9440 #endif
9441
9442 /* Keep these in proper order since it is searched via bsearch() */
9443 static const struct builtincmd builtintab[] = {
9444         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9445         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9446 #if ENABLE_ASH_TEST
9447         { BUILTIN_REGULAR       "["       , testcmd    },
9448 #endif
9449 #if BASH_TEST2
9450         { BUILTIN_REGULAR       "[["      , testcmd    },
9451 #endif
9452 #if ENABLE_ASH_ALIAS
9453         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9454 #endif
9455 #if JOBS
9456         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9457 #endif
9458         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9459         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9460         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9461 #if ENABLE_ASH_CMDCMD
9462         { BUILTIN_REGULAR       "command" , commandcmd },
9463 #endif
9464         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9465 #if ENABLE_ASH_ECHO
9466         { BUILTIN_REGULAR       "echo"    , echocmd    },
9467 #endif
9468         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9469         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9470         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9471         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9472         { BUILTIN_REGULAR       "false"   , falsecmd   },
9473 #if JOBS
9474         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9475 #endif
9476 #if ENABLE_ASH_GETOPTS
9477         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9478 #endif
9479         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9480 #if ENABLE_ASH_HELP
9481         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9482 #endif
9483 #if MAX_HISTORY
9484         { BUILTIN_NOSPEC        "history" , historycmd },
9485 #endif
9486 #if JOBS
9487         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9488         { BUILTIN_REGULAR       "kill"    , killcmd    },
9489 #endif
9490 #if ENABLE_FEATURE_SH_MATH
9491         { BUILTIN_NOSPEC        "let"     , letcmd     },
9492 #endif
9493         { BUILTIN_ASSIGN        "local"   , localcmd   },
9494 #if ENABLE_ASH_PRINTF
9495         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9496 #endif
9497         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9498         { BUILTIN_REGULAR       "read"    , readcmd    },
9499         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9500         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9501         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9502         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9503 #if BASH_SOURCE
9504         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9505 #endif
9506 #if ENABLE_ASH_TEST
9507         { BUILTIN_REGULAR       "test"    , testcmd    },
9508 #endif
9509         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9510         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9511         { BUILTIN_REGULAR       "true"    , truecmd    },
9512         { BUILTIN_NOSPEC        "type"    , typecmd    },
9513         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9514         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9515 #if ENABLE_ASH_ALIAS
9516         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9517 #endif
9518         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9519         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9520 };
9521
9522 /* Should match the above table! */
9523 #define COMMANDCMD (builtintab + \
9524         /* . : */       2 + \
9525         /* [ */         1 * ENABLE_ASH_TEST + \
9526         /* [[ */        1 * BASH_TEST2 + \
9527         /* alias */     1 * ENABLE_ASH_ALIAS + \
9528         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9529         /* break cd cddir  */   3)
9530 #define EVALCMD (COMMANDCMD + \
9531         /* command */   1 * ENABLE_ASH_CMDCMD + \
9532         /* continue */  1 + \
9533         /* echo */      1 * ENABLE_ASH_ECHO + \
9534         0)
9535 #define EXECCMD (EVALCMD + \
9536         /* eval */      1)
9537
9538 /*
9539  * Search the table of builtin commands.
9540  */
9541 static int
9542 pstrcmp1(const void *a, const void *b)
9543 {
9544         return strcmp((char*)a, *(char**)b + 1);
9545 }
9546 static struct builtincmd *
9547 find_builtin(const char *name)
9548 {
9549         struct builtincmd *bp;
9550
9551         bp = bsearch(
9552                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9553                 pstrcmp1
9554         );
9555         return bp;
9556 }
9557
9558 /*
9559  * Execute a simple command.
9560  */
9561 static int
9562 isassignment(const char *p)
9563 {
9564         const char *q = endofname(p);
9565         if (p == q)
9566                 return 0;
9567         return *q == '=';
9568 }
9569 static int FAST_FUNC
9570 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9571 {
9572         /* Preserve exitstatus of a previous possible redirection
9573          * as POSIX mandates */
9574         return back_exitstatus;
9575 }
9576 static int
9577 evalcommand(union node *cmd, int flags)
9578 {
9579         static const struct builtincmd null_bltin = {
9580                 "\0\0", bltincmd /* why three NULs? */
9581         };
9582         struct stackmark smark;
9583         union node *argp;
9584         struct arglist arglist;
9585         struct arglist varlist;
9586         char **argv;
9587         int argc;
9588         const struct strlist *sp;
9589         struct cmdentry cmdentry;
9590         struct job *jp;
9591         char *lastarg;
9592         const char *path;
9593         int spclbltin;
9594         int status;
9595         char **nargv;
9596         struct builtincmd *bcmd;
9597         smallint cmd_is_exec;
9598         smallint pseudovarflag = 0;
9599
9600         /* First expand the arguments. */
9601         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9602         setstackmark(&smark);
9603         back_exitstatus = 0;
9604
9605         cmdentry.cmdtype = CMDBUILTIN;
9606         cmdentry.u.cmd = &null_bltin;
9607         varlist.lastp = &varlist.list;
9608         *varlist.lastp = NULL;
9609         arglist.lastp = &arglist.list;
9610         *arglist.lastp = NULL;
9611
9612         argc = 0;
9613         if (cmd->ncmd.args) {
9614                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9615                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9616         }
9617
9618         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9619                 struct strlist **spp;
9620
9621                 spp = arglist.lastp;
9622                 if (pseudovarflag && isassignment(argp->narg.text))
9623                         expandarg(argp, &arglist, EXP_VARTILDE);
9624                 else
9625                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9626
9627                 for (sp = *spp; sp; sp = sp->next)
9628                         argc++;
9629         }
9630
9631         /* Reserve one extra spot at the front for shellexec. */
9632         nargv = stalloc(sizeof(char *) * (argc + 2));
9633         argv = ++nargv;
9634         for (sp = arglist.list; sp; sp = sp->next) {
9635                 TRACE(("evalcommand arg: %s\n", sp->text));
9636                 *nargv++ = sp->text;
9637         }
9638         *nargv = NULL;
9639
9640         lastarg = NULL;
9641         if (iflag && funcnest == 0 && argc > 0)
9642                 lastarg = nargv[-1];
9643
9644         preverrout_fd = 2;
9645         expredir(cmd->ncmd.redirect);
9646         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9647
9648         path = vpath.var_text;
9649         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9650                 struct strlist **spp;
9651                 char *p;
9652
9653                 spp = varlist.lastp;
9654                 expandarg(argp, &varlist, EXP_VARTILDE);
9655
9656                 /*
9657                  * Modify the command lookup path, if a PATH= assignment
9658                  * is present
9659                  */
9660                 p = (*spp)->text;
9661                 if (varcmp(p, path) == 0)
9662                         path = p;
9663         }
9664
9665         /* Print the command if xflag is set. */
9666         if (xflag) {
9667                 const char *pfx = "";
9668
9669                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9670
9671                 sp = varlist.list;
9672                 while (sp) {
9673                         char *varval = sp->text;
9674                         char *eq = strchrnul(varval, '=');
9675                         if (*eq)
9676                                 eq++;
9677                         fdprintf(preverrout_fd, "%s%.*s%s",
9678                                 pfx,
9679                                 (int)(eq - varval), varval,
9680                                 maybe_single_quote(eq)
9681                         );
9682                         sp = sp->next;
9683                         pfx = " ";
9684                 }
9685
9686                 sp = arglist.list;
9687                 while (sp) {
9688                         fdprintf(preverrout_fd, "%s%s",
9689                                 pfx,
9690                                 /* always quote if matches reserved word: */
9691                                 findkwd(sp->text)
9692                                 ? single_quote(sp->text)
9693                                 : maybe_single_quote(sp->text)
9694                         );
9695                         sp = sp->next;
9696                         pfx = " ";
9697                 }
9698                 safe_write(preverrout_fd, "\n", 1);
9699         }
9700
9701         cmd_is_exec = 0;
9702         spclbltin = -1;
9703
9704         /* Now locate the command. */
9705         if (argc) {
9706                 int cmd_flag = DO_ERR;
9707 #if ENABLE_ASH_CMDCMD
9708                 const char *oldpath = path + 5;
9709 #endif
9710                 path += 5;
9711                 for (;;) {
9712                         find_command(argv[0], &cmdentry, cmd_flag, path);
9713                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9714                                 flush_stdout_stderr();
9715                                 status = 127;
9716                                 goto bail;
9717                         }
9718
9719                         /* implement bltin and command here */
9720                         if (cmdentry.cmdtype != CMDBUILTIN)
9721                                 break;
9722                         if (spclbltin < 0)
9723                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9724                         if (cmdentry.u.cmd == EXECCMD)
9725                                 cmd_is_exec = 1;
9726 #if ENABLE_ASH_CMDCMD
9727                         if (cmdentry.u.cmd == COMMANDCMD) {
9728                                 path = oldpath;
9729                                 nargv = parse_command_args(argv, &path);
9730                                 if (!nargv)
9731                                         break;
9732                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9733                                  * nargv => "PROG". path is updated if -p.
9734                                  */
9735                                 argc -= nargv - argv;
9736                                 argv = nargv;
9737                                 cmd_flag |= DO_NOFUNC;
9738                         } else
9739 #endif
9740                                 break;
9741                 }
9742         }
9743
9744         if (status) {
9745  bail:
9746                 exitstatus = status;
9747
9748                 /* We have a redirection error. */
9749                 if (spclbltin > 0)
9750                         raise_exception(EXERROR);
9751
9752                 goto out;
9753         }
9754
9755         /* Execute the command. */
9756         switch (cmdentry.cmdtype) {
9757         default: {
9758
9759 #if ENABLE_FEATURE_SH_NOFORK
9760 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9761  *     around run_nofork_applet() call.
9762  * (2) Should this check also be done in forkshell()?
9763  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9764  */
9765                 /* find_command() encodes applet_no as (-2 - applet_no) */
9766                 int applet_no = (- cmdentry.u.index - 2);
9767                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9768                         listsetvar(varlist.list, VEXPORT|VSTACK);
9769                         /* run <applet>_main() */
9770                         status = run_nofork_applet(applet_no, argv);
9771                         break;
9772                 }
9773 #endif
9774                 /* Can we avoid forking off? For example, very last command
9775                  * in a script or a subshell does not need forking,
9776                  * we can just exec it.
9777                  */
9778                 if (!(flags & EV_EXIT) || may_have_traps) {
9779                         /* No, forking off a child is necessary */
9780                         INT_OFF;
9781                         get_tty_state();
9782                         jp = makejob(/*cmd,*/ 1);
9783                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9784                                 /* parent */
9785                                 status = waitforjob(jp);
9786                                 INT_ON;
9787                                 TRACE(("forked child exited with %d\n", status));
9788                                 break;
9789                         }
9790                         /* child */
9791                         FORCE_INT_ON;
9792                         /* fall through to exec'ing external program */
9793                 }
9794                 listsetvar(varlist.list, VEXPORT|VSTACK);
9795                 shellexec(argv[0], argv, path, cmdentry.u.index);
9796                 /* NOTREACHED */
9797         } /* default */
9798         case CMDBUILTIN:
9799                 cmdenviron = varlist.list;
9800                 if (cmdenviron) {
9801                         struct strlist *list = cmdenviron;
9802                         int i = VNOSET;
9803                         if (spclbltin > 0 || argc == 0) {
9804                                 i = 0;
9805                                 if (cmd_is_exec && argc > 1)
9806                                         i = VEXPORT;
9807                         }
9808                         listsetvar(list, i);
9809                 }
9810                 /* Tight loop with builtins only:
9811                  * "while kill -0 $child; do true; done"
9812                  * will never exit even if $child died, unless we do this
9813                  * to reap the zombie and make kill detect that it's gone: */
9814                 dowait(DOWAIT_NONBLOCK, NULL);
9815
9816                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9817                         if (exception_type == EXERROR && spclbltin <= 0) {
9818                                 FORCE_INT_ON;
9819                                 goto readstatus;
9820                         }
9821  raise:
9822                         longjmp(exception_handler->loc, 1);
9823                 }
9824                 goto readstatus;
9825
9826         case CMDFUNCTION:
9827                 listsetvar(varlist.list, 0);
9828                 /* See above for the rationale */
9829                 dowait(DOWAIT_NONBLOCK, NULL);
9830                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9831                         goto raise;
9832  readstatus:
9833                 status = exitstatus;
9834                 break;
9835         } /* switch */
9836
9837  out:
9838         if (cmd->ncmd.redirect)
9839                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9840         if (lastarg) {
9841                 /* dsl: I think this is intended to be used to support
9842                  * '_' in 'vi' command mode during line editing...
9843                  * However I implemented that within libedit itself.
9844                  */
9845                 setvar0("_", lastarg);
9846         }
9847         popstackmark(&smark);
9848
9849         return status;
9850 }
9851
9852 static int
9853 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9854 {
9855         char *volatile savecmdname;
9856         struct jmploc *volatile savehandler;
9857         struct jmploc jmploc;
9858         int status;
9859         int i;
9860
9861         savecmdname = commandname;
9862         savehandler = exception_handler;
9863         i = setjmp(jmploc.loc);
9864         if (i)
9865                 goto cmddone;
9866         exception_handler = &jmploc;
9867         commandname = argv[0];
9868         argptr = argv + 1;
9869         optptr = NULL;                  /* initialize nextopt */
9870         if (cmd == EVALCMD)
9871                 status = evalcmd(argc, argv, flags);
9872         else
9873                 status = (*cmd->builtin)(argc, argv);
9874         flush_stdout_stderr();
9875         status |= ferror(stdout);
9876         exitstatus = status;
9877  cmddone:
9878         clearerr(stdout);
9879         commandname = savecmdname;
9880         exception_handler = savehandler;
9881
9882         return i;
9883 }
9884
9885 static int
9886 goodname(const char *p)
9887 {
9888         return endofname(p)[0] == '\0';
9889 }
9890
9891
9892 /*
9893  * Search for a command.  This is called before we fork so that the
9894  * location of the command will be available in the parent as well as
9895  * the child.  The check for "goodname" is an overly conservative
9896  * check that the name will not be subject to expansion.
9897  */
9898 static void
9899 prehash(union node *n)
9900 {
9901         struct cmdentry entry;
9902
9903         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9904                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9905 }
9906
9907
9908 /* ============ Builtin commands
9909  *
9910  * Builtin commands whose functions are closely tied to evaluation
9911  * are implemented here.
9912  */
9913
9914 /*
9915  * Handle break and continue commands.  Break, continue, and return are
9916  * all handled by setting the evalskip flag.  The evaluation routines
9917  * above all check this flag, and if it is set they start skipping
9918  * commands rather than executing them.  The variable skipcount is
9919  * the number of loops to break/continue, or the number of function
9920  * levels to return.  (The latter is always 1.)  It should probably
9921  * be an error to break out of more loops than exist, but it isn't
9922  * in the standard shell so we don't make it one here.
9923  */
9924 static int FAST_FUNC
9925 breakcmd(int argc UNUSED_PARAM, char **argv)
9926 {
9927         int n = argv[1] ? number(argv[1]) : 1;
9928
9929         if (n <= 0)
9930                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9931         if (n > loopnest)
9932                 n = loopnest;
9933         if (n > 0) {
9934                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9935                 skipcount = n;
9936         }
9937         return 0;
9938 }
9939
9940
9941 /*
9942  * This implements the input routines used by the parser.
9943  */
9944
9945 enum {
9946         INPUT_PUSH_FILE = 1,
9947         INPUT_NOFILE_OK = 2,
9948 };
9949
9950 static smallint checkkwd;
9951 /* values of checkkwd variable */
9952 #define CHKALIAS        0x1
9953 #define CHKKWD          0x2
9954 #define CHKNL           0x4
9955
9956 /*
9957  * Push a string back onto the input at this current parsefile level.
9958  * We handle aliases this way.
9959  */
9960 #if !ENABLE_ASH_ALIAS
9961 #define pushstring(s, ap) pushstring(s)
9962 #endif
9963 static void
9964 pushstring(char *s, struct alias *ap)
9965 {
9966         struct strpush *sp;
9967         int len;
9968
9969         len = strlen(s);
9970         INT_OFF;
9971         if (g_parsefile->strpush) {
9972                 sp = ckzalloc(sizeof(*sp));
9973                 sp->prev = g_parsefile->strpush;
9974         } else {
9975                 sp = &(g_parsefile->basestrpush);
9976         }
9977         g_parsefile->strpush = sp;
9978         sp->prev_string = g_parsefile->next_to_pgetc;
9979         sp->prev_left_in_line = g_parsefile->left_in_line;
9980         sp->unget = g_parsefile->unget;
9981         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
9982 #if ENABLE_ASH_ALIAS
9983         sp->ap = ap;
9984         if (ap) {
9985                 ap->flag |= ALIASINUSE;
9986                 sp->string = s;
9987         }
9988 #endif
9989         g_parsefile->next_to_pgetc = s;
9990         g_parsefile->left_in_line = len;
9991         g_parsefile->unget = 0;
9992         INT_ON;
9993 }
9994
9995 static void
9996 popstring(void)
9997 {
9998         struct strpush *sp = g_parsefile->strpush;
9999
10000         INT_OFF;
10001 #if ENABLE_ASH_ALIAS
10002         if (sp->ap) {
10003                 if (g_parsefile->next_to_pgetc[-1] == ' '
10004                  || g_parsefile->next_to_pgetc[-1] == '\t'
10005                 ) {
10006                         checkkwd |= CHKALIAS;
10007                 }
10008                 if (sp->string != sp->ap->val) {
10009                         free(sp->string);
10010                 }
10011                 sp->ap->flag &= ~ALIASINUSE;
10012                 if (sp->ap->flag & ALIASDEAD) {
10013                         unalias(sp->ap->name);
10014                 }
10015         }
10016 #endif
10017         g_parsefile->next_to_pgetc = sp->prev_string;
10018         g_parsefile->left_in_line = sp->prev_left_in_line;
10019         g_parsefile->unget = sp->unget;
10020         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10021         g_parsefile->strpush = sp->prev;
10022         if (sp != &(g_parsefile->basestrpush))
10023                 free(sp);
10024         INT_ON;
10025 }
10026
10027 static int
10028 preadfd(void)
10029 {
10030         int nr;
10031         char *buf = g_parsefile->buf;
10032
10033         g_parsefile->next_to_pgetc = buf;
10034 #if ENABLE_FEATURE_EDITING
10035  retry:
10036         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10037                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10038         else {
10039                 int timeout = -1;
10040 # if ENABLE_ASH_IDLE_TIMEOUT
10041                 if (iflag) {
10042                         const char *tmout_var = lookupvar("TMOUT");
10043                         if (tmout_var) {
10044                                 timeout = atoi(tmout_var) * 1000;
10045                                 if (timeout <= 0)
10046                                         timeout = -1;
10047                         }
10048                 }
10049 # endif
10050 # if ENABLE_FEATURE_TAB_COMPLETION
10051                 line_input_state->path_lookup = pathval();
10052 # endif
10053                 reinit_unicode_for_ash();
10054                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10055                 if (nr == 0) {
10056                         /* ^C pressed, "convert" to SIGINT */
10057                         write(STDOUT_FILENO, "^C", 2);
10058                         if (trap[SIGINT]) {
10059                                 buf[0] = '\n';
10060                                 buf[1] = '\0';
10061                                 raise(SIGINT);
10062                                 return 1;
10063                         }
10064                         exitstatus = 128 + SIGINT;
10065                         bb_putchar('\n');
10066                         goto retry;
10067                 }
10068                 if (nr < 0) {
10069                         if (errno == 0) {
10070                                 /* Ctrl+D pressed */
10071                                 nr = 0;
10072                         }
10073 # if ENABLE_ASH_IDLE_TIMEOUT
10074                         else if (errno == EAGAIN && timeout > 0) {
10075                                 puts("\007timed out waiting for input: auto-logout");
10076                                 exitshell();
10077                         }
10078 # endif
10079                 }
10080         }
10081 #else
10082         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10083 #endif
10084
10085 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10086         if (nr < 0) {
10087                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10088                         int flags = fcntl(0, F_GETFL);
10089                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10090                                 flags &= ~O_NONBLOCK;
10091                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10092                                         out2str("sh: turning off NDELAY mode\n");
10093                                         goto retry;
10094                                 }
10095                         }
10096                 }
10097         }
10098 #endif
10099         return nr;
10100 }
10101
10102 /*
10103  * Refill the input buffer and return the next input character:
10104  *
10105  * 1) If a string was pushed back on the input, pop it;
10106  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10107  *    or we are reading from a string so we can't refill the buffer,
10108  *    return EOF.
10109  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10110  * 4) Process input up to the next newline, deleting nul characters.
10111  */
10112 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10113 #define pgetc_debug(...) ((void)0)
10114 static int pgetc(void);
10115 static int
10116 preadbuffer(void)
10117 {
10118         char *q;
10119         int more;
10120
10121         if (g_parsefile->strpush) {
10122 #if ENABLE_ASH_ALIAS
10123                 if (g_parsefile->left_in_line == -1
10124                  && g_parsefile->strpush->ap
10125                  && g_parsefile->next_to_pgetc[-1] != ' '
10126                  && g_parsefile->next_to_pgetc[-1] != '\t'
10127                 ) {
10128                         pgetc_debug("preadbuffer PEOA");
10129                         return PEOA;
10130                 }
10131 #endif
10132                 popstring();
10133                 return pgetc();
10134         }
10135         /* on both branches above g_parsefile->left_in_line < 0.
10136          * "pgetc" needs refilling.
10137          */
10138
10139         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10140          * pungetc() may increment it a few times.
10141          * Assuming it won't increment it to less than -90.
10142          */
10143         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10144                 pgetc_debug("preadbuffer PEOF1");
10145                 /* even in failure keep left_in_line and next_to_pgetc
10146                  * in lock step, for correct multi-layer pungetc.
10147                  * left_in_line was decremented before preadbuffer(),
10148                  * must inc next_to_pgetc: */
10149                 g_parsefile->next_to_pgetc++;
10150                 return PEOF;
10151         }
10152
10153         more = g_parsefile->left_in_buffer;
10154         if (more <= 0) {
10155                 flush_stdout_stderr();
10156  again:
10157                 more = preadfd();
10158                 if (more <= 0) {
10159                         /* don't try reading again */
10160                         g_parsefile->left_in_line = -99;
10161                         pgetc_debug("preadbuffer PEOF2");
10162                         g_parsefile->next_to_pgetc++;
10163                         return PEOF;
10164                 }
10165         }
10166
10167         /* Find out where's the end of line.
10168          * Set g_parsefile->left_in_line
10169          * and g_parsefile->left_in_buffer acordingly.
10170          * NUL chars are deleted.
10171          */
10172         q = g_parsefile->next_to_pgetc;
10173         for (;;) {
10174                 char c;
10175
10176                 more--;
10177
10178                 c = *q;
10179                 if (c == '\0') {
10180                         memmove(q, q + 1, more);
10181                 } else {
10182                         q++;
10183                         if (c == '\n') {
10184                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10185                                 break;
10186                         }
10187                 }
10188
10189                 if (more <= 0) {
10190                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10191                         if (g_parsefile->left_in_line < 0)
10192                                 goto again;
10193                         break;
10194                 }
10195         }
10196         g_parsefile->left_in_buffer = more;
10197
10198         if (vflag) {
10199                 char save = *q;
10200                 *q = '\0';
10201                 out2str(g_parsefile->next_to_pgetc);
10202                 *q = save;
10203         }
10204
10205         pgetc_debug("preadbuffer at %d:%p'%s'",
10206                         g_parsefile->left_in_line,
10207                         g_parsefile->next_to_pgetc,
10208                         g_parsefile->next_to_pgetc);
10209         return (unsigned char)*g_parsefile->next_to_pgetc++;
10210 }
10211
10212 static void
10213 nlprompt(void)
10214 {
10215         g_parsefile->linno++;
10216         setprompt_if(doprompt, 2);
10217 }
10218 static void
10219 nlnoprompt(void)
10220 {
10221         g_parsefile->linno++;
10222         needprompt = doprompt;
10223 }
10224
10225 static int
10226 pgetc(void)
10227 {
10228         int c;
10229
10230         pgetc_debug("pgetc at %d:%p'%s'",
10231                         g_parsefile->left_in_line,
10232                         g_parsefile->next_to_pgetc,
10233                         g_parsefile->next_to_pgetc);
10234         if (g_parsefile->unget)
10235                 return g_parsefile->lastc[--g_parsefile->unget];
10236
10237         if (--g_parsefile->left_in_line >= 0)
10238                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10239         else
10240                 c = preadbuffer();
10241
10242         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10243         g_parsefile->lastc[0] = c;
10244
10245         return c;
10246 }
10247
10248 #if ENABLE_ASH_ALIAS
10249 static int
10250 pgetc_without_PEOA(void)
10251 {
10252         int c;
10253         do {
10254                 pgetc_debug("pgetc at %d:%p'%s'",
10255                                 g_parsefile->left_in_line,
10256                                 g_parsefile->next_to_pgetc,
10257                                 g_parsefile->next_to_pgetc);
10258                 c = pgetc();
10259         } while (c == PEOA);
10260         return c;
10261 }
10262 #else
10263 # define pgetc_without_PEOA() pgetc()
10264 #endif
10265
10266 /*
10267  * Read a line from the script.
10268  */
10269 static char *
10270 pfgets(char *line, int len)
10271 {
10272         char *p = line;
10273         int nleft = len;
10274         int c;
10275
10276         while (--nleft > 0) {
10277                 c = pgetc_without_PEOA();
10278                 if (c == PEOF) {
10279                         if (p == line)
10280                                 return NULL;
10281                         break;
10282                 }
10283                 *p++ = c;
10284                 if (c == '\n')
10285                         break;
10286         }
10287         *p = '\0';
10288         return line;
10289 }
10290
10291 /*
10292  * Undo a call to pgetc.  Only two characters may be pushed back.
10293  * PEOF may be pushed back.
10294  */
10295 static void
10296 pungetc(void)
10297 {
10298         g_parsefile->unget++;
10299 }
10300
10301 /* This one eats backslash+newline */
10302 static int
10303 pgetc_eatbnl(void)
10304 {
10305         int c;
10306
10307         while ((c = pgetc()) == '\\') {
10308                 if (pgetc() != '\n') {
10309                         pungetc();
10310                         break;
10311                 }
10312
10313                 nlprompt();
10314         }
10315
10316         return c;
10317 }
10318
10319 /*
10320  * To handle the "." command, a stack of input files is used.  Pushfile
10321  * adds a new entry to the stack and popfile restores the previous level.
10322  */
10323 static void
10324 pushfile(void)
10325 {
10326         struct parsefile *pf;
10327
10328         pf = ckzalloc(sizeof(*pf));
10329         pf->prev = g_parsefile;
10330         pf->pf_fd = -1;
10331         /*pf->strpush = NULL; - ckzalloc did it */
10332         /*pf->basestrpush.prev = NULL;*/
10333         /*pf->unget = 0;*/
10334         g_parsefile = pf;
10335 }
10336
10337 static void
10338 popfile(void)
10339 {
10340         struct parsefile *pf = g_parsefile;
10341
10342         if (pf == &basepf)
10343                 return;
10344
10345         INT_OFF;
10346         if (pf->pf_fd >= 0)
10347                 close(pf->pf_fd);
10348         free(pf->buf);
10349         while (pf->strpush)
10350                 popstring();
10351         g_parsefile = pf->prev;
10352         free(pf);
10353         INT_ON;
10354 }
10355
10356 /*
10357  * Return to top level.
10358  */
10359 static void
10360 popallfiles(void)
10361 {
10362         while (g_parsefile != &basepf)
10363                 popfile();
10364 }
10365
10366 /*
10367  * Close the file(s) that the shell is reading commands from.  Called
10368  * after a fork is done.
10369  */
10370 static void
10371 closescript(void)
10372 {
10373         popallfiles();
10374         if (g_parsefile->pf_fd > 0) {
10375                 close(g_parsefile->pf_fd);
10376                 g_parsefile->pf_fd = 0;
10377         }
10378 }
10379
10380 /*
10381  * Like setinputfile, but takes an open file descriptor.  Call this with
10382  * interrupts off.
10383  */
10384 static void
10385 setinputfd(int fd, int push)
10386 {
10387         if (push) {
10388                 pushfile();
10389                 g_parsefile->buf = NULL;
10390         }
10391         g_parsefile->pf_fd = fd;
10392         if (g_parsefile->buf == NULL)
10393                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10394         g_parsefile->left_in_buffer = 0;
10395         g_parsefile->left_in_line = 0;
10396         g_parsefile->linno = 1;
10397 }
10398
10399 /*
10400  * Set the input to take input from a file.  If push is set, push the
10401  * old input onto the stack first.
10402  */
10403 static int
10404 setinputfile(const char *fname, int flags)
10405 {
10406         int fd;
10407
10408         INT_OFF;
10409         fd = open(fname, O_RDONLY);
10410         if (fd < 0) {
10411                 if (flags & INPUT_NOFILE_OK)
10412                         goto out;
10413                 exitstatus = 127;
10414                 ash_msg_and_raise_error("can't open '%s'", fname);
10415         }
10416         if (fd < 10)
10417                 fd = savefd(fd);
10418         else
10419                 close_on_exec_on(fd);
10420         setinputfd(fd, flags & INPUT_PUSH_FILE);
10421  out:
10422         INT_ON;
10423         return fd;
10424 }
10425
10426 /*
10427  * Like setinputfile, but takes input from a string.
10428  */
10429 static void
10430 setinputstring(char *string)
10431 {
10432         INT_OFF;
10433         pushfile();
10434         g_parsefile->next_to_pgetc = string;
10435         g_parsefile->left_in_line = strlen(string);
10436         g_parsefile->buf = NULL;
10437         g_parsefile->linno = 1;
10438         INT_ON;
10439 }
10440
10441
10442 /*
10443  * Routines to check for mail.
10444  */
10445
10446 #if ENABLE_ASH_MAIL
10447
10448 /* Hash of mtimes of mailboxes */
10449 static unsigned mailtime_hash;
10450 /* Set if MAIL or MAILPATH is changed. */
10451 static smallint mail_var_path_changed;
10452
10453 /*
10454  * Print appropriate message(s) if mail has arrived.
10455  * If mail_var_path_changed is set,
10456  * then the value of MAIL has mail_var_path_changed,
10457  * so we just update the values.
10458  */
10459 static void
10460 chkmail(void)
10461 {
10462         const char *mpath;
10463         char *p;
10464         char *q;
10465         unsigned new_hash;
10466         struct stackmark smark;
10467         struct stat statb;
10468
10469         setstackmark(&smark);
10470         mpath = mpathset() ? mpathval() : mailval();
10471         new_hash = 0;
10472         for (;;) {
10473                 p = path_advance(&mpath, nullstr);
10474                 if (p == NULL)
10475                         break;
10476                 if (*p == '\0')
10477                         continue;
10478                 for (q = p; *q; q++)
10479                         continue;
10480 #if DEBUG
10481                 if (q[-1] != '/')
10482                         abort();
10483 #endif
10484                 q[-1] = '\0';                   /* delete trailing '/' */
10485                 if (stat(p, &statb) < 0) {
10486                         continue;
10487                 }
10488                 /* Very simplistic "hash": just a sum of all mtimes */
10489                 new_hash += (unsigned)statb.st_mtime;
10490         }
10491         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10492                 if (mailtime_hash != 0)
10493                         out2str("you have mail\n");
10494                 mailtime_hash = new_hash;
10495         }
10496         mail_var_path_changed = 0;
10497         popstackmark(&smark);
10498 }
10499
10500 static void FAST_FUNC
10501 changemail(const char *val UNUSED_PARAM)
10502 {
10503         mail_var_path_changed = 1;
10504 }
10505
10506 #endif /* ASH_MAIL */
10507
10508
10509 /* ============ ??? */
10510
10511 /*
10512  * Set the shell parameters.
10513  */
10514 static void
10515 setparam(char **argv)
10516 {
10517         char **newparam;
10518         char **ap;
10519         int nparam;
10520
10521         for (nparam = 0; argv[nparam]; nparam++)
10522                 continue;
10523         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10524         while (*argv) {
10525                 *ap++ = ckstrdup(*argv++);
10526         }
10527         *ap = NULL;
10528         freeparam(&shellparam);
10529         shellparam.malloced = 1;
10530         shellparam.nparam = nparam;
10531         shellparam.p = newparam;
10532 #if ENABLE_ASH_GETOPTS
10533         shellparam.optind = 1;
10534         shellparam.optoff = -1;
10535 #endif
10536 }
10537
10538 /*
10539  * Process shell options.  The global variable argptr contains a pointer
10540  * to the argument list; we advance it past the options.
10541  *
10542  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10543  * For a non-interactive shell, an error condition encountered
10544  * by a special built-in ... shall cause the shell to write a diagnostic message
10545  * to standard error and exit as shown in the following table:
10546  * Error                                           Special Built-In
10547  * ...
10548  * Utility syntax error (option or operand error)  Shall exit
10549  * ...
10550  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10551  * we see that bash does not do that (set "finishes" with error code 1 instead,
10552  * and shell continues), and people rely on this behavior!
10553  * Testcase:
10554  * set -o barfoo 2>/dev/null
10555  * echo $?
10556  *
10557  * Oh well. Let's mimic that.
10558  */
10559 static int
10560 plus_minus_o(char *name, int val)
10561 {
10562         int i;
10563
10564         if (name) {
10565                 for (i = 0; i < NOPTS; i++) {
10566                         if (strcmp(name, optnames(i)) == 0) {
10567                                 optlist[i] = val;
10568                                 return 0;
10569                         }
10570                 }
10571                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10572                 return 1;
10573         }
10574         for (i = 0; i < NOPTS; i++) {
10575                 if (val) {
10576                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10577                 } else {
10578                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10579                 }
10580         }
10581         return 0;
10582 }
10583 static void
10584 setoption(int flag, int val)
10585 {
10586         int i;
10587
10588         for (i = 0; i < NOPTS; i++) {
10589                 if (optletters(i) == flag) {
10590                         optlist[i] = val;
10591                         return;
10592                 }
10593         }
10594         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10595         /* NOTREACHED */
10596 }
10597 static int
10598 options(int cmdline)
10599 {
10600         char *p;
10601         int val;
10602         int c;
10603
10604         if (cmdline)
10605                 minusc = NULL;
10606         while ((p = *argptr) != NULL) {
10607                 c = *p++;
10608                 if (c != '-' && c != '+')
10609                         break;
10610                 argptr++;
10611                 val = 0; /* val = 0 if c == '+' */
10612                 if (c == '-') {
10613                         val = 1;
10614                         if (p[0] == '\0' || LONE_DASH(p)) {
10615                                 if (!cmdline) {
10616                                         /* "-" means turn off -x and -v */
10617                                         if (p[0] == '\0')
10618                                                 xflag = vflag = 0;
10619                                         /* "--" means reset params */
10620                                         else if (*argptr == NULL)
10621                                                 setparam(argptr);
10622                                 }
10623                                 break;    /* "-" or "--" terminates options */
10624                         }
10625                 }
10626                 /* first char was + or - */
10627                 while ((c = *p++) != '\0') {
10628                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10629                         if (c == 'c' && cmdline) {
10630                                 minusc = p;     /* command is after shell args */
10631                         } else if (c == 'o') {
10632                                 if (plus_minus_o(*argptr, val)) {
10633                                         /* it already printed err message */
10634                                         return 1; /* error */
10635                                 }
10636                                 if (*argptr)
10637                                         argptr++;
10638                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10639                                 isloginsh = 1;
10640                         /* bash does not accept +-login, we also won't */
10641                         } else if (cmdline && val && (c == '-')) { /* long options */
10642                                 if (strcmp(p, "login") == 0)
10643                                         isloginsh = 1;
10644                                 break;
10645                         } else {
10646                                 setoption(c, val);
10647                         }
10648                 }
10649         }
10650         return 0;
10651 }
10652
10653 /*
10654  * The shift builtin command.
10655  */
10656 static int FAST_FUNC
10657 shiftcmd(int argc UNUSED_PARAM, char **argv)
10658 {
10659         int n;
10660         char **ap1, **ap2;
10661
10662         n = 1;
10663         if (argv[1])
10664                 n = number(argv[1]);
10665         if (n > shellparam.nparam)
10666                 n = 0; /* bash compat, was = shellparam.nparam; */
10667         INT_OFF;
10668         shellparam.nparam -= n;
10669         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10670                 if (shellparam.malloced)
10671                         free(*ap1);
10672         }
10673         ap2 = shellparam.p;
10674         while ((*ap2++ = *ap1++) != NULL)
10675                 continue;
10676 #if ENABLE_ASH_GETOPTS
10677         shellparam.optind = 1;
10678         shellparam.optoff = -1;
10679 #endif
10680         INT_ON;
10681         return 0;
10682 }
10683
10684 /*
10685  * POSIX requires that 'set' (but not export or readonly) output the
10686  * variables in lexicographic order - by the locale's collating order (sigh).
10687  * Maybe we could keep them in an ordered balanced binary tree
10688  * instead of hashed lists.
10689  * For now just roll 'em through qsort for printing...
10690  */
10691 static int
10692 showvars(const char *sep_prefix, int on, int off)
10693 {
10694         const char *sep;
10695         char **ep, **epend;
10696
10697         ep = listvars(on, off, &epend);
10698         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10699
10700         sep = *sep_prefix ? " " : sep_prefix;
10701
10702         for (; ep < epend; ep++) {
10703                 const char *p;
10704                 const char *q;
10705
10706                 p = strchrnul(*ep, '=');
10707                 q = nullstr;
10708                 if (*p)
10709                         q = single_quote(++p);
10710                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10711         }
10712         return 0;
10713 }
10714
10715 /*
10716  * The set command builtin.
10717  */
10718 static int FAST_FUNC
10719 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10720 {
10721         int retval;
10722
10723         if (!argv[1])
10724                 return showvars(nullstr, 0, VUNSET);
10725
10726         INT_OFF;
10727         retval = options(/*cmdline:*/ 0);
10728         if (retval == 0) { /* if no parse error... */
10729                 optschanged();
10730                 if (*argptr != NULL) {
10731                         setparam(argptr);
10732                 }
10733         }
10734         INT_ON;
10735         return retval;
10736 }
10737
10738 #if ENABLE_ASH_RANDOM_SUPPORT
10739 static void FAST_FUNC
10740 change_random(const char *value)
10741 {
10742         uint32_t t;
10743
10744         if (value == NULL) {
10745                 /* "get", generate */
10746                 t = next_random(&random_gen);
10747                 /* set without recursion */
10748                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10749                 vrandom.flags &= ~VNOFUNC;
10750         } else {
10751                 /* set/reset */
10752                 t = strtoul(value, NULL, 10);
10753                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10754         }
10755 }
10756 #endif
10757
10758 #if ENABLE_ASH_GETOPTS
10759 static int
10760 getopts(char *optstr, char *optvar, char **optfirst)
10761 {
10762         char *p, *q;
10763         char c = '?';
10764         int done = 0;
10765         char sbuf[2];
10766         char **optnext;
10767         int ind = shellparam.optind;
10768         int off = shellparam.optoff;
10769
10770         sbuf[1] = '\0';
10771
10772         shellparam.optind = -1;
10773         optnext = optfirst + ind - 1;
10774
10775         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10776                 p = NULL;
10777         else
10778                 p = optnext[-1] + off;
10779         if (p == NULL || *p == '\0') {
10780                 /* Current word is done, advance */
10781                 p = *optnext;
10782                 if (p == NULL || *p != '-' || *++p == '\0') {
10783  atend:
10784                         p = NULL;
10785                         done = 1;
10786                         goto out;
10787                 }
10788                 optnext++;
10789                 if (LONE_DASH(p))        /* check for "--" */
10790                         goto atend;
10791         }
10792
10793         c = *p++;
10794         for (q = optstr; *q != c;) {
10795                 if (*q == '\0') {
10796                         if (optstr[0] == ':') {
10797                                 sbuf[0] = c;
10798                                 /*sbuf[1] = '\0'; - already is */
10799                                 setvar0("OPTARG", sbuf);
10800                         } else {
10801                                 fprintf(stderr, "Illegal option -%c\n", c);
10802                                 unsetvar("OPTARG");
10803                         }
10804                         c = '?';
10805                         goto out;
10806                 }
10807                 if (*++q == ':')
10808                         q++;
10809         }
10810
10811         if (*++q == ':') {
10812                 if (*p == '\0' && (p = *optnext) == NULL) {
10813                         if (optstr[0] == ':') {
10814                                 sbuf[0] = c;
10815                                 /*sbuf[1] = '\0'; - already is */
10816                                 setvar0("OPTARG", sbuf);
10817                                 c = ':';
10818                         } else {
10819                                 fprintf(stderr, "No arg for -%c option\n", c);
10820                                 unsetvar("OPTARG");
10821                                 c = '?';
10822                         }
10823                         goto out;
10824                 }
10825
10826                 if (p == *optnext)
10827                         optnext++;
10828                 setvar0("OPTARG", p);
10829                 p = NULL;
10830         } else
10831                 setvar0("OPTARG", nullstr);
10832  out:
10833         ind = optnext - optfirst + 1;
10834         setvar("OPTIND", itoa(ind), VNOFUNC);
10835         sbuf[0] = c;
10836         /*sbuf[1] = '\0'; - already is */
10837         setvar0(optvar, sbuf);
10838
10839         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10840         shellparam.optind = ind;
10841
10842         return done;
10843 }
10844
10845 /*
10846  * The getopts builtin.  Shellparam.optnext points to the next argument
10847  * to be processed.  Shellparam.optptr points to the next character to
10848  * be processed in the current argument.  If shellparam.optnext is NULL,
10849  * then it's the first time getopts has been called.
10850  */
10851 static int FAST_FUNC
10852 getoptscmd(int argc, char **argv)
10853 {
10854         char **optbase;
10855
10856         if (argc < 3)
10857                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10858         if (argc == 3) {
10859                 optbase = shellparam.p;
10860                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10861                         shellparam.optind = 1;
10862                         shellparam.optoff = -1;
10863                 }
10864         } else {
10865                 optbase = &argv[3];
10866                 if ((unsigned)shellparam.optind > argc - 2) {
10867                         shellparam.optind = 1;
10868                         shellparam.optoff = -1;
10869                 }
10870         }
10871
10872         return getopts(argv[1], argv[2], optbase);
10873 }
10874 #endif /* ASH_GETOPTS */
10875
10876
10877 /* ============ Shell parser */
10878
10879 struct heredoc {
10880         struct heredoc *next;   /* next here document in list */
10881         union node *here;       /* redirection node */
10882         char *eofmark;          /* string indicating end of input */
10883         smallint striptabs;     /* if set, strip leading tabs */
10884 };
10885
10886 static smallint tokpushback;           /* last token pushed back */
10887 static smallint quoteflag;             /* set if (part of) last token was quoted */
10888 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10889 static struct heredoc *heredoclist;    /* list of here documents to read */
10890 static char *wordtext;                 /* text of last word returned by readtoken */
10891 static struct nodelist *backquotelist;
10892 static union node *redirnode;
10893 static struct heredoc *heredoc;
10894
10895 static const char *
10896 tokname(char *buf, int tok)
10897 {
10898         if (tok < TSEMI)
10899                 return tokname_array[tok];
10900         sprintf(buf, "\"%s\"", tokname_array[tok]);
10901         return buf;
10902 }
10903
10904 /* raise_error_unexpected_syntax:
10905  * Called when an unexpected token is read during the parse.  The argument
10906  * is the token that is expected, or -1 if more than one type of token can
10907  * occur at this point.
10908  */
10909 static void raise_error_unexpected_syntax(int) NORETURN;
10910 static void
10911 raise_error_unexpected_syntax(int token)
10912 {
10913         char msg[64];
10914         char buf[16];
10915         int l;
10916
10917         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10918         if (token >= 0)
10919                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10920         raise_error_syntax(msg);
10921         /* NOTREACHED */
10922 }
10923
10924 #define EOFMARKLEN 79
10925
10926 /* parsing is heavily cross-recursive, need these forward decls */
10927 static union node *andor(void);
10928 static union node *pipeline(void);
10929 static union node *parse_command(void);
10930 static void parseheredoc(void);
10931 static int peektoken(void);
10932 static int readtoken(void);
10933
10934 static union node *
10935 list(int nlflag)
10936 {
10937         union node *n1, *n2, *n3;
10938         int tok;
10939
10940         n1 = NULL;
10941         for (;;) {
10942                 switch (peektoken()) {
10943                 case TNL:
10944                         if (!(nlflag & 1))
10945                                 break;
10946                         parseheredoc();
10947                         return n1;
10948
10949                 case TEOF:
10950                         if (!n1 && (nlflag & 1))
10951                                 n1 = NODE_EOF;
10952                         parseheredoc();
10953                         return n1;
10954                 }
10955
10956                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10957                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10958                         return n1;
10959                 nlflag |= 2;
10960
10961                 n2 = andor();
10962                 tok = readtoken();
10963                 if (tok == TBACKGND) {
10964                         if (n2->type == NPIPE) {
10965                                 n2->npipe.pipe_backgnd = 1;
10966                         } else {
10967                                 if (n2->type != NREDIR) {
10968                                         n3 = stzalloc(sizeof(struct nredir));
10969                                         n3->nredir.n = n2;
10970                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10971                                         n2 = n3;
10972                                 }
10973                                 n2->type = NBACKGND;
10974                         }
10975                 }
10976                 if (n1 == NULL) {
10977                         n1 = n2;
10978                 } else {
10979                         n3 = stzalloc(sizeof(struct nbinary));
10980                         n3->type = NSEMI;
10981                         n3->nbinary.ch1 = n1;
10982                         n3->nbinary.ch2 = n2;
10983                         n1 = n3;
10984                 }
10985                 switch (tok) {
10986                 case TNL:
10987                 case TEOF:
10988                         tokpushback = 1;
10989                         /* fall through */
10990                 case TBACKGND:
10991                 case TSEMI:
10992                         break;
10993                 default:
10994                         if ((nlflag & 1))
10995                                 raise_error_unexpected_syntax(-1);
10996                         tokpushback = 1;
10997                         return n1;
10998                 }
10999         }
11000 }
11001
11002 static union node *
11003 andor(void)
11004 {
11005         union node *n1, *n2, *n3;
11006         int t;
11007
11008         n1 = pipeline();
11009         for (;;) {
11010                 t = readtoken();
11011                 if (t == TAND) {
11012                         t = NAND;
11013                 } else if (t == TOR) {
11014                         t = NOR;
11015                 } else {
11016                         tokpushback = 1;
11017                         return n1;
11018                 }
11019                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11020                 n2 = pipeline();
11021                 n3 = stzalloc(sizeof(struct nbinary));
11022                 n3->type = t;
11023                 n3->nbinary.ch1 = n1;
11024                 n3->nbinary.ch2 = n2;
11025                 n1 = n3;
11026         }
11027 }
11028
11029 static union node *
11030 pipeline(void)
11031 {
11032         union node *n1, *n2, *pipenode;
11033         struct nodelist *lp, *prev;
11034         int negate;
11035
11036         negate = 0;
11037         TRACE(("pipeline: entered\n"));
11038         if (readtoken() == TNOT) {
11039                 negate = !negate;
11040                 checkkwd = CHKKWD | CHKALIAS;
11041         } else
11042                 tokpushback = 1;
11043         n1 = parse_command();
11044         if (readtoken() == TPIPE) {
11045                 pipenode = stzalloc(sizeof(struct npipe));
11046                 pipenode->type = NPIPE;
11047                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11048                 lp = stzalloc(sizeof(struct nodelist));
11049                 pipenode->npipe.cmdlist = lp;
11050                 lp->n = n1;
11051                 do {
11052                         prev = lp;
11053                         lp = stzalloc(sizeof(struct nodelist));
11054                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11055                         lp->n = parse_command();
11056                         prev->next = lp;
11057                 } while (readtoken() == TPIPE);
11058                 lp->next = NULL;
11059                 n1 = pipenode;
11060         }
11061         tokpushback = 1;
11062         if (negate) {
11063                 n2 = stzalloc(sizeof(struct nnot));
11064                 n2->type = NNOT;
11065                 n2->nnot.com = n1;
11066                 return n2;
11067         }
11068         return n1;
11069 }
11070
11071 static union node *
11072 makename(void)
11073 {
11074         union node *n;
11075
11076         n = stzalloc(sizeof(struct narg));
11077         n->type = NARG;
11078         /*n->narg.next = NULL; - stzalloc did it */
11079         n->narg.text = wordtext;
11080         n->narg.backquote = backquotelist;
11081         return n;
11082 }
11083
11084 static void
11085 fixredir(union node *n, const char *text, int err)
11086 {
11087         int fd;
11088
11089         TRACE(("Fix redir %s %d\n", text, err));
11090         if (!err)
11091                 n->ndup.vname = NULL;
11092
11093         fd = bb_strtou(text, NULL, 10);
11094         if (!errno && fd >= 0)
11095                 n->ndup.dupfd = fd;
11096         else if (LONE_DASH(text))
11097                 n->ndup.dupfd = -1;
11098         else {
11099                 if (err)
11100                         raise_error_syntax("bad fd number");
11101                 n->ndup.vname = makename();
11102         }
11103 }
11104
11105 /*
11106  * Returns true if the text contains nothing to expand (no dollar signs
11107  * or backquotes).
11108  */
11109 static int
11110 noexpand(const char *text)
11111 {
11112         unsigned char c;
11113
11114         while ((c = *text++) != '\0') {
11115                 if (c == CTLQUOTEMARK)
11116                         continue;
11117                 if (c == CTLESC)
11118                         text++;
11119                 else if (SIT(c, BASESYNTAX) == CCTL)
11120                         return 0;
11121         }
11122         return 1;
11123 }
11124
11125 static void
11126 parsefname(void)
11127 {
11128         union node *n = redirnode;
11129
11130         if (readtoken() != TWORD)
11131                 raise_error_unexpected_syntax(-1);
11132         if (n->type == NHERE) {
11133                 struct heredoc *here = heredoc;
11134                 struct heredoc *p;
11135                 int i;
11136
11137                 if (quoteflag == 0)
11138                         n->type = NXHERE;
11139                 TRACE(("Here document %d\n", n->type));
11140                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11141                         raise_error_syntax("illegal eof marker for << redirection");
11142                 rmescapes(wordtext, 0);
11143                 here->eofmark = wordtext;
11144                 here->next = NULL;
11145                 if (heredoclist == NULL)
11146                         heredoclist = here;
11147                 else {
11148                         for (p = heredoclist; p->next; p = p->next)
11149                                 continue;
11150                         p->next = here;
11151                 }
11152         } else if (n->type == NTOFD || n->type == NFROMFD) {
11153                 fixredir(n, wordtext, 0);
11154         } else {
11155                 n->nfile.fname = makename();
11156         }
11157 }
11158
11159 static union node *
11160 simplecmd(void)
11161 {
11162         union node *args, **app;
11163         union node *n = NULL;
11164         union node *vars, **vpp;
11165         union node **rpp, *redir;
11166         int savecheckkwd;
11167 #if BASH_TEST2
11168         smallint double_brackets_flag = 0;
11169 #endif
11170         IF_BASH_FUNCTION(smallint function_flag = 0;)
11171
11172         args = NULL;
11173         app = &args;
11174         vars = NULL;
11175         vpp = &vars;
11176         redir = NULL;
11177         rpp = &redir;
11178
11179         savecheckkwd = CHKALIAS;
11180         for (;;) {
11181                 int t;
11182                 checkkwd = savecheckkwd;
11183                 t = readtoken();
11184                 switch (t) {
11185 #if BASH_FUNCTION
11186                 case TFUNCTION:
11187                         if (peektoken() != TWORD)
11188                                 raise_error_unexpected_syntax(TWORD);
11189                         function_flag = 1;
11190                         break;
11191 #endif
11192 #if BASH_TEST2
11193                 case TAND: /* "&&" */
11194                 case TOR: /* "||" */
11195                         if (!double_brackets_flag) {
11196                                 tokpushback = 1;
11197                                 goto out;
11198                         }
11199                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11200 #endif
11201                 case TWORD:
11202                         n = stzalloc(sizeof(struct narg));
11203                         n->type = NARG;
11204                         /*n->narg.next = NULL; - stzalloc did it */
11205                         n->narg.text = wordtext;
11206 #if BASH_TEST2
11207                         if (strcmp("[[", wordtext) == 0)
11208                                 double_brackets_flag = 1;
11209                         else if (strcmp("]]", wordtext) == 0)
11210                                 double_brackets_flag = 0;
11211 #endif
11212                         n->narg.backquote = backquotelist;
11213                         if (savecheckkwd && isassignment(wordtext)) {
11214                                 *vpp = n;
11215                                 vpp = &n->narg.next;
11216                         } else {
11217                                 *app = n;
11218                                 app = &n->narg.next;
11219                                 savecheckkwd = 0;
11220                         }
11221 #if BASH_FUNCTION
11222                         if (function_flag) {
11223                                 checkkwd = CHKNL | CHKKWD;
11224                                 switch (peektoken()) {
11225                                 case TBEGIN:
11226                                 case TIF:
11227                                 case TCASE:
11228                                 case TUNTIL:
11229                                 case TWHILE:
11230                                 case TFOR:
11231                                         goto do_func;
11232                                 case TLP:
11233                                         function_flag = 0;
11234                                         break;
11235                                 case TWORD:
11236                                         if (strcmp("[[", wordtext) == 0)
11237                                                 goto do_func;
11238                                         /* fall through */
11239                                 default:
11240                                         raise_error_unexpected_syntax(-1);
11241                                 }
11242                         }
11243 #endif
11244                         break;
11245                 case TREDIR:
11246                         *rpp = n = redirnode;
11247                         rpp = &n->nfile.next;
11248                         parsefname();   /* read name of redirection file */
11249                         break;
11250                 case TLP:
11251  IF_BASH_FUNCTION(do_func:)
11252                         if (args && app == &args->narg.next
11253                          && !vars && !redir
11254                         ) {
11255                                 struct builtincmd *bcmd;
11256                                 const char *name;
11257
11258                                 /* We have a function */
11259                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11260                                         raise_error_unexpected_syntax(TRP);
11261                                 name = n->narg.text;
11262                                 if (!goodname(name)
11263                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11264                                 ) {
11265                                         raise_error_syntax("bad function name");
11266                                 }
11267                                 n->type = NDEFUN;
11268                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11269                                 n->narg.next = parse_command();
11270                                 return n;
11271                         }
11272                         IF_BASH_FUNCTION(function_flag = 0;)
11273                         /* fall through */
11274                 default:
11275                         tokpushback = 1;
11276                         goto out;
11277                 }
11278         }
11279  out:
11280         *app = NULL;
11281         *vpp = NULL;
11282         *rpp = NULL;
11283         n = stzalloc(sizeof(struct ncmd));
11284         n->type = NCMD;
11285         n->ncmd.args = args;
11286         n->ncmd.assign = vars;
11287         n->ncmd.redirect = redir;
11288         return n;
11289 }
11290
11291 static union node *
11292 parse_command(void)
11293 {
11294         union node *n1, *n2;
11295         union node *ap, **app;
11296         union node *cp, **cpp;
11297         union node *redir, **rpp;
11298         union node **rpp2;
11299         int t;
11300
11301         redir = NULL;
11302         rpp2 = &redir;
11303
11304         switch (readtoken()) {
11305         default:
11306                 raise_error_unexpected_syntax(-1);
11307                 /* NOTREACHED */
11308         case TIF:
11309                 n1 = stzalloc(sizeof(struct nif));
11310                 n1->type = NIF;
11311                 n1->nif.test = list(0);
11312                 if (readtoken() != TTHEN)
11313                         raise_error_unexpected_syntax(TTHEN);
11314                 n1->nif.ifpart = list(0);
11315                 n2 = n1;
11316                 while (readtoken() == TELIF) {
11317                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11318                         n2 = n2->nif.elsepart;
11319                         n2->type = NIF;
11320                         n2->nif.test = list(0);
11321                         if (readtoken() != TTHEN)
11322                                 raise_error_unexpected_syntax(TTHEN);
11323                         n2->nif.ifpart = list(0);
11324                 }
11325                 if (lasttoken == TELSE)
11326                         n2->nif.elsepart = list(0);
11327                 else {
11328                         n2->nif.elsepart = NULL;
11329                         tokpushback = 1;
11330                 }
11331                 t = TFI;
11332                 break;
11333         case TWHILE:
11334         case TUNTIL: {
11335                 int got;
11336                 n1 = stzalloc(sizeof(struct nbinary));
11337                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11338                 n1->nbinary.ch1 = list(0);
11339                 got = readtoken();
11340                 if (got != TDO) {
11341                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11342                                         got == TWORD ? wordtext : ""));
11343                         raise_error_unexpected_syntax(TDO);
11344                 }
11345                 n1->nbinary.ch2 = list(0);
11346                 t = TDONE;
11347                 break;
11348         }
11349         case TFOR:
11350                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11351                         raise_error_syntax("bad for loop variable");
11352                 n1 = stzalloc(sizeof(struct nfor));
11353                 n1->type = NFOR;
11354                 n1->nfor.var = wordtext;
11355                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11356                 if (readtoken() == TIN) {
11357                         app = &ap;
11358                         while (readtoken() == TWORD) {
11359                                 n2 = stzalloc(sizeof(struct narg));
11360                                 n2->type = NARG;
11361                                 /*n2->narg.next = NULL; - stzalloc did it */
11362                                 n2->narg.text = wordtext;
11363                                 n2->narg.backquote = backquotelist;
11364                                 *app = n2;
11365                                 app = &n2->narg.next;
11366                         }
11367                         *app = NULL;
11368                         n1->nfor.args = ap;
11369                         if (lasttoken != TNL && lasttoken != TSEMI)
11370                                 raise_error_unexpected_syntax(-1);
11371                 } else {
11372                         n2 = stzalloc(sizeof(struct narg));
11373                         n2->type = NARG;
11374                         /*n2->narg.next = NULL; - stzalloc did it */
11375                         n2->narg.text = (char *)dolatstr;
11376                         /*n2->narg.backquote = NULL;*/
11377                         n1->nfor.args = n2;
11378                         /*
11379                          * Newline or semicolon here is optional (but note
11380                          * that the original Bourne shell only allowed NL).
11381                          */
11382                         if (lasttoken != TSEMI)
11383                                 tokpushback = 1;
11384                 }
11385                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11386                 if (readtoken() != TDO)
11387                         raise_error_unexpected_syntax(TDO);
11388                 n1->nfor.body = list(0);
11389                 t = TDONE;
11390                 break;
11391         case TCASE:
11392                 n1 = stzalloc(sizeof(struct ncase));
11393                 n1->type = NCASE;
11394                 if (readtoken() != TWORD)
11395                         raise_error_unexpected_syntax(TWORD);
11396                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11397                 n2->type = NARG;
11398                 /*n2->narg.next = NULL; - stzalloc did it */
11399                 n2->narg.text = wordtext;
11400                 n2->narg.backquote = backquotelist;
11401                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11402                 if (readtoken() != TIN)
11403                         raise_error_unexpected_syntax(TIN);
11404                 cpp = &n1->ncase.cases;
11405  next_case:
11406                 checkkwd = CHKNL | CHKKWD;
11407                 t = readtoken();
11408                 while (t != TESAC) {
11409                         if (lasttoken == TLP)
11410                                 readtoken();
11411                         *cpp = cp = stzalloc(sizeof(struct nclist));
11412                         cp->type = NCLIST;
11413                         app = &cp->nclist.pattern;
11414                         for (;;) {
11415                                 *app = ap = stzalloc(sizeof(struct narg));
11416                                 ap->type = NARG;
11417                                 /*ap->narg.next = NULL; - stzalloc did it */
11418                                 ap->narg.text = wordtext;
11419                                 ap->narg.backquote = backquotelist;
11420                                 if (readtoken() != TPIPE)
11421                                         break;
11422                                 app = &ap->narg.next;
11423                                 readtoken();
11424                         }
11425                         //ap->narg.next = NULL;
11426                         if (lasttoken != TRP)
11427                                 raise_error_unexpected_syntax(TRP);
11428                         cp->nclist.body = list(2);
11429
11430                         cpp = &cp->nclist.next;
11431
11432                         checkkwd = CHKNL | CHKKWD;
11433                         t = readtoken();
11434                         if (t != TESAC) {
11435                                 if (t != TENDCASE)
11436                                         raise_error_unexpected_syntax(TENDCASE);
11437                                 goto next_case;
11438                         }
11439                 }
11440                 *cpp = NULL;
11441                 goto redir;
11442         case TLP:
11443                 n1 = stzalloc(sizeof(struct nredir));
11444                 n1->type = NSUBSHELL;
11445                 n1->nredir.n = list(0);
11446                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11447                 t = TRP;
11448                 break;
11449         case TBEGIN:
11450                 n1 = list(0);
11451                 t = TEND;
11452                 break;
11453         IF_BASH_FUNCTION(case TFUNCTION:)
11454         case TWORD:
11455         case TREDIR:
11456                 tokpushback = 1;
11457                 return simplecmd();
11458         }
11459
11460         if (readtoken() != t)
11461                 raise_error_unexpected_syntax(t);
11462
11463  redir:
11464         /* Now check for redirection which may follow command */
11465         checkkwd = CHKKWD | CHKALIAS;
11466         rpp = rpp2;
11467         while (readtoken() == TREDIR) {
11468                 *rpp = n2 = redirnode;
11469                 rpp = &n2->nfile.next;
11470                 parsefname();
11471         }
11472         tokpushback = 1;
11473         *rpp = NULL;
11474         if (redir) {
11475                 if (n1->type != NSUBSHELL) {
11476                         n2 = stzalloc(sizeof(struct nredir));
11477                         n2->type = NREDIR;
11478                         n2->nredir.n = n1;
11479                         n1 = n2;
11480                 }
11481                 n1->nredir.redirect = redir;
11482         }
11483         return n1;
11484 }
11485
11486 #if BASH_DOLLAR_SQUOTE
11487 static int
11488 decode_dollar_squote(void)
11489 {
11490         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11491         int c, cnt;
11492         char *p;
11493         char buf[4];
11494
11495         c = pgetc();
11496         p = strchr(C_escapes, c);
11497         if (p) {
11498                 buf[0] = c;
11499                 p = buf;
11500                 cnt = 3;
11501                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11502                         do {
11503                                 c = pgetc();
11504                                 *++p = c;
11505                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11506                         pungetc();
11507                 } else if (c == 'x') { /* \xHH */
11508                         do {
11509                                 c = pgetc();
11510                                 *++p = c;
11511                         } while (isxdigit(c) && --cnt);
11512                         pungetc();
11513                         if (cnt == 3) { /* \x but next char is "bad" */
11514                                 c = 'x';
11515                                 goto unrecognized;
11516                         }
11517                 } else { /* simple seq like \\ or \t */
11518                         p++;
11519                 }
11520                 *p = '\0';
11521                 p = buf;
11522                 c = bb_process_escape_sequence((void*)&p);
11523         } else { /* unrecognized "\z": print both chars unless ' or " */
11524                 if (c != '\'' && c != '"') {
11525  unrecognized:
11526                         c |= 0x100; /* "please encode \, then me" */
11527                 }
11528         }
11529         return c;
11530 }
11531 #endif
11532
11533 /*
11534  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11535  * is not NULL, read a here document.  In the latter case, eofmark is the
11536  * word which marks the end of the document and striptabs is true if
11537  * leading tabs should be stripped from the document.  The argument c
11538  * is the first character of the input token or document.
11539  *
11540  * Because C does not have internal subroutines, I have simulated them
11541  * using goto's to implement the subroutine linkage.  The following macros
11542  * will run code that appears at the end of readtoken1.
11543  */
11544 #define CHECKEND()      {goto checkend; checkend_return:;}
11545 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11546 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11547 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11548 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11549 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11550 static int
11551 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11552 {
11553         /* NB: syntax parameter fits into smallint */
11554         /* c parameter is an unsigned char or PEOF or PEOA */
11555         char *out;
11556         size_t len;
11557         char line[EOFMARKLEN + 1];
11558         struct nodelist *bqlist;
11559         smallint quotef;
11560         smallint dblquote;
11561         smallint oldstyle;
11562         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11563         smallint pssyntax;   /* we are expanding a prompt string */
11564         int varnest;         /* levels of variables expansion */
11565         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11566         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11567         int dqvarnest;       /* levels of variables expansion within double quotes */
11568
11569         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11570
11571         startlinno = g_parsefile->linno;
11572         bqlist = NULL;
11573         quotef = 0;
11574         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11575         pssyntax = (syntax == PSSYNTAX);
11576         if (pssyntax)
11577                 syntax = DQSYNTAX;
11578         dblquote = (syntax == DQSYNTAX);
11579         varnest = 0;
11580         IF_FEATURE_SH_MATH(arinest = 0;)
11581         IF_FEATURE_SH_MATH(parenlevel = 0;)
11582         dqvarnest = 0;
11583
11584         STARTSTACKSTR(out);
11585  loop:
11586         /* For each line, until end of word */
11587         CHECKEND();     /* set c to PEOF if at end of here document */
11588         for (;;) {      /* until end of line or end of word */
11589                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11590                 switch (SIT(c, syntax)) {
11591                 case CNL:       /* '\n' */
11592                         if (syntax == BASESYNTAX)
11593                                 goto endword;   /* exit outer loop */
11594                         USTPUTC(c, out);
11595                         nlprompt();
11596                         c = pgetc();
11597                         goto loop;              /* continue outer loop */
11598                 case CWORD:
11599                         USTPUTC(c, out);
11600                         break;
11601                 case CCTL:
11602 #if BASH_DOLLAR_SQUOTE
11603                         if (c == '\\' && bash_dollar_squote) {
11604                                 c = decode_dollar_squote();
11605                                 if (c == '\0') {
11606                                         /* skip $'\000', $'\x00' (like bash) */
11607                                         break;
11608                                 }
11609                                 if (c & 0x100) {
11610                                         /* Unknown escape. Encode as '\z' */
11611                                         c = (unsigned char)c;
11612                                         if (eofmark == NULL || dblquote)
11613                                                 USTPUTC(CTLESC, out);
11614                                         USTPUTC('\\', out);
11615                                 }
11616                         }
11617 #endif
11618                         if (eofmark == NULL || dblquote)
11619                                 USTPUTC(CTLESC, out);
11620                         USTPUTC(c, out);
11621                         break;
11622                 case CBACK:     /* backslash */
11623                         c = pgetc_without_PEOA();
11624                         if (c == PEOF) {
11625                                 USTPUTC(CTLESC, out);
11626                                 USTPUTC('\\', out);
11627                                 pungetc();
11628                         } else if (c == '\n') {
11629                                 nlprompt();
11630                         } else {
11631                                 if (c == '$' && pssyntax) {
11632                                         USTPUTC(CTLESC, out);
11633                                         USTPUTC('\\', out);
11634                                 }
11635                                 /* Backslash is retained if we are in "str" and next char isn't special */
11636                                 if (dblquote
11637                                  && c != '\\'
11638                                  && c != '`'
11639                                  && c != '$'
11640                                  && (c != '"' || eofmark != NULL)
11641                                 ) {
11642                                         USTPUTC('\\', out);
11643                                 }
11644                                 USTPUTC(CTLESC, out);
11645                                 USTPUTC(c, out);
11646                                 quotef = 1;
11647                         }
11648                         break;
11649                 case CSQUOTE:
11650                         syntax = SQSYNTAX;
11651  quotemark:
11652                         if (eofmark == NULL) {
11653                                 USTPUTC(CTLQUOTEMARK, out);
11654                         }
11655                         break;
11656                 case CDQUOTE:
11657                         syntax = DQSYNTAX;
11658                         dblquote = 1;
11659                         goto quotemark;
11660                 case CENDQUOTE:
11661                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11662                         if (eofmark != NULL && varnest == 0) {
11663                                 USTPUTC(c, out);
11664                         } else {
11665                                 if (dqvarnest == 0) {
11666                                         syntax = BASESYNTAX;
11667                                         dblquote = 0;
11668                                 }
11669                                 quotef = 1;
11670                                 goto quotemark;
11671                         }
11672                         break;
11673                 case CVAR:      /* '$' */
11674                         PARSESUB();             /* parse substitution */
11675                         break;
11676                 case CENDVAR:   /* '}' */
11677                         if (varnest > 0) {
11678                                 varnest--;
11679                                 if (dqvarnest > 0) {
11680                                         dqvarnest--;
11681                                 }
11682                                 c = CTLENDVAR;
11683                         }
11684                         USTPUTC(c, out);
11685                         break;
11686 #if ENABLE_FEATURE_SH_MATH
11687                 case CLP:       /* '(' in arithmetic */
11688                         parenlevel++;
11689                         USTPUTC(c, out);
11690                         break;
11691                 case CRP:       /* ')' in arithmetic */
11692                         if (parenlevel > 0) {
11693                                 parenlevel--;
11694                         } else {
11695                                 if (pgetc_eatbnl() == ')') {
11696                                         c = CTLENDARI;
11697                                         if (--arinest == 0) {
11698                                                 syntax = prevsyntax;
11699                                         }
11700                                 } else {
11701                                         /*
11702                                          * unbalanced parens
11703                                          * (don't 2nd guess - no error)
11704                                          */
11705                                         pungetc();
11706                                 }
11707                         }
11708                         USTPUTC(c, out);
11709                         break;
11710 #endif
11711                 case CBQUOTE:   /* '`' */
11712                         PARSEBACKQOLD();
11713                         break;
11714                 case CENDFILE:
11715                         goto endword;           /* exit outer loop */
11716                 case CIGN:
11717                         break;
11718                 default:
11719                         if (varnest == 0) {
11720 #if BASH_REDIR_OUTPUT
11721                                 if (c == '&') {
11722 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11723                                         if (pgetc() == '>')
11724                                                 c = 0x100 + '>'; /* flag &> */
11725                                         pungetc();
11726                                 }
11727 #endif
11728                                 goto endword;   /* exit outer loop */
11729                         }
11730                         IF_ASH_ALIAS(if (c != PEOA))
11731                                 USTPUTC(c, out);
11732                 }
11733                 c = pgetc();
11734         } /* for (;;) */
11735  endword:
11736
11737 #if ENABLE_FEATURE_SH_MATH
11738         if (syntax == ARISYNTAX)
11739                 raise_error_syntax("missing '))'");
11740 #endif
11741         if (syntax != BASESYNTAX && eofmark == NULL)
11742                 raise_error_syntax("unterminated quoted string");
11743         if (varnest != 0) {
11744                 startlinno = g_parsefile->linno;
11745                 /* { */
11746                 raise_error_syntax("missing '}'");
11747         }
11748         USTPUTC('\0', out);
11749         len = out - (char *)stackblock();
11750         out = stackblock();
11751         if (eofmark == NULL) {
11752                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11753                  && quotef == 0
11754                 ) {
11755                         if (isdigit_str9(out)) {
11756                                 PARSEREDIR(); /* passed as params: out, c */
11757                                 lasttoken = TREDIR;
11758                                 return lasttoken;
11759                         }
11760                         /* else: non-number X seen, interpret it
11761                          * as "NNNX>file" = "NNNX >file" */
11762                 }
11763                 pungetc();
11764         }
11765         quoteflag = quotef;
11766         backquotelist = bqlist;
11767         grabstackblock(len);
11768         wordtext = out;
11769         lasttoken = TWORD;
11770         return lasttoken;
11771 /* end of readtoken routine */
11772
11773 /*
11774  * Check to see whether we are at the end of the here document.  When this
11775  * is called, c is set to the first character of the next input line.  If
11776  * we are at the end of the here document, this routine sets the c to PEOF.
11777  */
11778 checkend: {
11779         if (eofmark) {
11780 #if ENABLE_ASH_ALIAS
11781                 if (c == PEOA)
11782                         c = pgetc_without_PEOA();
11783 #endif
11784                 if (striptabs) {
11785                         while (c == '\t') {
11786                                 c = pgetc_without_PEOA();
11787                         }
11788                 }
11789                 if (c == *eofmark) {
11790                         if (pfgets(line, sizeof(line)) != NULL) {
11791                                 char *p, *q;
11792                                 int cc;
11793
11794                                 p = line;
11795                                 for (q = eofmark + 1;; p++, q++) {
11796                                         cc = *p;
11797                                         if (cc == '\n')
11798                                                 cc = 0;
11799                                         if (!*q || cc != *q)
11800                                                 break;
11801                                 }
11802                                 if (cc == *q) {
11803                                         c = PEOF;
11804                                         nlnoprompt();
11805                                 } else {
11806                                         pushstring(line, NULL);
11807                                 }
11808                         }
11809                 }
11810         }
11811         goto checkend_return;
11812 }
11813
11814 /*
11815  * Parse a redirection operator.  The variable "out" points to a string
11816  * specifying the fd to be redirected.  The variable "c" contains the
11817  * first character of the redirection operator.
11818  */
11819 parseredir: {
11820         /* out is already checked to be a valid number or "" */
11821         int fd = (*out == '\0' ? -1 : atoi(out));
11822         union node *np;
11823
11824         np = stzalloc(sizeof(struct nfile));
11825         if (c == '>') {
11826                 np->nfile.fd = 1;
11827                 c = pgetc();
11828                 if (c == '>')
11829                         np->type = NAPPEND;
11830                 else if (c == '|')
11831                         np->type = NCLOBBER;
11832                 else if (c == '&')
11833                         np->type = NTOFD;
11834                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11835                 else {
11836                         np->type = NTO;
11837                         pungetc();
11838                 }
11839         }
11840 #if BASH_REDIR_OUTPUT
11841         else if (c == 0x100 + '>') { /* this flags &> redirection */
11842                 np->nfile.fd = 1;
11843                 pgetc(); /* this is '>', no need to check */
11844                 np->type = NTO2;
11845         }
11846 #endif
11847         else { /* c == '<' */
11848                 /*np->nfile.fd = 0; - stzalloc did it */
11849                 c = pgetc();
11850                 switch (c) {
11851                 case '<':
11852                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11853                                 np = stzalloc(sizeof(struct nhere));
11854                                 /*np->nfile.fd = 0; - stzalloc did it */
11855                         }
11856                         np->type = NHERE;
11857                         heredoc = stzalloc(sizeof(struct heredoc));
11858                         heredoc->here = np;
11859                         c = pgetc();
11860                         if (c == '-') {
11861                                 heredoc->striptabs = 1;
11862                         } else {
11863                                 /*heredoc->striptabs = 0; - stzalloc did it */
11864                                 pungetc();
11865                         }
11866                         break;
11867
11868                 case '&':
11869                         np->type = NFROMFD;
11870                         break;
11871
11872                 case '>':
11873                         np->type = NFROMTO;
11874                         break;
11875
11876                 default:
11877                         np->type = NFROM;
11878                         pungetc();
11879                         break;
11880                 }
11881         }
11882         if (fd >= 0)
11883                 np->nfile.fd = fd;
11884         redirnode = np;
11885         goto parseredir_return;
11886 }
11887
11888 /*
11889  * Parse a substitution.  At this point, we have read the dollar sign
11890  * and nothing else.
11891  */
11892
11893 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11894  * (assuming ascii char codes, as the original implementation did) */
11895 #define is_special(c) \
11896         (((unsigned)(c) - 33 < 32) \
11897                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11898 parsesub: {
11899         unsigned char subtype;
11900         int typeloc;
11901
11902         c = pgetc_eatbnl();
11903         if (c > 255 /* PEOA or PEOF */
11904          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11905         ) {
11906 #if BASH_DOLLAR_SQUOTE
11907                 if (syntax != DQSYNTAX && c == '\'')
11908                         bash_dollar_squote = 1;
11909                 else
11910 #endif
11911                         USTPUTC('$', out);
11912                 pungetc();
11913         } else if (c == '(') {
11914                 /* $(command) or $((arith)) */
11915                 if (pgetc_eatbnl() == '(') {
11916 #if ENABLE_FEATURE_SH_MATH
11917                         PARSEARITH();
11918 #else
11919                         raise_error_syntax("support for $((arith)) is disabled");
11920 #endif
11921                 } else {
11922                         pungetc();
11923                         PARSEBACKQNEW();
11924                 }
11925         } else {
11926                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11927                 USTPUTC(CTLVAR, out);
11928                 typeloc = out - (char *)stackblock();
11929                 STADJUST(1, out);
11930                 subtype = VSNORMAL;
11931                 if (c == '{') {
11932                         c = pgetc_eatbnl();
11933                         subtype = 0;
11934                 }
11935  varname:
11936                 if (is_name(c)) {
11937                         /* $[{[#]]NAME[}] */
11938                         do {
11939                                 STPUTC(c, out);
11940                                 c = pgetc_eatbnl();
11941                         } while (is_in_name(c));
11942                 } else if (isdigit(c)) {
11943                         /* $[{[#]]NUM[}] */
11944                         do {
11945                                 STPUTC(c, out);
11946                                 c = pgetc_eatbnl();
11947                         } while (isdigit(c));
11948                 } else if (is_special(c)) {
11949                         /* $[{[#]]<specialchar>[}] */
11950                         int cc = c;
11951
11952                         c = pgetc_eatbnl();
11953                         if (!subtype && cc == '#') {
11954                                 subtype = VSLENGTH;
11955                                 if (c == '_' || isalnum(c))
11956                                         goto varname;
11957                                 cc = c;
11958                                 c = pgetc_eatbnl();
11959                                 if (cc == '}' || c != '}') {
11960                                         pungetc();
11961                                         subtype = 0;
11962                                         c = cc;
11963                                         cc = '#';
11964                                 }
11965                         }
11966                         USTPUTC(cc, out);
11967                 } else {
11968                         goto badsub;
11969                 }
11970                 if (c != '}' && subtype == VSLENGTH) {
11971                         /* ${#VAR didn't end with } */
11972                         goto badsub;
11973                 }
11974
11975                 if (subtype == 0) {
11976                         static const char types[] ALIGN1 = "}-+?=";
11977                         /* ${VAR...} but not $VAR or ${#VAR} */
11978                         /* c == first char after VAR */
11979                         switch (c) {
11980                         case ':':
11981                                 c = pgetc_eatbnl();
11982 #if BASH_SUBSTR
11983                                 /* This check is only needed to not misinterpret
11984                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11985                                  * constructs.
11986                                  */
11987                                 if (!strchr(types, c)) {
11988                                         subtype = VSSUBSTR;
11989                                         pungetc();
11990                                         break; /* "goto badsub" is bigger (!) */
11991                                 }
11992 #endif
11993                                 subtype = VSNUL;
11994                                 /*FALLTHROUGH*/
11995                         default: {
11996                                 const char *p = strchr(types, c);
11997                                 if (p == NULL)
11998                                         break;
11999                                 subtype |= p - types + VSNORMAL;
12000                                 break;
12001                         }
12002                         case '%':
12003                         case '#': {
12004                                 int cc = c;
12005                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12006                                 c = pgetc_eatbnl();
12007                                 if (c != cc)
12008                                         goto badsub;
12009                                 subtype++;
12010                                 break;
12011                         }
12012 #if BASH_PATTERN_SUBST
12013                         case '/':
12014                                 /* ${v/[/]pattern/repl} */
12015 //TODO: encode pattern and repl separately.
12016 // Currently ${v/$var_with_slash/repl} is horribly broken
12017                                 subtype = VSREPLACE;
12018                                 c = pgetc_eatbnl();
12019                                 if (c != '/')
12020                                         goto badsub;
12021                                 subtype++; /* VSREPLACEALL */
12022                                 break;
12023 #endif
12024                         }
12025                 } else {
12026  badsub:
12027                         pungetc();
12028                 }
12029                 ((unsigned char *)stackblock())[typeloc] = subtype;
12030                 if (subtype != VSNORMAL) {
12031                         varnest++;
12032                         if (dblquote)
12033                                 dqvarnest++;
12034                 }
12035                 STPUTC('=', out);
12036         }
12037         goto parsesub_return;
12038 }
12039
12040 /*
12041  * Called to parse command substitutions.  Newstyle is set if the command
12042  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12043  * list of commands (passed by reference), and savelen is the number of
12044  * characters on the top of the stack which must be preserved.
12045  */
12046 parsebackq: {
12047         struct nodelist **nlpp;
12048         union node *n;
12049         char *str;
12050         size_t savelen;
12051         smallint saveprompt = 0;
12052
12053         str = NULL;
12054         savelen = out - (char *)stackblock();
12055         if (savelen > 0) {
12056                 /*
12057                  * FIXME: this can allocate very large block on stack and SEGV.
12058                  * Example:
12059                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12060                  * allocates 100kb for every command subst. With about
12061                  * a hundred command substitutions stack overflows.
12062                  * With larger prepended string, SEGV happens sooner.
12063                  */
12064                 str = alloca(savelen);
12065                 memcpy(str, stackblock(), savelen);
12066         }
12067
12068         if (oldstyle) {
12069                 /* We must read until the closing backquote, giving special
12070                  * treatment to some slashes, and then push the string and
12071                  * reread it as input, interpreting it normally.
12072                  */
12073                 char *pout;
12074                 size_t psavelen;
12075                 char *pstr;
12076
12077                 STARTSTACKSTR(pout);
12078                 for (;;) {
12079                         int pc;
12080
12081                         setprompt_if(needprompt, 2);
12082                         pc = pgetc();
12083                         switch (pc) {
12084                         case '`':
12085                                 goto done;
12086
12087                         case '\\':
12088                                 pc = pgetc();
12089                                 if (pc == '\n') {
12090                                         nlprompt();
12091                                         /*
12092                                          * If eating a newline, avoid putting
12093                                          * the newline into the new character
12094                                          * stream (via the STPUTC after the
12095                                          * switch).
12096                                          */
12097                                         continue;
12098                                 }
12099                                 if (pc != '\\' && pc != '`' && pc != '$'
12100                                  && (!dblquote || pc != '"')
12101                                 ) {
12102                                         STPUTC('\\', pout);
12103                                 }
12104                                 if (pc <= 255 /* not PEOA or PEOF */) {
12105                                         break;
12106                                 }
12107                                 /* fall through */
12108
12109                         case PEOF:
12110                         IF_ASH_ALIAS(case PEOA:)
12111                                 startlinno = g_parsefile->linno;
12112                                 raise_error_syntax("EOF in backquote substitution");
12113
12114                         case '\n':
12115                                 nlnoprompt();
12116                                 break;
12117
12118                         default:
12119                                 break;
12120                         }
12121                         STPUTC(pc, pout);
12122                 }
12123  done:
12124                 STPUTC('\0', pout);
12125                 psavelen = pout - (char *)stackblock();
12126                 if (psavelen > 0) {
12127                         pstr = grabstackstr(pout);
12128                         setinputstring(pstr);
12129                 }
12130         }
12131         nlpp = &bqlist;
12132         while (*nlpp)
12133                 nlpp = &(*nlpp)->next;
12134         *nlpp = stzalloc(sizeof(**nlpp));
12135         /* (*nlpp)->next = NULL; - stzalloc did it */
12136
12137         if (oldstyle) {
12138                 saveprompt = doprompt;
12139                 doprompt = 0;
12140         }
12141
12142         n = list(2);
12143
12144         if (oldstyle)
12145                 doprompt = saveprompt;
12146         else if (readtoken() != TRP)
12147                 raise_error_unexpected_syntax(TRP);
12148
12149         (*nlpp)->n = n;
12150         if (oldstyle) {
12151                 /*
12152                  * Start reading from old file again, ignoring any pushed back
12153                  * tokens left from the backquote parsing
12154                  */
12155                 popfile();
12156                 tokpushback = 0;
12157         }
12158         while (stackblocksize() <= savelen)
12159                 growstackblock();
12160         STARTSTACKSTR(out);
12161         if (str) {
12162                 memcpy(out, str, savelen);
12163                 STADJUST(savelen, out);
12164         }
12165         USTPUTC(CTLBACKQ, out);
12166         if (oldstyle)
12167                 goto parsebackq_oldreturn;
12168         goto parsebackq_newreturn;
12169 }
12170
12171 #if ENABLE_FEATURE_SH_MATH
12172 /*
12173  * Parse an arithmetic expansion (indicate start of one and set state)
12174  */
12175 parsearith: {
12176         if (++arinest == 1) {
12177                 prevsyntax = syntax;
12178                 syntax = ARISYNTAX;
12179         }
12180         USTPUTC(CTLARI, out);
12181         goto parsearith_return;
12182 }
12183 #endif
12184 } /* end of readtoken */
12185
12186 /*
12187  * Read the next input token.
12188  * If the token is a word, we set backquotelist to the list of cmds in
12189  *      backquotes.  We set quoteflag to true if any part of the word was
12190  *      quoted.
12191  * If the token is TREDIR, then we set redirnode to a structure containing
12192  *      the redirection.
12193  * In all cases, the variable startlinno is set to the number of the line
12194  *      on which the token starts.
12195  *
12196  * [Change comment:  here documents and internal procedures]
12197  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12198  *  word parsing code into a separate routine.  In this case, readtoken
12199  *  doesn't need to have any internal procedures, but parseword does.
12200  *  We could also make parseoperator in essence the main routine, and
12201  *  have parseword (readtoken1?) handle both words and redirection.]
12202  */
12203 #define NEW_xxreadtoken
12204 #ifdef NEW_xxreadtoken
12205 /* singles must be first! */
12206 static const char xxreadtoken_chars[7] ALIGN1 = {
12207         '\n', '(', ')', /* singles */
12208         '&', '|', ';',  /* doubles */
12209         0
12210 };
12211
12212 #define xxreadtoken_singles 3
12213 #define xxreadtoken_doubles 3
12214
12215 static const char xxreadtoken_tokens[] ALIGN1 = {
12216         TNL, TLP, TRP,          /* only single occurrence allowed */
12217         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12218         TEOF,                   /* corresponds to trailing nul */
12219         TAND, TOR, TENDCASE     /* if double occurrence */
12220 };
12221
12222 static int
12223 xxreadtoken(void)
12224 {
12225         int c;
12226
12227         if (tokpushback) {
12228                 tokpushback = 0;
12229                 return lasttoken;
12230         }
12231         setprompt_if(needprompt, 2);
12232         startlinno = g_parsefile->linno;
12233         for (;;) {                      /* until token or start of word found */
12234                 c = pgetc();
12235                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12236                         continue;
12237
12238                 if (c == '#') {
12239                         while ((c = pgetc()) != '\n' && c != PEOF)
12240                                 continue;
12241                         pungetc();
12242                 } else if (c == '\\') {
12243                         if (pgetc() != '\n') {
12244                                 pungetc();
12245                                 break; /* return readtoken1(...) */
12246                         }
12247                         nlprompt();
12248                 } else {
12249                         const char *p;
12250
12251                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12252                         if (c != PEOF) {
12253                                 if (c == '\n') {
12254                                         nlnoprompt();
12255                                 }
12256
12257                                 p = strchr(xxreadtoken_chars, c);
12258                                 if (p == NULL)
12259                                         break; /* return readtoken1(...) */
12260
12261                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12262                                         int cc = pgetc();
12263                                         if (cc == c) {    /* double occurrence? */
12264                                                 p += xxreadtoken_doubles + 1;
12265                                         } else {
12266                                                 pungetc();
12267 #if BASH_REDIR_OUTPUT
12268                                                 if (c == '&' && cc == '>') /* &> */
12269                                                         break; /* return readtoken1(...) */
12270 #endif
12271                                         }
12272                                 }
12273                         }
12274                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12275                         return lasttoken;
12276                 }
12277         } /* for (;;) */
12278
12279         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12280 }
12281 #else /* old xxreadtoken */
12282 #define RETURN(token)   return lasttoken = token
12283 static int
12284 xxreadtoken(void)
12285 {
12286         int c;
12287
12288         if (tokpushback) {
12289                 tokpushback = 0;
12290                 return lasttoken;
12291         }
12292         setprompt_if(needprompt, 2);
12293         startlinno = g_parsefile->linno;
12294         for (;;) {      /* until token or start of word found */
12295                 c = pgetc();
12296                 switch (c) {
12297                 case ' ': case '\t':
12298                 IF_ASH_ALIAS(case PEOA:)
12299                         continue;
12300                 case '#':
12301                         while ((c = pgetc()) != '\n' && c != PEOF)
12302                                 continue;
12303                         pungetc();
12304                         continue;
12305                 case '\\':
12306                         if (pgetc() == '\n') {
12307                                 nlprompt();
12308                                 continue;
12309                         }
12310                         pungetc();
12311                         goto breakloop;
12312                 case '\n':
12313                         nlnoprompt();
12314                         RETURN(TNL);
12315                 case PEOF:
12316                         RETURN(TEOF);
12317                 case '&':
12318                         if (pgetc() == '&')
12319                                 RETURN(TAND);
12320                         pungetc();
12321                         RETURN(TBACKGND);
12322                 case '|':
12323                         if (pgetc() == '|')
12324                                 RETURN(TOR);
12325                         pungetc();
12326                         RETURN(TPIPE);
12327                 case ';':
12328                         if (pgetc() == ';')
12329                                 RETURN(TENDCASE);
12330                         pungetc();
12331                         RETURN(TSEMI);
12332                 case '(':
12333                         RETURN(TLP);
12334                 case ')':
12335                         RETURN(TRP);
12336                 default:
12337                         goto breakloop;
12338                 }
12339         }
12340  breakloop:
12341         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12342 #undef RETURN
12343 }
12344 #endif /* old xxreadtoken */
12345
12346 static int
12347 readtoken(void)
12348 {
12349         int t;
12350         int kwd = checkkwd;
12351 #if DEBUG
12352         smallint alreadyseen = tokpushback;
12353 #endif
12354
12355 #if ENABLE_ASH_ALIAS
12356  top:
12357 #endif
12358
12359         t = xxreadtoken();
12360
12361         /*
12362          * eat newlines
12363          */
12364         if (kwd & CHKNL) {
12365                 while (t == TNL) {
12366                         parseheredoc();
12367                         t = xxreadtoken();
12368                 }
12369         }
12370
12371         if (t != TWORD || quoteflag) {
12372                 goto out;
12373         }
12374
12375         /*
12376          * check for keywords
12377          */
12378         if (kwd & CHKKWD) {
12379                 const char *const *pp;
12380
12381                 pp = findkwd(wordtext);
12382                 if (pp) {
12383                         lasttoken = t = pp - tokname_array;
12384                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12385                         goto out;
12386                 }
12387         }
12388
12389         if (checkkwd & CHKALIAS) {
12390 #if ENABLE_ASH_ALIAS
12391                 struct alias *ap;
12392                 ap = lookupalias(wordtext, 1);
12393                 if (ap != NULL) {
12394                         if (*ap->val) {
12395                                 pushstring(ap->val, ap);
12396                         }
12397                         goto top;
12398                 }
12399 #endif
12400         }
12401  out:
12402         checkkwd = 0;
12403 #if DEBUG
12404         if (!alreadyseen)
12405                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12406         else
12407                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12408 #endif
12409         return t;
12410 }
12411
12412 static int
12413 peektoken(void)
12414 {
12415         int t;
12416
12417         t = readtoken();
12418         tokpushback = 1;
12419         return t;
12420 }
12421
12422 /*
12423  * Read and parse a command.  Returns NODE_EOF on end of file.
12424  * (NULL is a valid parse tree indicating a blank line.)
12425  */
12426 static union node *
12427 parsecmd(int interact)
12428 {
12429         tokpushback = 0;
12430         checkkwd = 0;
12431         heredoclist = 0;
12432         doprompt = interact;
12433         setprompt_if(doprompt, doprompt);
12434         needprompt = 0;
12435         return list(1);
12436 }
12437
12438 /*
12439  * Input any here documents.
12440  */
12441 static void
12442 parseheredoc(void)
12443 {
12444         struct heredoc *here;
12445         union node *n;
12446
12447         here = heredoclist;
12448         heredoclist = NULL;
12449
12450         while (here) {
12451                 setprompt_if(needprompt, 2);
12452                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12453                                 here->eofmark, here->striptabs);
12454                 n = stzalloc(sizeof(struct narg));
12455                 n->narg.type = NARG;
12456                 /*n->narg.next = NULL; - stzalloc did it */
12457                 n->narg.text = wordtext;
12458                 n->narg.backquote = backquotelist;
12459                 here->here->nhere.doc = n;
12460                 here = here->next;
12461         }
12462 }
12463
12464
12465 /*
12466  * called by editline -- any expansions to the prompt should be added here.
12467  */
12468 static const char *
12469 expandstr(const char *ps)
12470 {
12471         union node n;
12472         int saveprompt;
12473
12474         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12475          * and token processing _can_ alter it (delete NULs etc). */
12476         setinputstring((char *)ps);
12477
12478         saveprompt = doprompt;
12479         doprompt = 0;
12480         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12481         doprompt = saveprompt;
12482
12483         popfile();
12484
12485         n.narg.type = NARG;
12486         n.narg.next = NULL;
12487         n.narg.text = wordtext;
12488         n.narg.backquote = backquotelist;
12489
12490         expandarg(&n, NULL, EXP_QUOTED);
12491         return stackblock();
12492 }
12493
12494 /*
12495  * Execute a command or commands contained in a string.
12496  */
12497 static int
12498 evalstring(char *s, int flags)
12499 {
12500         struct jmploc *volatile savehandler;
12501         struct jmploc jmploc;
12502         int ex;
12503
12504         union node *n;
12505         struct stackmark smark;
12506         int status;
12507
12508         s = sstrdup(s);
12509         setinputstring(s);
12510         setstackmark(&smark);
12511
12512         status = 0;
12513         /* On exception inside execution loop, we must popfile().
12514          * Try interactively:
12515          *      readonly a=a
12516          *      command eval "a=b"  # throws "is read only" error
12517          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12518          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12519          */
12520         savehandler = exception_handler;
12521         ex = setjmp(jmploc.loc);
12522         if (ex)
12523                 goto out;
12524         exception_handler = &jmploc;
12525
12526         while ((n = parsecmd(0)) != NODE_EOF) {
12527                 int i;
12528
12529                 i = evaltree(n, flags);
12530                 if (n)
12531                         status = i;
12532                 popstackmark(&smark);
12533                 if (evalskip)
12534                         break;
12535         }
12536  out:
12537         popstackmark(&smark);
12538         popfile();
12539         stunalloc(s);
12540
12541         exception_handler = savehandler;
12542         if (ex)
12543                 longjmp(exception_handler->loc, ex);
12544
12545         return status;
12546 }
12547
12548 /*
12549  * The eval command.
12550  */
12551 static int FAST_FUNC
12552 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12553 {
12554         char *p;
12555         char *concat;
12556
12557         if (argv[1]) {
12558                 p = argv[1];
12559                 argv += 2;
12560                 if (argv[0]) {
12561                         STARTSTACKSTR(concat);
12562                         for (;;) {
12563                                 concat = stack_putstr(p, concat);
12564                                 p = *argv++;
12565                                 if (p == NULL)
12566                                         break;
12567                                 STPUTC(' ', concat);
12568                         }
12569                         STPUTC('\0', concat);
12570                         p = grabstackstr(concat);
12571                 }
12572                 return evalstring(p, flags & EV_TESTED);
12573         }
12574         return 0;
12575 }
12576
12577 /*
12578  * Read and execute commands.
12579  * "Top" is nonzero for the top level command loop;
12580  * it turns on prompting if the shell is interactive.
12581  */
12582 static int
12583 cmdloop(int top)
12584 {
12585         union node *n;
12586         struct stackmark smark;
12587         int inter;
12588         int status = 0;
12589         int numeof = 0;
12590
12591         TRACE(("cmdloop(%d) called\n", top));
12592         for (;;) {
12593                 int skip;
12594
12595                 setstackmark(&smark);
12596 #if JOBS
12597                 if (doing_jobctl)
12598                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12599 #endif
12600                 inter = 0;
12601                 if (iflag && top) {
12602                         inter++;
12603                         chkmail();
12604                 }
12605                 n = parsecmd(inter);
12606 #if DEBUG
12607                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12608                         showtree(n);
12609 #endif
12610                 if (n == NODE_EOF) {
12611                         if (!top || numeof >= 50)
12612                                 break;
12613                         if (!stoppedjobs()) {
12614                                 if (!Iflag)
12615                                         break;
12616                                 out2str("\nUse \"exit\" to leave shell.\n");
12617                         }
12618                         numeof++;
12619                 } else if (nflag == 0) {
12620                         int i;
12621
12622                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12623                         job_warning >>= 1;
12624                         numeof = 0;
12625                         i = evaltree(n, 0);
12626                         if (n)
12627                                 status = i;
12628                 }
12629                 popstackmark(&smark);
12630                 skip = evalskip;
12631
12632                 if (skip) {
12633                         evalskip &= ~SKIPFUNC;
12634                         break;
12635                 }
12636         }
12637         return status;
12638 }
12639
12640 /*
12641  * Take commands from a file.  To be compatible we should do a path
12642  * search for the file, which is necessary to find sub-commands.
12643  */
12644 static char *
12645 find_dot_file(char *name)
12646 {
12647         char *fullname;
12648         const char *path = pathval();
12649         struct stat statb;
12650
12651         /* don't try this for absolute or relative paths */
12652         if (strchr(name, '/'))
12653                 return name;
12654
12655         while ((fullname = path_advance(&path, name)) != NULL) {
12656                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12657                         /*
12658                          * Don't bother freeing here, since it will
12659                          * be freed by the caller.
12660                          */
12661                         return fullname;
12662                 }
12663                 if (fullname != name)
12664                         stunalloc(fullname);
12665         }
12666
12667         /* not found in the PATH */
12668         ash_msg_and_raise_error("%s: not found", name);
12669         /* NOTREACHED */
12670 }
12671
12672 static int FAST_FUNC
12673 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12674 {
12675         /* "false; . empty_file; echo $?" should print 0, not 1: */
12676         int status = 0;
12677         char *fullname;
12678         char **argv;
12679         char *args_need_save;
12680         struct strlist *sp;
12681         volatile struct shparam saveparam;
12682
12683         for (sp = cmdenviron; sp; sp = sp->next)
12684                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12685
12686         nextopt(nullstr); /* handle possible "--" */
12687         argv = argptr;
12688
12689         if (!argv[0]) {
12690                 /* bash says: "bash: .: filename argument required" */
12691                 return 2; /* bash compat */
12692         }
12693
12694         /* This aborts if file isn't found, which is POSIXly correct.
12695          * bash returns exitcode 1 instead.
12696          */
12697         fullname = find_dot_file(argv[0]);
12698         argv++;
12699         args_need_save = argv[0];
12700         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12701                 int argc;
12702                 saveparam = shellparam;
12703                 shellparam.malloced = 0;
12704                 argc = 1;
12705                 while (argv[argc])
12706                         argc++;
12707                 shellparam.nparam = argc;
12708                 shellparam.p = argv;
12709         };
12710
12711         /* This aborts if file can't be opened, which is POSIXly correct.
12712          * bash returns exitcode 1 instead.
12713          */
12714         setinputfile(fullname, INPUT_PUSH_FILE);
12715         commandname = fullname;
12716         status = cmdloop(0);
12717         popfile();
12718
12719         if (args_need_save) {
12720                 freeparam(&shellparam);
12721                 shellparam = saveparam;
12722         };
12723
12724         return status;
12725 }
12726
12727 static int FAST_FUNC
12728 exitcmd(int argc UNUSED_PARAM, char **argv)
12729 {
12730         if (stoppedjobs())
12731                 return 0;
12732         if (argv[1])
12733                 exitstatus = number(argv[1]);
12734         raise_exception(EXEXIT);
12735         /* NOTREACHED */
12736 }
12737
12738 /*
12739  * Read a file containing shell functions.
12740  */
12741 static void
12742 readcmdfile(char *name)
12743 {
12744         setinputfile(name, INPUT_PUSH_FILE);
12745         cmdloop(0);
12746         popfile();
12747 }
12748
12749
12750 /* ============ find_command inplementation */
12751
12752 /*
12753  * Resolve a command name.  If you change this routine, you may have to
12754  * change the shellexec routine as well.
12755  */
12756 static void
12757 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12758 {
12759         struct tblentry *cmdp;
12760         int idx;
12761         int prev;
12762         char *fullname;
12763         struct stat statb;
12764         int e;
12765         int updatetbl;
12766         struct builtincmd *bcmd;
12767
12768         /* If name contains a slash, don't use PATH or hash table */
12769         if (strchr(name, '/') != NULL) {
12770                 entry->u.index = -1;
12771                 if (act & DO_ABS) {
12772                         while (stat(name, &statb) < 0) {
12773 #ifdef SYSV
12774                                 if (errno == EINTR)
12775                                         continue;
12776 #endif
12777                                 entry->cmdtype = CMDUNKNOWN;
12778                                 return;
12779                         }
12780                 }
12781                 entry->cmdtype = CMDNORMAL;
12782                 return;
12783         }
12784
12785 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12786
12787         updatetbl = (path == pathval());
12788         if (!updatetbl) {
12789                 act |= DO_ALTPATH;
12790                 if (strstr(path, "%builtin") != NULL)
12791                         act |= DO_ALTBLTIN;
12792         }
12793
12794         /* If name is in the table, check answer will be ok */
12795         cmdp = cmdlookup(name, 0);
12796         if (cmdp != NULL) {
12797                 int bit;
12798
12799                 switch (cmdp->cmdtype) {
12800                 default:
12801 #if DEBUG
12802                         abort();
12803 #endif
12804                 case CMDNORMAL:
12805                         bit = DO_ALTPATH;
12806                         break;
12807                 case CMDFUNCTION:
12808                         bit = DO_NOFUNC;
12809                         break;
12810                 case CMDBUILTIN:
12811                         bit = DO_ALTBLTIN;
12812                         break;
12813                 }
12814                 if (act & bit) {
12815                         updatetbl = 0;
12816                         cmdp = NULL;
12817                 } else if (cmdp->rehash == 0)
12818                         /* if not invalidated by cd, we're done */
12819                         goto success;
12820         }
12821
12822         /* If %builtin not in path, check for builtin next */
12823         bcmd = find_builtin(name);
12824         if (bcmd) {
12825                 if (IS_BUILTIN_REGULAR(bcmd))
12826                         goto builtin_success;
12827                 if (act & DO_ALTPATH) {
12828                         if (!(act & DO_ALTBLTIN))
12829                                 goto builtin_success;
12830                 } else if (builtinloc <= 0) {
12831                         goto builtin_success;
12832                 }
12833         }
12834
12835 #if ENABLE_FEATURE_SH_STANDALONE
12836         {
12837                 int applet_no = find_applet_by_name(name);
12838                 if (applet_no >= 0) {
12839                         entry->cmdtype = CMDNORMAL;
12840                         entry->u.index = -2 - applet_no;
12841                         return;
12842                 }
12843         }
12844 #endif
12845
12846         /* We have to search path. */
12847         prev = -1;              /* where to start */
12848         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12849                 if (cmdp->cmdtype == CMDBUILTIN)
12850                         prev = builtinloc;
12851                 else
12852                         prev = cmdp->param.index;
12853         }
12854
12855         e = ENOENT;
12856         idx = -1;
12857  loop:
12858         while ((fullname = path_advance(&path, name)) != NULL) {
12859                 stunalloc(fullname);
12860                 /* NB: code below will still use fullname
12861                  * despite it being "unallocated" */
12862                 idx++;
12863                 if (pathopt) {
12864                         if (prefix(pathopt, "builtin")) {
12865                                 if (bcmd)
12866                                         goto builtin_success;
12867                                 continue;
12868                         }
12869                         if ((act & DO_NOFUNC)
12870                          || !prefix(pathopt, "func")
12871                         ) {     /* ignore unimplemented options */
12872                                 continue;
12873                         }
12874                 }
12875                 /* if rehash, don't redo absolute path names */
12876                 if (fullname[0] == '/' && idx <= prev) {
12877                         if (idx < prev)
12878                                 continue;
12879                         TRACE(("searchexec \"%s\": no change\n", name));
12880                         goto success;
12881                 }
12882                 while (stat(fullname, &statb) < 0) {
12883 #ifdef SYSV
12884                         if (errno == EINTR)
12885                                 continue;
12886 #endif
12887                         if (errno != ENOENT && errno != ENOTDIR)
12888                                 e = errno;
12889                         goto loop;
12890                 }
12891                 e = EACCES;     /* if we fail, this will be the error */
12892                 if (!S_ISREG(statb.st_mode))
12893                         continue;
12894                 if (pathopt) {          /* this is a %func directory */
12895                         stalloc(strlen(fullname) + 1);
12896                         /* NB: stalloc will return space pointed by fullname
12897                          * (because we don't have any intervening allocations
12898                          * between stunalloc above and this stalloc) */
12899                         readcmdfile(fullname);
12900                         cmdp = cmdlookup(name, 0);
12901                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12902                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12903                         stunalloc(fullname);
12904                         goto success;
12905                 }
12906                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12907                 if (!updatetbl) {
12908                         entry->cmdtype = CMDNORMAL;
12909                         entry->u.index = idx;
12910                         return;
12911                 }
12912                 INT_OFF;
12913                 cmdp = cmdlookup(name, 1);
12914                 cmdp->cmdtype = CMDNORMAL;
12915                 cmdp->param.index = idx;
12916                 INT_ON;
12917                 goto success;
12918         }
12919
12920         /* We failed.  If there was an entry for this command, delete it */
12921         if (cmdp && updatetbl)
12922                 delete_cmd_entry();
12923         if (act & DO_ERR)
12924                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12925         entry->cmdtype = CMDUNKNOWN;
12926         return;
12927
12928  builtin_success:
12929         if (!updatetbl) {
12930                 entry->cmdtype = CMDBUILTIN;
12931                 entry->u.cmd = bcmd;
12932                 return;
12933         }
12934         INT_OFF;
12935         cmdp = cmdlookup(name, 1);
12936         cmdp->cmdtype = CMDBUILTIN;
12937         cmdp->param.cmd = bcmd;
12938         INT_ON;
12939  success:
12940         cmdp->rehash = 0;
12941         entry->cmdtype = cmdp->cmdtype;
12942         entry->u = cmdp->param;
12943 }
12944
12945
12946 /*
12947  * The trap builtin.
12948  */
12949 static int FAST_FUNC
12950 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12951 {
12952         char *action;
12953         char **ap;
12954         int signo, exitcode;
12955
12956         nextopt(nullstr);
12957         ap = argptr;
12958         if (!*ap) {
12959                 for (signo = 0; signo < NSIG; signo++) {
12960                         char *tr = trap_ptr[signo];
12961                         if (tr) {
12962                                 /* note: bash adds "SIG", but only if invoked
12963                                  * as "bash". If called as "sh", or if set -o posix,
12964                                  * then it prints short signal names.
12965                                  * We are printing short names: */
12966                                 out1fmt("trap -- %s %s\n",
12967                                                 single_quote(tr),
12968                                                 get_signame(signo));
12969                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12970                  * In this case, we will exit very soon, no need to free(). */
12971                                 /* if (trap_ptr != trap && tp[0]) */
12972                                 /*      free(tr); */
12973                         }
12974                 }
12975                 /*
12976                 if (trap_ptr != trap) {
12977                         free(trap_ptr);
12978                         trap_ptr = trap;
12979                 }
12980                 */
12981                 return 0;
12982         }
12983
12984         /* Why the second check?
12985          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
12986          * In this case, NUM is signal no, not an action.
12987          */
12988         action = NULL;
12989         if (ap[1] && !is_number(ap[0]))
12990                 action = *ap++;
12991
12992         exitcode = 0;
12993         while (*ap) {
12994                 signo = get_signum(*ap);
12995                 if (signo < 0) {
12996                         /* Mimic bash message exactly */
12997                         ash_msg("%s: invalid signal specification", *ap);
12998                         exitcode = 1;
12999                         goto next;
13000                 }
13001                 INT_OFF;
13002                 if (action) {
13003                         if (LONE_DASH(action))
13004                                 action = NULL;
13005                         else {
13006                                 if (action[0]) /* not NULL and not "" and not "-" */
13007                                         may_have_traps = 1;
13008                                 action = ckstrdup(action);
13009                         }
13010                 }
13011                 free(trap[signo]);
13012                 trap[signo] = action;
13013                 if (signo != 0)
13014                         setsignal(signo);
13015                 INT_ON;
13016  next:
13017                 ap++;
13018         }
13019         return exitcode;
13020 }
13021
13022
13023 /* ============ Builtins */
13024
13025 #if ENABLE_ASH_HELP
13026 static int FAST_FUNC
13027 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13028 {
13029         unsigned col;
13030         unsigned i;
13031
13032         out1fmt(
13033                 "Built-in commands:\n"
13034                 "------------------\n");
13035         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13036                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13037                                         builtintab[i].name + 1);
13038                 if (col > 60) {
13039                         out1fmt("\n");
13040                         col = 0;
13041                 }
13042         }
13043 # if ENABLE_FEATURE_SH_STANDALONE
13044         {
13045                 const char *a = applet_names;
13046                 while (*a) {
13047                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13048                         if (col > 60) {
13049                                 out1fmt("\n");
13050                                 col = 0;
13051                         }
13052                         while (*a++ != '\0')
13053                                 continue;
13054                 }
13055         }
13056 # endif
13057         newline_and_flush(stdout);
13058         return EXIT_SUCCESS;
13059 }
13060 #endif
13061
13062 #if MAX_HISTORY
13063 static int FAST_FUNC
13064 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13065 {
13066         show_history(line_input_state);
13067         return EXIT_SUCCESS;
13068 }
13069 #endif
13070
13071 /*
13072  * The export and readonly commands.
13073  */
13074 static int FAST_FUNC
13075 exportcmd(int argc UNUSED_PARAM, char **argv)
13076 {
13077         struct var *vp;
13078         char *name;
13079         const char *p;
13080         char **aptr;
13081         char opt;
13082         int flag;
13083         int flag_off;
13084
13085         /* "readonly" in bash accepts, but ignores -n.
13086          * We do the same: it saves a conditional in nextopt's param.
13087          */
13088         flag_off = 0;
13089         while ((opt = nextopt("np")) != '\0') {
13090                 if (opt == 'n')
13091                         flag_off = VEXPORT;
13092         }
13093         flag = VEXPORT;
13094         if (argv[0][0] == 'r') {
13095                 flag = VREADONLY;
13096                 flag_off = 0; /* readonly ignores -n */
13097         }
13098         flag_off = ~flag_off;
13099
13100         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13101         {
13102                 aptr = argptr;
13103                 name = *aptr;
13104                 if (name) {
13105                         do {
13106                                 p = strchr(name, '=');
13107                                 if (p != NULL) {
13108                                         p++;
13109                                 } else {
13110                                         vp = *findvar(hashvar(name), name);
13111                                         if (vp) {
13112                                                 vp->flags = ((vp->flags | flag) & flag_off);
13113                                                 continue;
13114                                         }
13115                                 }
13116                                 setvar(name, p, (flag & flag_off));
13117                         } while ((name = *++aptr) != NULL);
13118                         return 0;
13119                 }
13120         }
13121
13122         /* No arguments. Show the list of exported or readonly vars.
13123          * -n is ignored.
13124          */
13125         showvars(argv[0], flag, 0);
13126         return 0;
13127 }
13128
13129 /*
13130  * Delete a function if it exists.
13131  */
13132 static void
13133 unsetfunc(const char *name)
13134 {
13135         struct tblentry *cmdp;
13136
13137         cmdp = cmdlookup(name, 0);
13138         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13139                 delete_cmd_entry();
13140 }
13141
13142 /*
13143  * The unset builtin command.  We unset the function before we unset the
13144  * variable to allow a function to be unset when there is a readonly variable
13145  * with the same name.
13146  */
13147 static int FAST_FUNC
13148 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13149 {
13150         char **ap;
13151         int i;
13152         int flag = 0;
13153
13154         while ((i = nextopt("vf")) != 0) {
13155                 flag = i;
13156         }
13157
13158         for (ap = argptr; *ap; ap++) {
13159                 if (flag != 'f') {
13160                         unsetvar(*ap);
13161                         continue;
13162                 }
13163                 if (flag != 'v')
13164                         unsetfunc(*ap);
13165         }
13166         return 0;
13167 }
13168
13169 static const unsigned char timescmd_str[] ALIGN1 = {
13170         ' ',  offsetof(struct tms, tms_utime),
13171         '\n', offsetof(struct tms, tms_stime),
13172         ' ',  offsetof(struct tms, tms_cutime),
13173         '\n', offsetof(struct tms, tms_cstime),
13174         0
13175 };
13176 static int FAST_FUNC
13177 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13178 {
13179         unsigned long clk_tck, s, t;
13180         const unsigned char *p;
13181         struct tms buf;
13182
13183         clk_tck = bb_clk_tck();
13184         times(&buf);
13185
13186         p = timescmd_str;
13187         do {
13188                 t = *(clock_t *)(((char *) &buf) + p[1]);
13189                 s = t / clk_tck;
13190                 t = t % clk_tck;
13191                 out1fmt("%lum%lu.%03lus%c",
13192                         s / 60, s % 60,
13193                         (t * 1000) / clk_tck,
13194                         p[0]);
13195                 p += 2;
13196         } while (*p);
13197
13198         return 0;
13199 }
13200
13201 #if ENABLE_FEATURE_SH_MATH
13202 /*
13203  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13204  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13205  *
13206  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13207  */
13208 static int FAST_FUNC
13209 letcmd(int argc UNUSED_PARAM, char **argv)
13210 {
13211         arith_t i;
13212
13213         argv++;
13214         if (!*argv)
13215                 ash_msg_and_raise_error("expression expected");
13216         do {
13217                 i = ash_arith(*argv);
13218         } while (*++argv);
13219
13220         return !i;
13221 }
13222 #endif
13223
13224 /*
13225  * The read builtin. Options:
13226  *      -r              Do not interpret '\' specially
13227  *      -s              Turn off echo (tty only)
13228  *      -n NCHARS       Read NCHARS max
13229  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13230  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13231  *      -u FD           Read from given FD instead of fd 0
13232  * This uses unbuffered input, which may be avoidable in some cases.
13233  * TODO: bash also has:
13234  *      -a ARRAY        Read into array[0],[1],etc
13235  *      -d DELIM        End on DELIM char, not newline
13236  *      -e              Use line editing (tty only)
13237  */
13238 static int FAST_FUNC
13239 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13240 {
13241         char *opt_n = NULL;
13242         char *opt_p = NULL;
13243         char *opt_t = NULL;
13244         char *opt_u = NULL;
13245         int read_flags = 0;
13246         const char *r;
13247         int i;
13248
13249         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13250                 switch (i) {
13251                 case 'p':
13252                         opt_p = optionarg;
13253                         break;
13254                 case 'n':
13255                         opt_n = optionarg;
13256                         break;
13257                 case 's':
13258                         read_flags |= BUILTIN_READ_SILENT;
13259                         break;
13260                 case 't':
13261                         opt_t = optionarg;
13262                         break;
13263                 case 'r':
13264                         read_flags |= BUILTIN_READ_RAW;
13265                         break;
13266                 case 'u':
13267                         opt_u = optionarg;
13268                         break;
13269                 default:
13270                         break;
13271                 }
13272         }
13273
13274         /* "read -s" needs to save/restore termios, can't allow ^C
13275          * to jump out of it.
13276          */
13277  again:
13278         INT_OFF;
13279         r = shell_builtin_read(setvar0,
13280                 argptr,
13281                 bltinlookup("IFS"), /* can be NULL */
13282                 read_flags,
13283                 opt_n,
13284                 opt_p,
13285                 opt_t,
13286                 opt_u
13287         );
13288         INT_ON;
13289
13290         if ((uintptr_t)r == 1 && errno == EINTR) {
13291                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13292                 if (pending_sig == 0)
13293                         goto again;
13294         }
13295
13296         if ((uintptr_t)r > 1)
13297                 ash_msg_and_raise_error(r);
13298
13299         return (uintptr_t)r;
13300 }
13301
13302 static int FAST_FUNC
13303 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13304 {
13305         static const char permuser[3] ALIGN1 = "ogu";
13306
13307         mode_t mask;
13308         int symbolic_mode = 0;
13309
13310         while (nextopt("S") != '\0') {
13311                 symbolic_mode = 1;
13312         }
13313
13314         INT_OFF;
13315         mask = umask(0);
13316         umask(mask);
13317         INT_ON;
13318
13319         if (*argptr == NULL) {
13320                 if (symbolic_mode) {
13321                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13322                         char *p = buf;
13323                         int i;
13324
13325                         i = 2;
13326                         for (;;) {
13327                                 *p++ = ',';
13328                                 *p++ = permuser[i];
13329                                 *p++ = '=';
13330                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13331                                 if (!(mask & 0400)) *p++ = 'r';
13332                                 if (!(mask & 0200)) *p++ = 'w';
13333                                 if (!(mask & 0100)) *p++ = 'x';
13334                                 mask <<= 3;
13335                                 if (--i < 0)
13336                                         break;
13337                         }
13338                         *p = '\0';
13339                         puts(buf + 1);
13340                 } else {
13341                         out1fmt("%04o\n", mask);
13342                 }
13343         } else {
13344                 char *modestr = *argptr;
13345                 /* numeric umasks are taken as-is */
13346                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13347                 if (!isdigit(modestr[0]))
13348                         mask ^= 0777;
13349                 mask = bb_parse_mode(modestr, mask);
13350                 if ((unsigned)mask > 0777) {
13351                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13352                 }
13353                 if (!isdigit(modestr[0]))
13354                         mask ^= 0777;
13355                 umask(mask);
13356         }
13357         return 0;
13358 }
13359
13360 static int FAST_FUNC
13361 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13362 {
13363         return shell_builtin_ulimit(argv);
13364 }
13365
13366 /* ============ main() and helpers */
13367
13368 /*
13369  * Called to exit the shell.
13370  */
13371 static void
13372 exitshell(void)
13373 {
13374         struct jmploc loc;
13375         char *p;
13376         int status;
13377
13378 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13379         save_history(line_input_state);
13380 #endif
13381         status = exitstatus;
13382         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13383         if (setjmp(loc.loc)) {
13384                 if (exception_type == EXEXIT)
13385                         status = exitstatus;
13386                 goto out;
13387         }
13388         exception_handler = &loc;
13389         p = trap[0];
13390         if (p) {
13391                 trap[0] = NULL;
13392                 evalskip = 0;
13393                 evalstring(p, 0);
13394                 /*free(p); - we'll exit soon */
13395         }
13396  out:
13397         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13398          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13399          */
13400         setjobctl(0);
13401         flush_stdout_stderr();
13402         _exit(status);
13403         /* NOTREACHED */
13404 }
13405
13406 static void
13407 init(void)
13408 {
13409         /* we will never free this */
13410         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13411
13412         sigmode[SIGCHLD - 1] = S_DFL;
13413         setsignal(SIGCHLD);
13414
13415         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13416          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13417          */
13418         signal(SIGHUP, SIG_DFL);
13419
13420         {
13421                 char **envp;
13422                 const char *p;
13423                 struct stat st1, st2;
13424
13425                 initvar();
13426                 for (envp = environ; envp && *envp; envp++) {
13427                         p = endofname(*envp);
13428                         if (p != *envp && *p == '=') {
13429                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13430                         }
13431                 }
13432
13433                 setvareq((char*)defoptindvar, VTEXTFIXED);
13434
13435                 setvar0("PPID", utoa(getppid()));
13436 #if BASH_SHLVL_VAR
13437                 p = lookupvar("SHLVL");
13438                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13439 #endif
13440 #if BASH_HOSTNAME_VAR
13441                 if (!lookupvar("HOSTNAME")) {
13442                         struct utsname uts;
13443                         uname(&uts);
13444                         setvar0("HOSTNAME", uts.nodename);
13445                 }
13446 #endif
13447                 p = lookupvar("PWD");
13448                 if (p) {
13449                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13450                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13451                         ) {
13452                                 p = NULL;
13453                         }
13454                 }
13455                 setpwd(p, 0);
13456         }
13457 }
13458
13459
13460 //usage:#define ash_trivial_usage
13461 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13462 //usage:#define ash_full_usage "\n\n"
13463 //usage:        "Unix shell interpreter"
13464
13465 /*
13466  * Process the shell command line arguments.
13467  */
13468 static void
13469 procargs(char **argv)
13470 {
13471         int i;
13472         const char *xminusc;
13473         char **xargv;
13474
13475         xargv = argv;
13476         arg0 = xargv[0];
13477         /* if (xargv[0]) - mmm, this is always true! */
13478                 xargv++;
13479         for (i = 0; i < NOPTS; i++)
13480                 optlist[i] = 2;
13481         argptr = xargv;
13482         if (options(/*cmdline:*/ 1)) {
13483                 /* it already printed err message */
13484                 raise_exception(EXERROR);
13485         }
13486         xargv = argptr;
13487         xminusc = minusc;
13488         if (*xargv == NULL) {
13489                 if (xminusc)
13490                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13491                 sflag = 1;
13492         }
13493         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13494                 iflag = 1;
13495         if (mflag == 2)
13496                 mflag = iflag;
13497         for (i = 0; i < NOPTS; i++)
13498                 if (optlist[i] == 2)
13499                         optlist[i] = 0;
13500 #if DEBUG == 2
13501         debug = 1;
13502 #endif
13503         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13504         if (xminusc) {
13505                 minusc = *xargv++;
13506                 if (*xargv)
13507                         goto setarg0;
13508         } else if (!sflag) {
13509                 setinputfile(*xargv, 0);
13510  setarg0:
13511                 arg0 = *xargv++;
13512                 commandname = arg0;
13513         }
13514
13515         shellparam.p = xargv;
13516 #if ENABLE_ASH_GETOPTS
13517         shellparam.optind = 1;
13518         shellparam.optoff = -1;
13519 #endif
13520         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13521         while (*xargv) {
13522                 shellparam.nparam++;
13523                 xargv++;
13524         }
13525         optschanged();
13526 }
13527
13528 /*
13529  * Read /etc/profile, ~/.profile, $ENV.
13530  */
13531 static void
13532 read_profile(const char *name)
13533 {
13534         name = expandstr(name);
13535         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13536                 return;
13537         cmdloop(0);
13538         popfile();
13539 }
13540
13541 /*
13542  * This routine is called when an error or an interrupt occurs in an
13543  * interactive shell and control is returned to the main command loop.
13544  * (In dash, this function is auto-generated by build machinery).
13545  */
13546 static void
13547 reset(void)
13548 {
13549         /* from eval.c: */
13550         evalskip = 0;
13551         loopnest = 0;
13552
13553         /* from expand.c: */
13554         ifsfree();
13555
13556         /* from input.c: */
13557         g_parsefile->left_in_buffer = 0;
13558         g_parsefile->left_in_line = 0;      /* clear input buffer */
13559         popallfiles();
13560
13561         /* from redir.c: */
13562         while (redirlist)
13563                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13564 }
13565
13566 #if PROFILE
13567 static short profile_buf[16384];
13568 extern int etext();
13569 #endif
13570
13571 /*
13572  * Main routine.  We initialize things, parse the arguments, execute
13573  * profiles if we're a login shell, and then call cmdloop to execute
13574  * commands.  The setjmp call sets up the location to jump to when an
13575  * exception occurs.  When an exception occurs the variable "state"
13576  * is used to figure out how far we had gotten.
13577  */
13578 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13579 int ash_main(int argc UNUSED_PARAM, char **argv)
13580 {
13581         volatile smallint state;
13582         struct jmploc jmploc;
13583         struct stackmark smark;
13584
13585         /* Initialize global data */
13586         INIT_G_misc();
13587         INIT_G_memstack();
13588         INIT_G_var();
13589 #if ENABLE_ASH_ALIAS
13590         INIT_G_alias();
13591 #endif
13592         INIT_G_cmdtable();
13593
13594 #if PROFILE
13595         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13596 #endif
13597
13598 #if ENABLE_FEATURE_EDITING
13599         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13600 #endif
13601         state = 0;
13602         if (setjmp(jmploc.loc)) {
13603                 smallint e;
13604                 smallint s;
13605
13606                 reset();
13607
13608                 e = exception_type;
13609                 s = state;
13610                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13611                         exitshell();
13612                 }
13613                 if (e == EXINT) {
13614                         newline_and_flush(stderr);
13615                 }
13616
13617                 popstackmark(&smark);
13618                 FORCE_INT_ON; /* enable interrupts */
13619                 if (s == 1)
13620                         goto state1;
13621                 if (s == 2)
13622                         goto state2;
13623                 if (s == 3)
13624                         goto state3;
13625                 goto state4;
13626         }
13627         exception_handler = &jmploc;
13628         rootpid = getpid();
13629
13630         init();
13631         setstackmark(&smark);
13632         procargs(argv);
13633 #if DEBUG
13634         TRACE(("Shell args: "));
13635         trace_puts_args(argv);
13636 #endif
13637
13638         if (argv[0] && argv[0][0] == '-')
13639                 isloginsh = 1;
13640         if (isloginsh) {
13641                 const char *hp;
13642
13643                 state = 1;
13644                 read_profile("/etc/profile");
13645  state1:
13646                 state = 2;
13647                 hp = lookupvar("HOME");
13648                 if (hp)
13649                         read_profile("$HOME/.profile");
13650         }
13651  state2:
13652         state = 3;
13653         if (
13654 #ifndef linux
13655          getuid() == geteuid() && getgid() == getegid() &&
13656 #endif
13657          iflag
13658         ) {
13659                 const char *shinit = lookupvar("ENV");
13660                 if (shinit != NULL && *shinit != '\0')
13661                         read_profile(shinit);
13662         }
13663         popstackmark(&smark);
13664  state3:
13665         state = 4;
13666         if (minusc) {
13667                 /* evalstring pushes parsefile stack.
13668                  * Ensure we don't falsely claim that 0 (stdin)
13669                  * is one of stacked source fds.
13670                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13671                 // if (!sflag) g_parsefile->pf_fd = -1;
13672                 // ^^ not necessary since now we special-case fd 0
13673                 // in is_hidden_fd() to not be considered "hidden fd"
13674                 evalstring(minusc, 0);
13675         }
13676
13677         if (sflag || minusc == NULL) {
13678 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13679                 if (iflag) {
13680                         const char *hp = lookupvar("HISTFILE");
13681                         if (!hp) {
13682                                 hp = lookupvar("HOME");
13683                                 if (hp) {
13684                                         INT_OFF;
13685                                         hp = concat_path_file(hp, ".ash_history");
13686                                         setvar0("HISTFILE", hp);
13687                                         free((char*)hp);
13688                                         INT_ON;
13689                                         hp = lookupvar("HISTFILE");
13690                                 }
13691                         }
13692                         if (hp)
13693                                 line_input_state->hist_file = hp;
13694 # if ENABLE_FEATURE_SH_HISTFILESIZE
13695                         hp = lookupvar("HISTFILESIZE");
13696                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13697 # endif
13698                 }
13699 #endif
13700  state4: /* XXX ??? - why isn't this before the "if" statement */
13701                 cmdloop(1);
13702         }
13703 #if PROFILE
13704         monitor(0);
13705 #endif
13706 #ifdef GPROF
13707         {
13708                 extern void _mcleanup(void);
13709                 _mcleanup();
13710         }
13711 #endif
13712         TRACE(("End of main reached\n"));
13713         exitshell();
13714         /* NOTREACHED */
13715 }
13716
13717
13718 /*-
13719  * Copyright (c) 1989, 1991, 1993, 1994
13720  *      The Regents of the University of California.  All rights reserved.
13721  *
13722  * This code is derived from software contributed to Berkeley by
13723  * Kenneth Almquist.
13724  *
13725  * Redistribution and use in source and binary forms, with or without
13726  * modification, are permitted provided that the following conditions
13727  * are met:
13728  * 1. Redistributions of source code must retain the above copyright
13729  *    notice, this list of conditions and the following disclaimer.
13730  * 2. Redistributions in binary form must reproduce the above copyright
13731  *    notice, this list of conditions and the following disclaimer in the
13732  *    documentation and/or other materials provided with the distribution.
13733  * 3. Neither the name of the University nor the names of its contributors
13734  *    may be used to endorse or promote products derived from this software
13735  *    without specific prior written permission.
13736  *
13737  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13738  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13739  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13740  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13741  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13742  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13743  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13744  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13745  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13746  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13747  * SUCH DAMAGE.
13748  */