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