hush: fix dup_CLOEXEC() call without "avoid_fd" parameter
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_BASH_SOURCE_CURDIR
55 //config:       bool "'source' and '.' builtins search current directory after $PATH"
56 //config:       default n   # do not encourage non-standard behavior
57 //config:       depends on ASH_BASH_COMPAT
58 //config:       help
59 //config:       This is not compliant with standards. Avoid if possible.
60 //config:
61 //config:config ASH_BASH_NOT_FOUND_HOOK
62 //config:       bool "command_not_found_handle hook support"
63 //config:       default y
64 //config:       depends on ASH_BASH_COMPAT
65 //config:       help
66 //config:       Enable support for the 'command_not_found_handle' hook function,
67 //config:       from GNU bash, which allows for alternative command not found
68 //config:       handling.
69 //config:
70 //config:config ASH_JOB_CONTROL
71 //config:       bool "Job control"
72 //config:       default y
73 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
74 //config:
75 //config:config ASH_ALIAS
76 //config:       bool "Alias support"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:
80 //config:config ASH_RANDOM_SUPPORT
81 //config:       bool "Pseudorandom generator and $RANDOM variable"
82 //config:       default y
83 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
84 //config:       help
85 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
86 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
87 //config:       You can reset the generator by using a specified start value.
88 //config:       After "unset RANDOM" the generator will switch off and this
89 //config:       variable will no longer have special treatment.
90 //config:
91 //config:config ASH_EXPAND_PRMT
92 //config:       bool "Expand prompt string"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       $PS# may contain volatile content, such as backquote commands.
97 //config:       This option recreates the prompt string from the environment
98 //config:       variable each time it is displayed.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable $TMOUT"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_MAIL
108 //config:       bool "Check for new mail in interactive shell"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:       help
112 //config:       Enable "check for new mail" function:
113 //config:       if set, $MAIL file and $MAILPATH list of files
114 //config:       are checked for mtime changes, and "you have mail"
115 //config:       message is printed if change is detected.
116 //config:
117 //config:config ASH_ECHO
118 //config:       bool "echo builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_PRINTF
123 //config:       bool "printf builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_TEST
128 //config:       bool "test builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:
132 //config:config ASH_HELP
133 //config:       bool "help builtin"
134 //config:       default y
135 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
136 //config:
137 //config:config ASH_GETOPTS
138 //config:       bool "getopts builtin"
139 //config:       default y
140 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
141 //config:
142 //config:config ASH_CMDCMD
143 //config:       bool "command builtin"
144 //config:       default y
145 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
146 //config:       help
147 //config:       Enable support for the 'command' builtin, which allows
148 //config:       you to run the specified command or builtin,
149 //config:       even when there is a function with the same name.
150 //config:
151 //config:endif # ash options
152
153 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
154 //                      APPLET_ODDNAME:name  main location    suid_type     help
155 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
156 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
157
158 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
159 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
160 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
161 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
162
163 /*
164  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
165  * DEBUG=2 to compile in and turn on debugging.
166  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
167  * debugging info is written to ./trace, quit signal generates core dump.
168  */
169 #define DEBUG 0
170 /* Tweak debug output verbosity here */
171 #define DEBUG_TIME 0
172 #define DEBUG_PID 1
173 #define DEBUG_SIG 1
174 #define DEBUG_INTONOFF 0
175
176 #define PROFILE 0
177
178 #define JOBS ENABLE_ASH_JOB_CONTROL
179
180 #include <fnmatch.h>
181 #include <sys/times.h>
182 #include <sys/utsname.h> /* for setting $HOSTNAME */
183 #include "busybox.h" /* for applet_names */
184
185 /* So far, all bash compat is controlled by one config option */
186 /* Separate defines document which part of code implements what */
187 /* function keyword */
188 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
189 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
190 /* &>file */
191 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
192 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
193 /* $'...' */
194 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
195 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
196 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
198 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
199 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
200 /* BASH_TEST2: [[ EXPR ]]
201  * Status of [[ support:
202  * We replace && and || with -a and -o
203  * TODO:
204  * singleword+noglob expansion:
205  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
206  *   [[ /bin/n* ]]; echo 0:$?
207  * -a/-o are not AND/OR ops! (they are just strings)
208  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
209  * = is glob match operator, not equality operator: STR = GLOB
210  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
211  * == same as =
212  * add =~ regex match operator: STR =~ REGEX
213  */
214 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
215 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
216 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
217 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
218 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
219 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
220 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
221 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
222
223 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
224 /* Bionic at least up to version 24 has no glob() */
225 # undef  ENABLE_ASH_INTERNAL_GLOB
226 # define ENABLE_ASH_INTERNAL_GLOB 1
227 #endif
228
229 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
230 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
231 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
232 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
233 # error glob() should unbackslash them and match. uClibc does not unbackslash,
234 # error fails to match dirname, subsequently not expanding <pattern> in it.
235 // Testcase:
236 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
237 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
238 #endif
239
240 #if !ENABLE_ASH_INTERNAL_GLOB
241 # include <glob.h>
242 #endif
243
244 #include "unicode.h"
245 #include "shell_common.h"
246 #if ENABLE_FEATURE_SH_MATH
247 # include "math.h"
248 #else
249 typedef long arith_t;
250 # define ARITH_FMT "%ld"
251 #endif
252 #if ENABLE_ASH_RANDOM_SUPPORT
253 # include "random.h"
254 #else
255 # define CLEAR_RANDOM_T(rnd) ((void)0)
256 #endif
257
258 #include "NUM_APPLETS.h"
259 #if NUM_APPLETS == 1
260 /* STANDALONE does not make sense, and won't compile */
261 # undef CONFIG_FEATURE_SH_STANDALONE
262 # undef ENABLE_FEATURE_SH_STANDALONE
263 # undef IF_FEATURE_SH_STANDALONE
264 # undef IF_NOT_FEATURE_SH_STANDALONE
265 # define ENABLE_FEATURE_SH_STANDALONE 0
266 # define IF_FEATURE_SH_STANDALONE(...)
267 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
268 #endif
269
270 #ifndef F_DUPFD_CLOEXEC
271 # define F_DUPFD_CLOEXEC F_DUPFD
272 #endif
273 #ifndef O_CLOEXEC
274 # define O_CLOEXEC 0
275 #endif
276 #ifndef PIPE_BUF
277 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
278 #endif
279
280 #if !BB_MMU
281 # error "Do not even bother, ash will not run on NOMMU machine"
282 #endif
283
284 /* We use a trick to have more optimized code (fewer pointer reloads):
285  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
286  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
287  * This way, compiler in ash.c knows the pointer can not change.
288  *
289  * However, this may break on weird arches or toolchains. In this case,
290  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
291  * this optimization.
292  */
293 #ifndef BB_GLOBAL_CONST
294 # define BB_GLOBAL_CONST const
295 #endif
296
297
298 /* ============ Hash table sizes. Configurable. */
299
300 #define VTABSIZE 39
301 #define ATABSIZE 39
302 #define CMDTABLESIZE 31         /* should be prime */
303
304
305 /* ============ Shell options */
306
307 static const char *const optletters_optnames[] = {
308         "e"   "errexit",
309         "f"   "noglob",
310         "I"   "ignoreeof",
311         "i"   "interactive",
312         "m"   "monitor",
313         "n"   "noexec",
314         "s"   "stdin",
315         "x"   "xtrace",
316         "v"   "verbose",
317         "C"   "noclobber",
318         "a"   "allexport",
319         "b"   "notify",
320         "u"   "nounset",
321         "\0"  "vi"
322 #if BASH_PIPEFAIL
323         ,"\0"  "pipefail"
324 #endif
325 #if DEBUG
326         ,"\0"  "nolog"
327         ,"\0"  "debug"
328 #endif
329 };
330
331 #define optletters(n)  optletters_optnames[n][0]
332 #define optnames(n)   (optletters_optnames[n] + 1)
333
334 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
335
336
337 /* ============ Misc data */
338
339 #define msg_illnum "Illegal number: %s"
340
341 /*
342  * We enclose jmp_buf in a structure so that we can declare pointers to
343  * jump locations.  The global variable handler contains the location to
344  * jump to when an exception occurs, and the global variable exception_type
345  * contains a code identifying the exception.  To implement nested
346  * exception handlers, the user should save the value of handler on entry
347  * to an inner scope, set handler to point to a jmploc structure for the
348  * inner scope, and restore handler on exit from the scope.
349  */
350 struct jmploc {
351         jmp_buf loc;
352 };
353
354 struct globals_misc {
355         uint8_t exitstatus;     /* exit status of last command */
356         uint8_t back_exitstatus;/* exit status of backquoted command */
357         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
358         int rootpid;            /* pid of main shell */
359         /* shell level: 0 for the main shell, 1 for its children, and so on */
360         int shlvl;
361 #define rootshell (!shlvl)
362         int errlinno;
363
364         char *minusc;  /* argument to -c option */
365
366         char *curdir; // = nullstr;     /* current working directory */
367         char *physdir; // = nullstr;    /* physical working directory */
368
369         char *arg0; /* value of $0 */
370
371         struct jmploc *exception_handler;
372
373         volatile int suppress_int; /* counter */
374         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
375         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
376         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
377         smallint exception_type; /* kind of exception (0..5) */
378         /* exceptions */
379 #define EXINT 0         /* SIGINT received */
380 #define EXERROR 1       /* a generic error */
381 #define EXEXIT 4        /* exit the shell */
382
383         char nullstr[1];        /* zero length string */
384
385         char optlist[NOPTS];
386 #define eflag optlist[0]
387 #define fflag optlist[1]
388 #define Iflag optlist[2]
389 #define iflag optlist[3]
390 #define mflag optlist[4]
391 #define nflag optlist[5]
392 #define sflag optlist[6]
393 #define xflag optlist[7]
394 #define vflag optlist[8]
395 #define Cflag optlist[9]
396 #define aflag optlist[10]
397 #define bflag optlist[11]
398 #define uflag optlist[12]
399 #define viflag optlist[13]
400 #if BASH_PIPEFAIL
401 # define pipefail optlist[14]
402 #else
403 # define pipefail 0
404 #endif
405 #if DEBUG
406 # define nolog optlist[14 + BASH_PIPEFAIL]
407 # define debug optlist[15 + BASH_PIPEFAIL]
408 #endif
409
410         /* trap handler commands */
411         /*
412          * Sigmode records the current value of the signal handlers for the various
413          * modes.  A value of zero means that the current handler is not known.
414          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
415          */
416         char sigmode[NSIG - 1];
417 #define S_DFL      1            /* default signal handling (SIG_DFL) */
418 #define S_CATCH    2            /* signal is caught */
419 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
420 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
421
422         /* indicates specified signal received */
423         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
424         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
425         char *trap[NSIG];
426         char **trap_ptr;        /* used only by "trap hack" */
427
428         /* Rarely referenced stuff */
429 #if ENABLE_ASH_RANDOM_SUPPORT
430         random_t random_gen;
431 #endif
432         pid_t backgndpid;        /* pid of last background process */
433 };
434 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
435 #define G_misc (*ash_ptr_to_globals_misc)
436 #define exitstatus        (G_misc.exitstatus )
437 #define back_exitstatus   (G_misc.back_exitstatus )
438 #define job_warning       (G_misc.job_warning)
439 #define rootpid     (G_misc.rootpid    )
440 #define shlvl       (G_misc.shlvl      )
441 #define errlinno    (G_misc.errlinno   )
442 #define minusc      (G_misc.minusc     )
443 #define curdir      (G_misc.curdir     )
444 #define physdir     (G_misc.physdir    )
445 #define arg0        (G_misc.arg0       )
446 #define exception_handler (G_misc.exception_handler)
447 #define exception_type    (G_misc.exception_type   )
448 #define suppress_int      (G_misc.suppress_int     )
449 #define pending_int       (G_misc.pending_int      )
450 #define got_sigchld       (G_misc.got_sigchld      )
451 #define pending_sig       (G_misc.pending_sig      )
452 #define nullstr     (G_misc.nullstr    )
453 #define optlist     (G_misc.optlist    )
454 #define sigmode     (G_misc.sigmode    )
455 #define gotsig      (G_misc.gotsig     )
456 #define may_have_traps    (G_misc.may_have_traps   )
457 #define trap        (G_misc.trap       )
458 #define trap_ptr    (G_misc.trap_ptr   )
459 #define random_gen  (G_misc.random_gen )
460 #define backgndpid  (G_misc.backgndpid )
461 #define INIT_G_misc() do { \
462         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
463         barrier(); \
464         curdir = nullstr; \
465         physdir = nullstr; \
466         trap_ptr = trap; \
467 } while (0)
468
469
470 /* ============ DEBUG */
471 #if DEBUG
472 static void trace_printf(const char *fmt, ...);
473 static void trace_vprintf(const char *fmt, va_list va);
474 # define TRACE(param)    trace_printf param
475 # define TRACEV(param)   trace_vprintf param
476 # define close(fd) do { \
477         int dfd = (fd); \
478         if (close(dfd) < 0) \
479                 bb_error_msg("bug on %d: closing %d(0x%x)", \
480                         __LINE__, dfd, dfd); \
481 } while (0)
482 #else
483 # define TRACE(param)
484 # define TRACEV(param)
485 #endif
486
487
488 /* ============ Utility functions */
489 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
490 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
491
492 static int
493 isdigit_str9(const char *str)
494 {
495         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
496         while (--maxlen && isdigit(*str))
497                 str++;
498         return (*str == '\0');
499 }
500
501 static const char *
502 var_end(const char *var)
503 {
504         while (*var)
505                 if (*var++ == '=')
506                         break;
507         return var;
508 }
509
510
511 /* ============ Interrupts / exceptions */
512
513 static void exitshell(void) NORETURN;
514
515 /*
516  * These macros allow the user to suspend the handling of interrupt signals
517  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
518  * much more efficient and portable.  (But hacking the kernel is so much
519  * more fun than worrying about efficiency and portability. :-))
520  */
521 #if DEBUG_INTONOFF
522 # define INT_OFF do { \
523         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
524         suppress_int++; \
525         barrier(); \
526 } while (0)
527 #else
528 # define INT_OFF do { \
529         suppress_int++; \
530         barrier(); \
531 } while (0)
532 #endif
533
534 /*
535  * Called to raise an exception.  Since C doesn't include exceptions, we
536  * just do a longjmp to the exception handler.  The type of exception is
537  * stored in the global variable "exception_type".
538  */
539 static void raise_exception(int) NORETURN;
540 static void
541 raise_exception(int e)
542 {
543 #if DEBUG
544         if (exception_handler == NULL)
545                 abort();
546 #endif
547         INT_OFF;
548         exception_type = e;
549         longjmp(exception_handler->loc, 1);
550 }
551 #if DEBUG
552 #define raise_exception(e) do { \
553         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
554         raise_exception(e); \
555 } while (0)
556 #endif
557
558 /*
559  * Called when a SIGINT is received.  (If the user specifies
560  * that SIGINT is to be trapped or ignored using the trap builtin, then
561  * this routine is not called.)  Suppressint is nonzero when interrupts
562  * are held using the INT_OFF macro.  (The test for iflag is just
563  * defensive programming.)
564  */
565 static void raise_interrupt(void) NORETURN;
566 static void
567 raise_interrupt(void)
568 {
569         pending_int = 0;
570         /* Signal is not automatically unmasked after it is raised,
571          * do it ourself - unmask all signals */
572         sigprocmask_allsigs(SIG_UNBLOCK);
573         /* pending_sig = 0; - now done in signal_handler() */
574
575         if (!(rootshell && iflag)) {
576                 /* Kill ourself with SIGINT */
577                 signal(SIGINT, SIG_DFL);
578                 raise(SIGINT);
579         }
580         /* bash: ^C even on empty command line sets $? */
581         exitstatus = SIGINT + 128;
582         raise_exception(EXINT);
583         /* NOTREACHED */
584 }
585 #if DEBUG
586 #define raise_interrupt() do { \
587         TRACE(("raising interrupt on line %d\n", __LINE__)); \
588         raise_interrupt(); \
589 } while (0)
590 #endif
591
592 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
593 int_on(void)
594 {
595         barrier();
596         if (--suppress_int == 0 && pending_int) {
597                 raise_interrupt();
598         }
599 }
600 #if DEBUG_INTONOFF
601 # define INT_ON do { \
602         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
603         int_on(); \
604 } while (0)
605 #else
606 # define INT_ON int_on()
607 #endif
608 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
609 force_int_on(void)
610 {
611         barrier();
612         suppress_int = 0;
613         if (pending_int)
614                 raise_interrupt();
615 }
616 #define FORCE_INT_ON force_int_on()
617
618 #define SAVE_INT(v) ((v) = suppress_int)
619
620 #define RESTORE_INT(v) do { \
621         barrier(); \
622         suppress_int = (v); \
623         if (suppress_int == 0 && pending_int) \
624                 raise_interrupt(); \
625 } while (0)
626
627
628 /* ============ Stdout/stderr output */
629
630 static void
631 outstr(const char *p, FILE *file)
632 {
633         INT_OFF;
634         fputs(p, file);
635         INT_ON;
636 }
637
638 static void
639 flush_stdout_stderr(void)
640 {
641         INT_OFF;
642         fflush_all();
643         INT_ON;
644 }
645
646 /* Was called outcslow(c,FILE*), but c was always '\n' */
647 static void
648 newline_and_flush(FILE *dest)
649 {
650         INT_OFF;
651         putc('\n', dest);
652         fflush(dest);
653         INT_ON;
654 }
655
656 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
657 static int
658 out1fmt(const char *fmt, ...)
659 {
660         va_list ap;
661         int r;
662
663         INT_OFF;
664         va_start(ap, fmt);
665         r = vprintf(fmt, ap);
666         va_end(ap);
667         INT_ON;
668         return r;
669 }
670
671 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
672 static int
673 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
674 {
675         va_list ap;
676         int ret;
677
678         INT_OFF;
679         va_start(ap, fmt);
680         ret = vsnprintf(outbuf, length, fmt, ap);
681         va_end(ap);
682         INT_ON;
683         return ret;
684 }
685
686 static void
687 out1str(const char *p)
688 {
689         outstr(p, stdout);
690 }
691
692 static void
693 out2str(const char *p)
694 {
695         outstr(p, stderr);
696         flush_stdout_stderr();
697 }
698
699
700 /* ============ Parser structures */
701
702 /* control characters in argument strings */
703 #define CTL_FIRST CTLESC
704 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
705 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
706 #define CTLENDVAR    ((unsigned char)'\203')
707 #define CTLBACKQ     ((unsigned char)'\204')
708 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
709 #define CTLENDARI    ((unsigned char)'\207')
710 #define CTLQUOTEMARK ((unsigned char)'\210')
711 #define CTL_LAST CTLQUOTEMARK
712
713 /* variable substitution byte (follows CTLVAR) */
714 #define VSTYPE  0x0f            /* type of variable substitution */
715 #define VSNUL   0x10            /* colon--treat the empty string as unset */
716
717 /* values of VSTYPE field */
718 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
719 #define VSMINUS         0x2     /* ${var-text} */
720 #define VSPLUS          0x3     /* ${var+text} */
721 #define VSQUESTION      0x4     /* ${var?message} */
722 #define VSASSIGN        0x5     /* ${var=text} */
723 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
724 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
725 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
726 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
727 #define VSLENGTH        0xa     /* ${#var} */
728 #if BASH_SUBSTR
729 #define VSSUBSTR        0xc     /* ${var:position:length} */
730 #endif
731 #if BASH_PATTERN_SUBST
732 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
733 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
734 #endif
735
736 static const char dolatstr[] ALIGN1 = {
737         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
738 };
739 #define DOLATSTRLEN 6
740
741 #define NCMD      0
742 #define NPIPE     1
743 #define NREDIR    2
744 #define NBACKGND  3
745 #define NSUBSHELL 4
746 #define NAND      5
747 #define NOR       6
748 #define NSEMI     7
749 #define NIF       8
750 #define NWHILE    9
751 #define NUNTIL   10
752 #define NFOR     11
753 #define NCASE    12
754 #define NCLIST   13
755 #define NDEFUN   14
756 #define NARG     15
757 #define NTO      16
758 #if BASH_REDIR_OUTPUT
759 #define NTO2     17
760 #endif
761 #define NCLOBBER 18
762 #define NFROM    19
763 #define NFROMTO  20
764 #define NAPPEND  21
765 #define NTOFD    22
766 #define NFROMFD  23
767 #define NHERE    24
768 #define NXHERE   25
769 #define NNOT     26
770 #define N_NUMBER 27
771
772 union node;
773
774 struct ncmd {
775         smallint type; /* Nxxxx */
776         int linno;
777         union node *assign;
778         union node *args;
779         union node *redirect;
780 };
781
782 struct npipe {
783         smallint type;
784         smallint pipe_backgnd;
785         struct nodelist *cmdlist;
786 };
787
788 struct nredir {
789         smallint type;
790         int linno;
791         union node *n;
792         union node *redirect;
793 };
794
795 struct nbinary {
796         smallint type;
797         union node *ch1;
798         union node *ch2;
799 };
800
801 struct nif {
802         smallint type;
803         union node *test;
804         union node *ifpart;
805         union node *elsepart;
806 };
807
808 struct nfor {
809         smallint type;
810         int linno;
811         union node *args;
812         union node *body;
813         char *var;
814 };
815
816 struct ncase {
817         smallint type;
818         int linno;
819         union node *expr;
820         union node *cases;
821 };
822
823 struct nclist {
824         smallint type;
825         union node *next;
826         union node *pattern;
827         union node *body;
828 };
829
830 struct ndefun {
831         smallint type;
832         int linno;
833         char *text;
834         union node *body;
835 };
836
837 struct narg {
838         smallint type;
839         union node *next;
840         char *text;
841         struct nodelist *backquote;
842 };
843
844 /* nfile and ndup layout must match!
845  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
846  * that it is actually NTO2 (>&file), and change its type.
847  */
848 struct nfile {
849         smallint type;
850         union node *next;
851         int fd;
852         int _unused_dupfd;
853         union node *fname;
854         char *expfname;
855 };
856
857 struct ndup {
858         smallint type;
859         union node *next;
860         int fd;
861         int dupfd;
862         union node *vname;
863         char *_unused_expfname;
864 };
865
866 struct nhere {
867         smallint type;
868         union node *next;
869         int fd;
870         union node *doc;
871 };
872
873 struct nnot {
874         smallint type;
875         union node *com;
876 };
877
878 union node {
879         smallint type;
880         struct ncmd ncmd;
881         struct npipe npipe;
882         struct nredir nredir;
883         struct nbinary nbinary;
884         struct nif nif;
885         struct nfor nfor;
886         struct ncase ncase;
887         struct nclist nclist;
888         struct ndefun ndefun;
889         struct narg narg;
890         struct nfile nfile;
891         struct ndup ndup;
892         struct nhere nhere;
893         struct nnot nnot;
894 };
895
896 /*
897  * NODE_EOF is returned by parsecmd when it encounters an end of file.
898  * It must be distinct from NULL.
899  */
900 #define NODE_EOF ((union node *) -1L)
901
902 struct nodelist {
903         struct nodelist *next;
904         union node *n;
905 };
906
907 struct funcnode {
908         int count;
909         union node n;
910 };
911
912 /*
913  * Free a parse tree.
914  */
915 static void
916 freefunc(struct funcnode *f)
917 {
918         if (f && --f->count < 0)
919                 free(f);
920 }
921
922
923 /* ============ Debugging output */
924
925 #if DEBUG
926
927 static FILE *tracefile;
928
929 static void
930 trace_printf(const char *fmt, ...)
931 {
932         va_list va;
933
934         if (debug != 1)
935                 return;
936         if (DEBUG_TIME)
937                 fprintf(tracefile, "%u ", (int) time(NULL));
938         if (DEBUG_PID)
939                 fprintf(tracefile, "[%u] ", (int) getpid());
940         if (DEBUG_SIG)
941                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
942         va_start(va, fmt);
943         vfprintf(tracefile, fmt, va);
944         va_end(va);
945 }
946
947 static void
948 trace_vprintf(const char *fmt, va_list va)
949 {
950         if (debug != 1)
951                 return;
952         vfprintf(tracefile, fmt, va);
953         fprintf(tracefile, "\n");
954 }
955
956 static void
957 trace_puts(const char *s)
958 {
959         if (debug != 1)
960                 return;
961         fputs(s, tracefile);
962 }
963
964 static void
965 trace_puts_quoted(char *s)
966 {
967         char *p;
968         char c;
969
970         if (debug != 1)
971                 return;
972         putc('"', tracefile);
973         for (p = s; *p; p++) {
974                 switch ((unsigned char)*p) {
975                 case '\n': c = 'n'; goto backslash;
976                 case '\t': c = 't'; goto backslash;
977                 case '\r': c = 'r'; goto backslash;
978                 case '\"': c = '\"'; goto backslash;
979                 case '\\': c = '\\'; goto backslash;
980                 case CTLESC: c = 'e'; goto backslash;
981                 case CTLVAR: c = 'v'; goto backslash;
982                 case CTLBACKQ: c = 'q'; goto backslash;
983  backslash:
984                         putc('\\', tracefile);
985                         putc(c, tracefile);
986                         break;
987                 default:
988                         if (*p >= ' ' && *p <= '~')
989                                 putc(*p, tracefile);
990                         else {
991                                 putc('\\', tracefile);
992                                 putc((*p >> 6) & 03, tracefile);
993                                 putc((*p >> 3) & 07, tracefile);
994                                 putc(*p & 07, tracefile);
995                         }
996                         break;
997                 }
998         }
999         putc('"', tracefile);
1000 }
1001
1002 static void
1003 trace_puts_args(char **ap)
1004 {
1005         if (debug != 1)
1006                 return;
1007         if (!*ap)
1008                 return;
1009         while (1) {
1010                 trace_puts_quoted(*ap);
1011                 if (!*++ap) {
1012                         putc('\n', tracefile);
1013                         break;
1014                 }
1015                 putc(' ', tracefile);
1016         }
1017 }
1018
1019 static void
1020 opentrace(void)
1021 {
1022         char s[100];
1023 #ifdef O_APPEND
1024         int flags;
1025 #endif
1026
1027         if (debug != 1) {
1028                 if (tracefile)
1029                         fflush(tracefile);
1030                 /* leave open because libedit might be using it */
1031                 return;
1032         }
1033         strcpy(s, "./trace");
1034         if (tracefile) {
1035                 if (!freopen(s, "a", tracefile)) {
1036                         fprintf(stderr, "Can't re-open %s\n", s);
1037                         debug = 0;
1038                         return;
1039                 }
1040         } else {
1041                 tracefile = fopen(s, "a");
1042                 if (tracefile == NULL) {
1043                         fprintf(stderr, "Can't open %s\n", s);
1044                         debug = 0;
1045                         return;
1046                 }
1047         }
1048 #ifdef O_APPEND
1049         flags = fcntl(fileno(tracefile), F_GETFL);
1050         if (flags >= 0)
1051                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1052 #endif
1053         setlinebuf(tracefile);
1054         fputs("\nTracing started.\n", tracefile);
1055 }
1056
1057 static void
1058 indent(int amount, char *pfx, FILE *fp)
1059 {
1060         int i;
1061
1062         for (i = 0; i < amount; i++) {
1063                 if (pfx && i == amount - 1)
1064                         fputs(pfx, fp);
1065                 putc('\t', fp);
1066         }
1067 }
1068
1069 /* little circular references here... */
1070 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1071
1072 static void
1073 sharg(union node *arg, FILE *fp)
1074 {
1075         char *p;
1076         struct nodelist *bqlist;
1077         unsigned char subtype;
1078
1079         if (arg->type != NARG) {
1080                 out1fmt("<node type %d>\n", arg->type);
1081                 abort();
1082         }
1083         bqlist = arg->narg.backquote;
1084         for (p = arg->narg.text; *p; p++) {
1085                 switch ((unsigned char)*p) {
1086                 case CTLESC:
1087                         p++;
1088                         putc(*p, fp);
1089                         break;
1090                 case CTLVAR:
1091                         putc('$', fp);
1092                         putc('{', fp);
1093                         subtype = *++p;
1094                         if (subtype == VSLENGTH)
1095                                 putc('#', fp);
1096
1097                         while (*p != '=') {
1098                                 putc(*p, fp);
1099                                 p++;
1100                         }
1101
1102                         if (subtype & VSNUL)
1103                                 putc(':', fp);
1104
1105                         switch (subtype & VSTYPE) {
1106                         case VSNORMAL:
1107                                 putc('}', fp);
1108                                 break;
1109                         case VSMINUS:
1110                                 putc('-', fp);
1111                                 break;
1112                         case VSPLUS:
1113                                 putc('+', fp);
1114                                 break;
1115                         case VSQUESTION:
1116                                 putc('?', fp);
1117                                 break;
1118                         case VSASSIGN:
1119                                 putc('=', fp);
1120                                 break;
1121                         case VSTRIMLEFT:
1122                                 putc('#', fp);
1123                                 break;
1124                         case VSTRIMLEFTMAX:
1125                                 putc('#', fp);
1126                                 putc('#', fp);
1127                                 break;
1128                         case VSTRIMRIGHT:
1129                                 putc('%', fp);
1130                                 break;
1131                         case VSTRIMRIGHTMAX:
1132                                 putc('%', fp);
1133                                 putc('%', fp);
1134                                 break;
1135                         case VSLENGTH:
1136                                 break;
1137                         default:
1138                                 out1fmt("<subtype %d>", subtype);
1139                         }
1140                         break;
1141                 case CTLENDVAR:
1142                         putc('}', fp);
1143                         break;
1144                 case CTLBACKQ:
1145                         putc('$', fp);
1146                         putc('(', fp);
1147                         shtree(bqlist->n, -1, NULL, fp);
1148                         putc(')', fp);
1149                         break;
1150                 default:
1151                         putc(*p, fp);
1152                         break;
1153                 }
1154         }
1155 }
1156
1157 static void
1158 shcmd(union node *cmd, FILE *fp)
1159 {
1160         union node *np;
1161         int first;
1162         const char *s;
1163         int dftfd;
1164
1165         first = 1;
1166         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1167                 if (!first)
1168                         putc(' ', fp);
1169                 sharg(np, fp);
1170                 first = 0;
1171         }
1172         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1173                 if (!first)
1174                         putc(' ', fp);
1175                 dftfd = 0;
1176                 switch (np->nfile.type) {
1177                 case NTO:      s = ">>"+1; dftfd = 1; break;
1178                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1179                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1180 #if BASH_REDIR_OUTPUT
1181                 case NTO2:
1182 #endif
1183                 case NTOFD:    s = ">&"; dftfd = 1; break;
1184                 case NFROM:    s = "<"; break;
1185                 case NFROMFD:  s = "<&"; break;
1186                 case NFROMTO:  s = "<>"; break;
1187                 default:       s = "*error*"; break;
1188                 }
1189                 if (np->nfile.fd != dftfd)
1190                         fprintf(fp, "%d", np->nfile.fd);
1191                 fputs(s, fp);
1192                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1193                         fprintf(fp, "%d", np->ndup.dupfd);
1194                 } else {
1195                         sharg(np->nfile.fname, fp);
1196                 }
1197                 first = 0;
1198         }
1199 }
1200
1201 static void
1202 shtree(union node *n, int ind, char *pfx, FILE *fp)
1203 {
1204         struct nodelist *lp;
1205         const char *s;
1206
1207         if (n == NULL)
1208                 return;
1209
1210         indent(ind, pfx, fp);
1211
1212         if (n == NODE_EOF) {
1213                 fputs("<EOF>", fp);
1214                 return;
1215         }
1216
1217         switch (n->type) {
1218         case NSEMI:
1219                 s = "; ";
1220                 goto binop;
1221         case NAND:
1222                 s = " && ";
1223                 goto binop;
1224         case NOR:
1225                 s = " || ";
1226  binop:
1227                 shtree(n->nbinary.ch1, ind, NULL, fp);
1228                 /* if (ind < 0) */
1229                         fputs(s, fp);
1230                 shtree(n->nbinary.ch2, ind, NULL, fp);
1231                 break;
1232         case NCMD:
1233                 shcmd(n, fp);
1234                 if (ind >= 0)
1235                         putc('\n', fp);
1236                 break;
1237         case NPIPE:
1238                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1239                         shtree(lp->n, 0, NULL, fp);
1240                         if (lp->next)
1241                                 fputs(" | ", fp);
1242                 }
1243                 if (n->npipe.pipe_backgnd)
1244                         fputs(" &", fp);
1245                 if (ind >= 0)
1246                         putc('\n', fp);
1247                 break;
1248         default:
1249                 fprintf(fp, "<node type %d>", n->type);
1250                 if (ind >= 0)
1251                         putc('\n', fp);
1252                 break;
1253         }
1254 }
1255
1256 static void
1257 showtree(union node *n)
1258 {
1259         trace_puts("showtree called\n");
1260         shtree(n, 1, NULL, stderr);
1261 }
1262
1263 #endif /* DEBUG */
1264
1265
1266 /* ============ Parser data */
1267
1268 /*
1269  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1270  */
1271 struct strlist {
1272         struct strlist *next;
1273         char *text;
1274 };
1275
1276 struct alias;
1277
1278 struct strpush {
1279         struct strpush *prev;   /* preceding string on stack */
1280         char *prev_string;
1281         int prev_left_in_line;
1282 #if ENABLE_ASH_ALIAS
1283         struct alias *ap;       /* if push was associated with an alias */
1284 #endif
1285         char *string;           /* remember the string since it may change */
1286
1287         /* Remember last two characters for pungetc. */
1288         int lastc[2];
1289
1290         /* Number of outstanding calls to pungetc. */
1291         int unget;
1292 };
1293
1294 /*
1295  * The parsefile structure pointed to by the global variable parsefile
1296  * contains information about the current file being read.
1297  */
1298 struct parsefile {
1299         struct parsefile *prev; /* preceding file on stack */
1300         int linno;              /* current line */
1301         int pf_fd;              /* file descriptor (or -1 if string) */
1302         int left_in_line;       /* number of chars left in this line */
1303         int left_in_buffer;     /* number of chars left in this buffer past the line */
1304         char *next_to_pgetc;    /* next char in buffer */
1305         char *buf;              /* input buffer */
1306         struct strpush *strpush; /* for pushing strings at this level */
1307         struct strpush basestrpush; /* so pushing one is fast */
1308
1309         /* Remember last two characters for pungetc. */
1310         int lastc[2];
1311
1312         /* Number of outstanding calls to pungetc. */
1313         int unget;
1314 };
1315
1316 static struct parsefile basepf;        /* top level input file */
1317 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1318 static char *commandname;              /* currently executing command */
1319
1320
1321 /* ============ Message printing */
1322
1323 static void
1324 ash_vmsg(const char *msg, va_list ap)
1325 {
1326         fprintf(stderr, "%s: ", arg0);
1327         if (commandname) {
1328                 if (strcmp(arg0, commandname))
1329                         fprintf(stderr, "%s: ", commandname);
1330                 if (!iflag || g_parsefile->pf_fd > 0)
1331                         fprintf(stderr, "line %d: ", errlinno);
1332         }
1333         vfprintf(stderr, msg, ap);
1334         newline_and_flush(stderr);
1335 }
1336
1337 /*
1338  * Exverror is called to raise the error exception.  If the second argument
1339  * is not NULL then error prints an error message using printf style
1340  * formatting.  It then raises the error exception.
1341  */
1342 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1343 static void
1344 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1345 {
1346 #if DEBUG
1347         if (msg) {
1348                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1349                 TRACEV((msg, ap));
1350         } else
1351                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1352         if (msg)
1353 #endif
1354                 ash_vmsg(msg, ap);
1355
1356         flush_stdout_stderr();
1357         raise_exception(cond);
1358         /* NOTREACHED */
1359 }
1360
1361 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1362 static void
1363 ash_msg_and_raise_error(const char *msg, ...)
1364 {
1365         va_list ap;
1366
1367         exitstatus = 2;
1368
1369         va_start(ap, msg);
1370         ash_vmsg_and_raise(EXERROR, msg, ap);
1371         /* NOTREACHED */
1372         va_end(ap);
1373 }
1374
1375 /*
1376  * 'fmt' must be a string literal.
1377  */
1378 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1379
1380 static void raise_error_syntax(const char *) NORETURN;
1381 static void
1382 raise_error_syntax(const char *msg)
1383 {
1384         errlinno = g_parsefile->linno;
1385         ash_msg_and_raise_error("syntax error: %s", msg);
1386         /* NOTREACHED */
1387 }
1388
1389 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1390 static void
1391 ash_msg_and_raise(int cond, const char *msg, ...)
1392 {
1393         va_list ap;
1394
1395         va_start(ap, msg);
1396         ash_vmsg_and_raise(cond, msg, ap);
1397         /* NOTREACHED */
1398         va_end(ap);
1399 }
1400
1401 /*
1402  * error/warning routines for external builtins
1403  */
1404 static void
1405 ash_msg(const char *fmt, ...)
1406 {
1407         va_list ap;
1408
1409         va_start(ap, fmt);
1410         ash_vmsg(fmt, ap);
1411         va_end(ap);
1412 }
1413
1414 /*
1415  * Return a string describing an error.  The returned string may be a
1416  * pointer to a static buffer that will be overwritten on the next call.
1417  * Action describes the operation that got the error.
1418  */
1419 static const char *
1420 errmsg(int e, const char *em)
1421 {
1422         if (e == ENOENT || e == ENOTDIR) {
1423                 return em;
1424         }
1425         return strerror(e);
1426 }
1427
1428
1429 /* ============ Memory allocation */
1430
1431 #if 0
1432 /* I consider these wrappers nearly useless:
1433  * ok, they return you to nearest exception handler, but
1434  * how much memory do you leak in the process, making
1435  * memory starvation worse?
1436  */
1437 static void *
1438 ckrealloc(void * p, size_t nbytes)
1439 {
1440         p = realloc(p, nbytes);
1441         if (!p)
1442                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1443         return p;
1444 }
1445
1446 static void *
1447 ckmalloc(size_t nbytes)
1448 {
1449         return ckrealloc(NULL, nbytes);
1450 }
1451
1452 static void *
1453 ckzalloc(size_t nbytes)
1454 {
1455         return memset(ckmalloc(nbytes), 0, nbytes);
1456 }
1457
1458 static char *
1459 ckstrdup(const char *s)
1460 {
1461         char *p = strdup(s);
1462         if (!p)
1463                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1464         return p;
1465 }
1466 #else
1467 /* Using bbox equivalents. They exit if out of memory */
1468 # define ckrealloc xrealloc
1469 # define ckmalloc  xmalloc
1470 # define ckzalloc  xzalloc
1471 # define ckstrdup  xstrdup
1472 #endif
1473
1474 /*
1475  * It appears that grabstackstr() will barf with such alignments
1476  * because stalloc() will return a string allocated in a new stackblock.
1477  */
1478 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1479 enum {
1480         /* Most machines require the value returned from malloc to be aligned
1481          * in some way.  The following macro will get this right
1482          * on many machines.  */
1483         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1484         /* Minimum size of a block */
1485         MINSIZE = SHELL_ALIGN(504),
1486 };
1487
1488 struct stack_block {
1489         struct stack_block *prev;
1490         char space[MINSIZE];
1491 };
1492
1493 struct stackmark {
1494         struct stack_block *stackp;
1495         char *stacknxt;
1496         size_t stacknleft;
1497 };
1498
1499
1500 struct globals_memstack {
1501         struct stack_block *g_stackp; // = &stackbase;
1502         char *g_stacknxt; // = stackbase.space;
1503         char *sstrend; // = stackbase.space + MINSIZE;
1504         size_t g_stacknleft; // = MINSIZE;
1505         struct stack_block stackbase;
1506 };
1507 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1508 #define G_memstack (*ash_ptr_to_globals_memstack)
1509 #define g_stackp     (G_memstack.g_stackp    )
1510 #define g_stacknxt   (G_memstack.g_stacknxt  )
1511 #define sstrend      (G_memstack.sstrend     )
1512 #define g_stacknleft (G_memstack.g_stacknleft)
1513 #define stackbase    (G_memstack.stackbase   )
1514 #define INIT_G_memstack() do { \
1515         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1516         barrier(); \
1517         g_stackp = &stackbase; \
1518         g_stacknxt = stackbase.space; \
1519         g_stacknleft = MINSIZE; \
1520         sstrend = stackbase.space + MINSIZE; \
1521 } while (0)
1522
1523
1524 #define stackblock()     ((void *)g_stacknxt)
1525 #define stackblocksize() g_stacknleft
1526
1527 /*
1528  * Parse trees for commands are allocated in lifo order, so we use a stack
1529  * to make this more efficient, and also to avoid all sorts of exception
1530  * handling code to handle interrupts in the middle of a parse.
1531  *
1532  * The size 504 was chosen because the Ultrix malloc handles that size
1533  * well.
1534  */
1535 static void *
1536 stalloc(size_t nbytes)
1537 {
1538         char *p;
1539         size_t aligned;
1540
1541         aligned = SHELL_ALIGN(nbytes);
1542         if (aligned > g_stacknleft) {
1543                 size_t len;
1544                 size_t blocksize;
1545                 struct stack_block *sp;
1546
1547                 blocksize = aligned;
1548                 if (blocksize < MINSIZE)
1549                         blocksize = MINSIZE;
1550                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1551                 if (len < blocksize)
1552                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1553                 INT_OFF;
1554                 sp = ckmalloc(len);
1555                 sp->prev = g_stackp;
1556                 g_stacknxt = sp->space;
1557                 g_stacknleft = blocksize;
1558                 sstrend = g_stacknxt + blocksize;
1559                 g_stackp = sp;
1560                 INT_ON;
1561         }
1562         p = g_stacknxt;
1563         g_stacknxt += aligned;
1564         g_stacknleft -= aligned;
1565         return p;
1566 }
1567
1568 static void *
1569 stzalloc(size_t nbytes)
1570 {
1571         return memset(stalloc(nbytes), 0, nbytes);
1572 }
1573
1574 static void
1575 stunalloc(void *p)
1576 {
1577 #if DEBUG
1578         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1579                 write(STDERR_FILENO, "stunalloc\n", 10);
1580                 abort();
1581         }
1582 #endif
1583         g_stacknleft += g_stacknxt - (char *)p;
1584         g_stacknxt = p;
1585 }
1586
1587 /*
1588  * Like strdup but works with the ash stack.
1589  */
1590 static char *
1591 sstrdup(const char *p)
1592 {
1593         size_t len = strlen(p) + 1;
1594         return memcpy(stalloc(len), p, len);
1595 }
1596
1597 static ALWAYS_INLINE void
1598 grabstackblock(size_t len)
1599 {
1600         stalloc(len);
1601 }
1602
1603 static void
1604 pushstackmark(struct stackmark *mark, size_t len)
1605 {
1606         mark->stackp = g_stackp;
1607         mark->stacknxt = g_stacknxt;
1608         mark->stacknleft = g_stacknleft;
1609         grabstackblock(len);
1610 }
1611
1612 static void
1613 setstackmark(struct stackmark *mark)
1614 {
1615         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1616 }
1617
1618 static void
1619 popstackmark(struct stackmark *mark)
1620 {
1621         struct stack_block *sp;
1622
1623         if (!mark->stackp)
1624                 return;
1625
1626         INT_OFF;
1627         while (g_stackp != mark->stackp) {
1628                 sp = g_stackp;
1629                 g_stackp = sp->prev;
1630                 free(sp);
1631         }
1632         g_stacknxt = mark->stacknxt;
1633         g_stacknleft = mark->stacknleft;
1634         sstrend = mark->stacknxt + mark->stacknleft;
1635         INT_ON;
1636 }
1637
1638 /*
1639  * When the parser reads in a string, it wants to stick the string on the
1640  * stack and only adjust the stack pointer when it knows how big the
1641  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1642  * of space on top of the stack and stackblocklen returns the length of
1643  * this block.  Growstackblock will grow this space by at least one byte,
1644  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1645  * part of the block that has been used.
1646  */
1647 static void
1648 growstackblock(void)
1649 {
1650         size_t newlen;
1651
1652         newlen = g_stacknleft * 2;
1653         if (newlen < g_stacknleft)
1654                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1655         if (newlen < 128)
1656                 newlen += 128;
1657
1658         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1659                 struct stack_block *sp;
1660                 struct stack_block *prevstackp;
1661                 size_t grosslen;
1662
1663                 INT_OFF;
1664                 sp = g_stackp;
1665                 prevstackp = sp->prev;
1666                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1667                 sp = ckrealloc(sp, grosslen);
1668                 sp->prev = prevstackp;
1669                 g_stackp = sp;
1670                 g_stacknxt = sp->space;
1671                 g_stacknleft = newlen;
1672                 sstrend = sp->space + newlen;
1673                 INT_ON;
1674         } else {
1675                 char *oldspace = g_stacknxt;
1676                 size_t oldlen = g_stacknleft;
1677                 char *p = stalloc(newlen);
1678
1679                 /* free the space we just allocated */
1680                 g_stacknxt = memcpy(p, oldspace, oldlen);
1681                 g_stacknleft += newlen;
1682         }
1683 }
1684
1685 /*
1686  * The following routines are somewhat easier to use than the above.
1687  * The user declares a variable of type STACKSTR, which may be declared
1688  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1689  * the user uses the macro STPUTC to add characters to the string.  In
1690  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1691  * grown as necessary.  When the user is done, she can just leave the
1692  * string there and refer to it using stackblock().  Or she can allocate
1693  * the space for it using grabstackstr().  If it is necessary to allow
1694  * someone else to use the stack temporarily and then continue to grow
1695  * the string, the user should use grabstack to allocate the space, and
1696  * then call ungrabstr(p) to return to the previous mode of operation.
1697  *
1698  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1699  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1700  * is space for at least one character.
1701  */
1702 static void *
1703 growstackstr(void)
1704 {
1705         size_t len = stackblocksize();
1706         growstackblock();
1707         return (char *)stackblock() + len;
1708 }
1709
1710 /*
1711  * Called from CHECKSTRSPACE.
1712  */
1713 static char *
1714 makestrspace(size_t newlen, char *p)
1715 {
1716         size_t len = p - g_stacknxt;
1717         size_t size;
1718
1719         for (;;) {
1720                 size_t nleft;
1721
1722                 size = stackblocksize();
1723                 nleft = size - len;
1724                 if (nleft >= newlen)
1725                         break;
1726                 growstackblock();
1727         }
1728         return (char *)stackblock() + len;
1729 }
1730
1731 static char *
1732 stack_nputstr(const char *s, size_t n, char *p)
1733 {
1734         p = makestrspace(n, p);
1735         p = (char *)mempcpy(p, s, n);
1736         return p;
1737 }
1738
1739 static char *
1740 stack_putstr(const char *s, char *p)
1741 {
1742         return stack_nputstr(s, strlen(s), p);
1743 }
1744
1745 static char *
1746 _STPUTC(int c, char *p)
1747 {
1748         if (p == sstrend)
1749                 p = growstackstr();
1750         *p++ = c;
1751         return p;
1752 }
1753
1754 #define STARTSTACKSTR(p)        ((p) = stackblock())
1755 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1756 #define CHECKSTRSPACE(n, p) do { \
1757         char *q = (p); \
1758         size_t l = (n); \
1759         size_t m = sstrend - q; \
1760         if (l > m) \
1761                 (p) = makestrspace(l, q); \
1762 } while (0)
1763 #define USTPUTC(c, p)           (*(p)++ = (c))
1764 #define STACKSTRNUL(p) do { \
1765         if ((p) == sstrend) \
1766                 (p) = growstackstr(); \
1767         *(p) = '\0'; \
1768 } while (0)
1769 #define STUNPUTC(p)             (--(p))
1770 #define STTOPC(p)               ((p)[-1])
1771 #define STADJUST(amount, p)     ((p) += (amount))
1772
1773 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1774 #define ungrabstackstr(s, p)    stunalloc(s)
1775 #define stackstrend()           ((void *)sstrend)
1776
1777
1778 /* ============ String helpers */
1779
1780 /*
1781  * prefix -- see if pfx is a prefix of string.
1782  */
1783 static char *
1784 prefix(const char *string, const char *pfx)
1785 {
1786         while (*pfx) {
1787                 if (*pfx++ != *string++)
1788                         return NULL;
1789         }
1790         return (char *) string;
1791 }
1792
1793 /*
1794  * Check for a valid number.  This should be elsewhere.
1795  */
1796 static int
1797 is_number(const char *p)
1798 {
1799         do {
1800                 if (!isdigit(*p))
1801                         return 0;
1802         } while (*++p != '\0');
1803         return 1;
1804 }
1805
1806 /*
1807  * Convert a string of digits to an integer, printing an error message on
1808  * failure.
1809  */
1810 static int
1811 number(const char *s)
1812 {
1813         if (!is_number(s))
1814                 ash_msg_and_raise_error(msg_illnum, s);
1815         return atoi(s);
1816 }
1817
1818 /*
1819  * Produce a single quoted string suitable as input to the shell.
1820  * The return string is allocated on the stack.
1821  */
1822 static char *
1823 single_quote(const char *s)
1824 {
1825         char *p;
1826
1827         STARTSTACKSTR(p);
1828
1829         do {
1830                 char *q;
1831                 size_t len;
1832
1833                 len = strchrnul(s, '\'') - s;
1834
1835                 q = p = makestrspace(len + 3, p);
1836
1837                 *q++ = '\'';
1838                 q = (char *)mempcpy(q, s, len);
1839                 *q++ = '\'';
1840                 s += len;
1841
1842                 STADJUST(q - p, p);
1843
1844                 if (*s != '\'')
1845                         break;
1846                 len = 0;
1847                 do len++; while (*++s == '\'');
1848
1849                 q = p = makestrspace(len + 3, p);
1850
1851                 *q++ = '"';
1852                 q = (char *)mempcpy(q, s - len, len);
1853                 *q++ = '"';
1854
1855                 STADJUST(q - p, p);
1856         } while (*s);
1857
1858         USTPUTC('\0', p);
1859
1860         return stackblock();
1861 }
1862
1863 /*
1864  * Produce a possibly single quoted string suitable as input to the shell.
1865  * If quoting was done, the return string is allocated on the stack,
1866  * otherwise a pointer to the original string is returned.
1867  */
1868 static const char *
1869 maybe_single_quote(const char *s)
1870 {
1871         const char *p = s;
1872
1873         while (*p) {
1874                 /* Assuming ACSII */
1875                 /* quote ctrl_chars space !"#$%&'()* */
1876                 if (*p < '+')
1877                         goto need_quoting;
1878                 /* quote ;<=>? */
1879                 if (*p >= ';' && *p <= '?')
1880                         goto need_quoting;
1881                 /* quote `[\ */
1882                 if (*p == '`')
1883                         goto need_quoting;
1884                 if (*p == '[')
1885                         goto need_quoting;
1886                 if (*p == '\\')
1887                         goto need_quoting;
1888                 /* quote {|}~ DEL and high bytes */
1889                 if (*p > 'z')
1890                         goto need_quoting;
1891                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1892                 /* TODO: maybe avoid quoting % */
1893                 p++;
1894         }
1895         return s;
1896
1897  need_quoting:
1898         return single_quote(s);
1899 }
1900
1901
1902 /* ============ nextopt */
1903
1904 static char **argptr;                  /* argument list for builtin commands */
1905 static char *optionarg;                /* set by nextopt (like getopt) */
1906 static char *optptr;                   /* used by nextopt */
1907
1908 /*
1909  * XXX - should get rid of. Have all builtins use getopt(3).
1910  * The library getopt must have the BSD extension static variable
1911  * "optreset", otherwise it can't be used within the shell safely.
1912  *
1913  * Standard option processing (a la getopt) for builtin routines.
1914  * The only argument that is passed to nextopt is the option string;
1915  * the other arguments are unnecessary. It returns the character,
1916  * or '\0' on end of input.
1917  */
1918 static int
1919 nextopt(const char *optstring)
1920 {
1921         char *p;
1922         const char *q;
1923         char c;
1924
1925         p = optptr;
1926         if (p == NULL || *p == '\0') {
1927                 /* We ate entire "-param", take next one */
1928                 p = *argptr;
1929                 if (p == NULL)
1930                         return '\0';
1931                 if (*p != '-')
1932                         return '\0';
1933                 if (*++p == '\0') /* just "-" ? */
1934                         return '\0';
1935                 argptr++;
1936                 if (LONE_DASH(p)) /* "--" ? */
1937                         return '\0';
1938                 /* p => next "-param" */
1939         }
1940         /* p => some option char in the middle of a "-param" */
1941         c = *p++;
1942         for (q = optstring; *q != c;) {
1943                 if (*q == '\0')
1944                         ash_msg_and_raise_error("illegal option -%c", c);
1945                 if (*++q == ':')
1946                         q++;
1947         }
1948         if (*++q == ':') {
1949                 if (*p == '\0') {
1950                         p = *argptr++;
1951                         if (p == NULL)
1952                                 ash_msg_and_raise_error("no arg for -%c option", c);
1953                 }
1954                 optionarg = p;
1955                 p = NULL;
1956         }
1957         optptr = p;
1958         return c;
1959 }
1960
1961
1962 /* ============ Shell variables */
1963
1964 struct shparam {
1965         int nparam;             /* # of positional parameters (without $0) */
1966 #if ENABLE_ASH_GETOPTS
1967         int optind;             /* next parameter to be processed by getopts */
1968         int optoff;             /* used by getopts */
1969 #endif
1970         unsigned char malloced; /* if parameter list dynamically allocated */
1971         char **p;               /* parameter list */
1972 };
1973
1974 /*
1975  * Free the list of positional parameters.
1976  */
1977 static void
1978 freeparam(volatile struct shparam *param)
1979 {
1980         if (param->malloced) {
1981                 char **ap, **ap1;
1982                 ap = ap1 = param->p;
1983                 while (*ap)
1984                         free(*ap++);
1985                 free(ap1);
1986         }
1987 }
1988
1989 #if ENABLE_ASH_GETOPTS
1990 static void FAST_FUNC getoptsreset(const char *value);
1991 #endif
1992
1993 struct var {
1994         struct var *next;               /* next entry in hash list */
1995         int flags;                      /* flags are defined above */
1996         const char *var_text;           /* name=value */
1997         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1998                                         /* the variable gets set/unset */
1999 };
2000
2001 struct localvar {
2002         struct localvar *next;          /* next local variable in list */
2003         struct var *vp;                 /* the variable that was made local */
2004         int flags;                      /* saved flags */
2005         const char *text;               /* saved text */
2006 };
2007
2008 /* flags */
2009 #define VEXPORT         0x01    /* variable is exported */
2010 #define VREADONLY       0x02    /* variable cannot be modified */
2011 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2012 #define VTEXTFIXED      0x08    /* text is statically allocated */
2013 #define VSTACK          0x10    /* text is allocated on the stack */
2014 #define VUNSET          0x20    /* the variable is not set */
2015 #define VNOFUNC         0x40    /* don't call the callback function */
2016 #define VNOSET          0x80    /* do not set variable - just readonly test */
2017 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2018 #if ENABLE_ASH_RANDOM_SUPPORT
2019 # define VDYNAMIC       0x200   /* dynamic variable */
2020 #else
2021 # define VDYNAMIC       0
2022 #endif
2023
2024
2025 /* Need to be before varinit_data[] */
2026 #if ENABLE_LOCALE_SUPPORT
2027 static void FAST_FUNC
2028 change_lc_all(const char *value)
2029 {
2030         if (value && *value != '\0')
2031                 setlocale(LC_ALL, value);
2032 }
2033 static void FAST_FUNC
2034 change_lc_ctype(const char *value)
2035 {
2036         if (value && *value != '\0')
2037                 setlocale(LC_CTYPE, value);
2038 }
2039 #endif
2040 #if ENABLE_ASH_MAIL
2041 static void chkmail(void);
2042 static void changemail(const char *var_value) FAST_FUNC;
2043 #else
2044 # define chkmail()  ((void)0)
2045 #endif
2046 static void changepath(const char *) FAST_FUNC;
2047 #if ENABLE_ASH_RANDOM_SUPPORT
2048 static void change_random(const char *) FAST_FUNC;
2049 #endif
2050
2051 static const struct {
2052         int flags;
2053         const char *var_text;
2054         void (*var_func)(const char *) FAST_FUNC;
2055 } varinit_data[] = {
2056         /*
2057          * Note: VEXPORT would not work correctly here for NOFORK applets:
2058          * some environment strings may be constant.
2059          */
2060         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2061 #if ENABLE_ASH_MAIL
2062         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2063         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2064 #endif
2065         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2066         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2067         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2068         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2069 #if ENABLE_ASH_GETOPTS
2070         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2071 #endif
2072         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2073 #if ENABLE_ASH_RANDOM_SUPPORT
2074         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2075 #endif
2076 #if ENABLE_LOCALE_SUPPORT
2077         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2078         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2079 #endif
2080 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2081         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2082 #endif
2083 };
2084
2085 struct redirtab;
2086
2087 struct globals_var {
2088         struct shparam shellparam;      /* $@ current positional parameters */
2089         struct redirtab *redirlist;
2090         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2091         struct var *vartab[VTABSIZE];
2092         struct var varinit[ARRAY_SIZE(varinit_data)];
2093         int lineno;
2094         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2095 };
2096 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2097 #define G_var (*ash_ptr_to_globals_var)
2098 #define shellparam    (G_var.shellparam   )
2099 //#define redirlist     (G_var.redirlist    )
2100 #define preverrout_fd (G_var.preverrout_fd)
2101 #define vartab        (G_var.vartab       )
2102 #define varinit       (G_var.varinit      )
2103 #define lineno        (G_var.lineno       )
2104 #define linenovar     (G_var.linenovar    )
2105 #define vifs      varinit[0]
2106 #if ENABLE_ASH_MAIL
2107 # define vmail    (&vifs)[1]
2108 # define vmpath   (&vmail)[1]
2109 # define vpath    (&vmpath)[1]
2110 #else
2111 # define vpath    (&vifs)[1]
2112 #endif
2113 #define vps1      (&vpath)[1]
2114 #define vps2      (&vps1)[1]
2115 #define vps4      (&vps2)[1]
2116 #if ENABLE_ASH_GETOPTS
2117 # define voptind  (&vps4)[1]
2118 # define vlineno  (&voptind)[1]
2119 # if ENABLE_ASH_RANDOM_SUPPORT
2120 #  define vrandom (&vlineno)[1]
2121 # endif
2122 #else
2123 # define vlineno  (&vps4)[1]
2124 # if ENABLE_ASH_RANDOM_SUPPORT
2125 #  define vrandom (&vlineno)[1]
2126 # endif
2127 #endif
2128 #define INIT_G_var() do { \
2129         unsigned i; \
2130         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2131         barrier(); \
2132         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2133                 varinit[i].flags    = varinit_data[i].flags; \
2134                 varinit[i].var_text = varinit_data[i].var_text; \
2135                 varinit[i].var_func = varinit_data[i].var_func; \
2136         } \
2137         strcpy(linenovar, "LINENO="); \
2138         vlineno.var_text = linenovar; \
2139 } while (0)
2140
2141 /*
2142  * The following macros access the values of the above variables.
2143  * They have to skip over the name.  They return the null string
2144  * for unset variables.
2145  */
2146 #define ifsval()        (vifs.var_text + 4)
2147 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2148 #if ENABLE_ASH_MAIL
2149 # define mailval()      (vmail.var_text + 5)
2150 # define mpathval()     (vmpath.var_text + 9)
2151 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2152 #endif
2153 #define pathval()       (vpath.var_text + 5)
2154 #define ps1val()        (vps1.var_text + 4)
2155 #define ps2val()        (vps2.var_text + 4)
2156 #define ps4val()        (vps4.var_text + 4)
2157 #if ENABLE_ASH_GETOPTS
2158 # define optindval()    (voptind.var_text + 7)
2159 #endif
2160
2161 #if ENABLE_ASH_GETOPTS
2162 static void FAST_FUNC
2163 getoptsreset(const char *value)
2164 {
2165         shellparam.optind = 1;
2166         if (is_number(value))
2167                 shellparam.optind = number(value) ?: 1;
2168         shellparam.optoff = -1;
2169 }
2170 #endif
2171
2172 /*
2173  * Compares two strings up to the first = or '\0'.  The first
2174  * string must be terminated by '='; the second may be terminated by
2175  * either '=' or '\0'.
2176  */
2177 static int
2178 varcmp(const char *p, const char *q)
2179 {
2180         int c, d;
2181
2182         while ((c = *p) == (d = *q)) {
2183                 if (c == '\0' || c == '=')
2184                         goto out;
2185                 p++;
2186                 q++;
2187         }
2188         if (c == '=')
2189                 c = '\0';
2190         if (d == '=')
2191                 d = '\0';
2192  out:
2193         return c - d;
2194 }
2195
2196 /*
2197  * Find the appropriate entry in the hash table from the name.
2198  */
2199 static struct var **
2200 hashvar(const char *p)
2201 {
2202         unsigned hashval;
2203
2204         hashval = ((unsigned char) *p) << 4;
2205         while (*p && *p != '=')
2206                 hashval += (unsigned char) *p++;
2207         return &vartab[hashval % VTABSIZE];
2208 }
2209
2210 static int
2211 vpcmp(const void *a, const void *b)
2212 {
2213         return varcmp(*(const char **)a, *(const char **)b);
2214 }
2215
2216 /*
2217  * This routine initializes the builtin variables.
2218  */
2219 static void
2220 initvar(void)
2221 {
2222         struct var *vp;
2223         struct var *end;
2224         struct var **vpp;
2225
2226         /*
2227          * PS1 depends on uid
2228          */
2229 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2230         vps1.var_text = "PS1=\\w \\$ ";
2231 #else
2232         if (!geteuid())
2233                 vps1.var_text = "PS1=# ";
2234 #endif
2235         vp = varinit;
2236         end = vp + ARRAY_SIZE(varinit);
2237         do {
2238                 vpp = hashvar(vp->var_text);
2239                 vp->next = *vpp;
2240                 *vpp = vp;
2241         } while (++vp < end);
2242 }
2243
2244 static struct var **
2245 findvar(struct var **vpp, const char *name)
2246 {
2247         for (; *vpp; vpp = &(*vpp)->next) {
2248                 if (varcmp((*vpp)->var_text, name) == 0) {
2249                         break;
2250                 }
2251         }
2252         return vpp;
2253 }
2254
2255 /*
2256  * Find the value of a variable.  Returns NULL if not set.
2257  */
2258 static const char* FAST_FUNC
2259 lookupvar(const char *name)
2260 {
2261         struct var *v;
2262
2263         v = *findvar(hashvar(name), name);
2264         if (v) {
2265 #if ENABLE_ASH_RANDOM_SUPPORT
2266         /*
2267          * Dynamic variables are implemented roughly the same way they are
2268          * in bash. Namely, they're "special" so long as they aren't unset.
2269          * As soon as they're unset, they're no longer dynamic, and dynamic
2270          * lookup will no longer happen at that point. -- PFM.
2271          */
2272                 if (v->flags & VDYNAMIC)
2273                         v->var_func(NULL);
2274 #endif
2275                 if (!(v->flags & VUNSET)) {
2276                         if (v == &vlineno && v->var_text == linenovar) {
2277                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2278                         }
2279                         return var_end(v->var_text);
2280                 }
2281         }
2282         return NULL;
2283 }
2284
2285 #if ENABLE_UNICODE_SUPPORT
2286 static void
2287 reinit_unicode_for_ash(void)
2288 {
2289         /* Unicode support should be activated even if LANG is set
2290          * _during_ shell execution, not only if it was set when
2291          * shell was started. Therefore, re-check LANG every time:
2292          */
2293         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2294          || ENABLE_UNICODE_USING_LOCALE
2295         ) {
2296                 const char *s = lookupvar("LC_ALL");
2297                 if (!s) s = lookupvar("LC_CTYPE");
2298                 if (!s) s = lookupvar("LANG");
2299                 reinit_unicode(s);
2300         }
2301 }
2302 #else
2303 # define reinit_unicode_for_ash() ((void)0)
2304 #endif
2305
2306 /*
2307  * Search the environment of a builtin command.
2308  */
2309 static ALWAYS_INLINE const char *
2310 bltinlookup(const char *name)
2311 {
2312         return lookupvar(name);
2313 }
2314
2315 /*
2316  * Same as setvar except that the variable and value are passed in
2317  * the first argument as name=value.  Since the first argument will
2318  * be actually stored in the table, it should not be a string that
2319  * will go away.
2320  * Called with interrupts off.
2321  */
2322 static struct var *
2323 setvareq(char *s, int flags)
2324 {
2325         struct var *vp, **vpp;
2326
2327         vpp = hashvar(s);
2328         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2329         vpp = findvar(vpp, s);
2330         vp = *vpp;
2331         if (vp) {
2332                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2333                         const char *n;
2334
2335                         if (flags & VNOSAVE)
2336                                 free(s);
2337                         n = vp->var_text;
2338                         exitstatus = 1;
2339                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2340                 }
2341
2342                 if (flags & VNOSET)
2343                         goto out;
2344
2345                 if (vp->var_func && !(flags & VNOFUNC))
2346                         vp->var_func(var_end(s));
2347
2348                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2349                         free((char*)vp->var_text);
2350
2351                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2352                         *vpp = vp->next;
2353                         free(vp);
2354  out_free:
2355                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2356                                 free(s);
2357                         goto out;
2358                 }
2359
2360                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2361         } else {
2362                 /* variable s is not found */
2363                 if (flags & VNOSET)
2364                         goto out;
2365                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2366                         goto out_free;
2367                 vp = ckzalloc(sizeof(*vp));
2368                 vp->next = *vpp;
2369                 /*vp->func = NULL; - ckzalloc did it */
2370                 *vpp = vp;
2371         }
2372         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2373                 s = ckstrdup(s);
2374         vp->var_text = s;
2375         vp->flags = flags;
2376
2377  out:
2378         return vp;
2379 }
2380
2381 /*
2382  * Set the value of a variable.  The flags argument is ored with the
2383  * flags of the variable.  If val is NULL, the variable is unset.
2384  */
2385 static struct var *
2386 setvar(const char *name, const char *val, int flags)
2387 {
2388         const char *q;
2389         char *p;
2390         char *nameeq;
2391         size_t namelen;
2392         size_t vallen;
2393         struct var *vp;
2394
2395         q = endofname(name);
2396         p = strchrnul(q, '=');
2397         namelen = p - name;
2398         if (!namelen || p != q)
2399                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2400         vallen = 0;
2401         if (val == NULL) {
2402                 flags |= VUNSET;
2403         } else {
2404                 vallen = strlen(val);
2405         }
2406
2407         INT_OFF;
2408         nameeq = ckmalloc(namelen + vallen + 2);
2409         p = mempcpy(nameeq, name, namelen);
2410         if (val) {
2411                 *p++ = '=';
2412                 p = mempcpy(p, val, vallen);
2413         }
2414         *p = '\0';
2415         vp = setvareq(nameeq, flags | VNOSAVE);
2416         INT_ON;
2417
2418         return vp;
2419 }
2420
2421 static void FAST_FUNC
2422 setvar0(const char *name, const char *val)
2423 {
2424         setvar(name, val, 0);
2425 }
2426
2427 /*
2428  * Unset the specified variable.
2429  */
2430 static void
2431 unsetvar(const char *s)
2432 {
2433         setvar(s, NULL, 0);
2434 }
2435
2436 /*
2437  * Process a linked list of variable assignments.
2438  */
2439 static void
2440 listsetvar(struct strlist *list_set_var, int flags)
2441 {
2442         struct strlist *lp = list_set_var;
2443
2444         if (!lp)
2445                 return;
2446         INT_OFF;
2447         do {
2448                 setvareq(lp->text, flags);
2449                 lp = lp->next;
2450         } while (lp);
2451         INT_ON;
2452 }
2453
2454 /*
2455  * Generate a list of variables satisfying the given conditions.
2456  */
2457 #if !ENABLE_FEATURE_SH_NOFORK
2458 # define listvars(on, off, lp, end) listvars(on, off, end)
2459 #endif
2460 static char **
2461 listvars(int on, int off, struct strlist *lp, char ***end)
2462 {
2463         struct var **vpp;
2464         struct var *vp;
2465         char **ep;
2466         int mask;
2467
2468         STARTSTACKSTR(ep);
2469         vpp = vartab;
2470         mask = on | off;
2471         do {
2472                 for (vp = *vpp; vp; vp = vp->next) {
2473                         if ((vp->flags & mask) == on) {
2474 #if ENABLE_FEATURE_SH_NOFORK
2475                                 /* If variable with the same name is both
2476                                  * exported and temporarily set for a command:
2477                                  *  export ZVAR=5
2478                                  *  ZVAR=6 printenv
2479                                  * then "ZVAR=6" will be both in vartab and
2480                                  * lp lists. Do not pass it twice to printenv.
2481                                  */
2482                                 struct strlist *lp1 = lp;
2483                                 while (lp1) {
2484                                         if (strcmp(lp1->text, vp->var_text) == 0)
2485                                                 goto skip;
2486                                         lp1 = lp1->next;
2487                                 }
2488 #endif
2489                                 if (ep == stackstrend())
2490                                         ep = growstackstr();
2491                                 *ep++ = (char*)vp->var_text;
2492 #if ENABLE_FEATURE_SH_NOFORK
2493  skip: ;
2494 #endif
2495                         }
2496                 }
2497         } while (++vpp < vartab + VTABSIZE);
2498
2499 #if ENABLE_FEATURE_SH_NOFORK
2500         while (lp) {
2501                 if (ep == stackstrend())
2502                         ep = growstackstr();
2503                 *ep++ = lp->text;
2504                 lp = lp->next;
2505         }
2506 #endif
2507
2508         if (ep == stackstrend())
2509                 ep = growstackstr();
2510         if (end)
2511                 *end = ep;
2512         *ep++ = NULL;
2513         return grabstackstr(ep);
2514 }
2515
2516
2517 /* ============ Path search helper
2518  *
2519  * The variable path (passed by reference) should be set to the start
2520  * of the path before the first call; path_advance will update
2521  * this value as it proceeds.  Successive calls to path_advance will return
2522  * the possible path expansions in sequence.  If an option (indicated by
2523  * a percent sign) appears in the path entry then the global variable
2524  * pathopt will be set to point to it; otherwise pathopt will be set to
2525  * NULL.
2526  */
2527 static const char *pathopt;     /* set by path_advance */
2528
2529 static char *
2530 path_advance(const char **path, const char *name)
2531 {
2532         const char *p;
2533         char *q;
2534         const char *start;
2535         size_t len;
2536
2537         if (*path == NULL)
2538                 return NULL;
2539         start = *path;
2540         for (p = start; *p && *p != ':' && *p != '%'; p++)
2541                 continue;
2542         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2543         while (stackblocksize() < len)
2544                 growstackblock();
2545         q = stackblock();
2546         if (p != start) {
2547                 q = mempcpy(q, start, p - start);
2548                 *q++ = '/';
2549         }
2550         strcpy(q, name);
2551         pathopt = NULL;
2552         if (*p == '%') {
2553                 pathopt = ++p;
2554                 while (*p && *p != ':')
2555                         p++;
2556         }
2557         if (*p == ':')
2558                 *path = p + 1;
2559         else
2560                 *path = NULL;
2561         return stalloc(len);
2562 }
2563
2564
2565 /* ============ Prompt */
2566
2567 static smallint doprompt;                   /* if set, prompt the user */
2568 static smallint needprompt;                 /* true if interactive and at start of line */
2569
2570 #if ENABLE_FEATURE_EDITING
2571 static line_input_t *line_input_state;
2572 static const char *cmdedit_prompt;
2573 static void
2574 putprompt(const char *s)
2575 {
2576         if (ENABLE_ASH_EXPAND_PRMT) {
2577                 free((char*)cmdedit_prompt);
2578                 cmdedit_prompt = ckstrdup(s);
2579                 return;
2580         }
2581         cmdedit_prompt = s;
2582 }
2583 #else
2584 static void
2585 putprompt(const char *s)
2586 {
2587         out2str(s);
2588 }
2589 #endif
2590
2591 /* expandstr() needs parsing machinery, so it is far away ahead... */
2592 static const char *expandstr(const char *ps, int syntax_type);
2593 /* Values for syntax param */
2594 #define BASESYNTAX 0    /* not in quotes */
2595 #define DQSYNTAX   1    /* in double quotes */
2596 #define SQSYNTAX   2    /* in single quotes */
2597 #define ARISYNTAX  3    /* in arithmetic */
2598 #if ENABLE_ASH_EXPAND_PRMT
2599 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2600 #endif
2601 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2602
2603 /*
2604  * called by editline -- any expansions to the prompt should be added here.
2605  */
2606 static void
2607 setprompt_if(smallint do_set, int whichprompt)
2608 {
2609         const char *prompt;
2610         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2611
2612         if (!do_set)
2613                 return;
2614
2615         needprompt = 0;
2616
2617         switch (whichprompt) {
2618         case 1:
2619                 prompt = ps1val();
2620                 break;
2621         case 2:
2622                 prompt = ps2val();
2623                 break;
2624         default:                        /* 0 */
2625                 prompt = nullstr;
2626         }
2627 #if ENABLE_ASH_EXPAND_PRMT
2628         pushstackmark(&smark, stackblocksize());
2629         putprompt(expandstr(prompt, PSSYNTAX));
2630         popstackmark(&smark);
2631 #else
2632         putprompt(prompt);
2633 #endif
2634 }
2635
2636
2637 /* ============ The cd and pwd commands */
2638
2639 #define CD_PHYSICAL 1
2640 #define CD_PRINT 2
2641
2642 static int
2643 cdopt(void)
2644 {
2645         int flags = 0;
2646         int i, j;
2647
2648         j = 'L';
2649         while ((i = nextopt("LP")) != '\0') {
2650                 if (i != j) {
2651                         flags ^= CD_PHYSICAL;
2652                         j = i;
2653                 }
2654         }
2655
2656         return flags;
2657 }
2658
2659 /*
2660  * Update curdir (the name of the current directory) in response to a
2661  * cd command.
2662  */
2663 static const char *
2664 updatepwd(const char *dir)
2665 {
2666         char *new;
2667         char *p;
2668         char *cdcomppath;
2669         const char *lim;
2670
2671         cdcomppath = sstrdup(dir);
2672         STARTSTACKSTR(new);
2673         if (*dir != '/') {
2674                 if (curdir == nullstr)
2675                         return 0;
2676                 new = stack_putstr(curdir, new);
2677         }
2678         new = makestrspace(strlen(dir) + 2, new);
2679         lim = (char *)stackblock() + 1;
2680         if (*dir != '/') {
2681                 if (new[-1] != '/')
2682                         USTPUTC('/', new);
2683                 if (new > lim && *lim == '/')
2684                         lim++;
2685         } else {
2686                 USTPUTC('/', new);
2687                 cdcomppath++;
2688                 if (dir[1] == '/' && dir[2] != '/') {
2689                         USTPUTC('/', new);
2690                         cdcomppath++;
2691                         lim++;
2692                 }
2693         }
2694         p = strtok(cdcomppath, "/");
2695         while (p) {
2696                 switch (*p) {
2697                 case '.':
2698                         if (p[1] == '.' && p[2] == '\0') {
2699                                 while (new > lim) {
2700                                         STUNPUTC(new);
2701                                         if (new[-1] == '/')
2702                                                 break;
2703                                 }
2704                                 break;
2705                         }
2706                         if (p[1] == '\0')
2707                                 break;
2708                         /* fall through */
2709                 default:
2710                         new = stack_putstr(p, new);
2711                         USTPUTC('/', new);
2712                 }
2713                 p = strtok(NULL, "/");
2714         }
2715         if (new > lim)
2716                 STUNPUTC(new);
2717         *new = 0;
2718         return stackblock();
2719 }
2720
2721 /*
2722  * Find out what the current directory is. If we already know the current
2723  * directory, this routine returns immediately.
2724  */
2725 static char *
2726 getpwd(void)
2727 {
2728         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2729         return dir ? dir : nullstr;
2730 }
2731
2732 static void
2733 setpwd(const char *val, int setold)
2734 {
2735         char *oldcur, *dir;
2736
2737         oldcur = dir = curdir;
2738
2739         if (setold) {
2740                 setvar("OLDPWD", oldcur, VEXPORT);
2741         }
2742         INT_OFF;
2743         if (physdir != nullstr) {
2744                 if (physdir != oldcur)
2745                         free(physdir);
2746                 physdir = nullstr;
2747         }
2748         if (oldcur == val || !val) {
2749                 char *s = getpwd();
2750                 physdir = s;
2751                 if (!val)
2752                         dir = s;
2753         } else
2754                 dir = ckstrdup(val);
2755         if (oldcur != dir && oldcur != nullstr) {
2756                 free(oldcur);
2757         }
2758         curdir = dir;
2759         INT_ON;
2760         setvar("PWD", dir, VEXPORT);
2761 }
2762
2763 static void hashcd(void);
2764
2765 /*
2766  * Actually do the chdir.  We also call hashcd to let other routines
2767  * know that the current directory has changed.
2768  */
2769 static int
2770 docd(const char *dest, int flags)
2771 {
2772         const char *dir = NULL;
2773         int err;
2774
2775         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2776
2777         INT_OFF;
2778         if (!(flags & CD_PHYSICAL)) {
2779                 dir = updatepwd(dest);
2780                 if (dir)
2781                         dest = dir;
2782         }
2783         err = chdir(dest);
2784         if (err)
2785                 goto out;
2786         setpwd(dir, 1);
2787         hashcd();
2788  out:
2789         INT_ON;
2790         return err;
2791 }
2792
2793 static int FAST_FUNC
2794 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2795 {
2796         const char *dest;
2797         const char *path;
2798         const char *p;
2799         char c;
2800         struct stat statb;
2801         int flags;
2802
2803         flags = cdopt();
2804         dest = *argptr;
2805         if (!dest)
2806                 dest = bltinlookup("HOME");
2807         else if (LONE_DASH(dest)) {
2808                 dest = bltinlookup("OLDPWD");
2809                 flags |= CD_PRINT;
2810         }
2811         if (!dest)
2812                 dest = nullstr;
2813         if (*dest == '/')
2814                 goto step6;
2815         if (*dest == '.') {
2816                 c = dest[1];
2817  dotdot:
2818                 switch (c) {
2819                 case '\0':
2820                 case '/':
2821                         goto step6;
2822                 case '.':
2823                         c = dest[2];
2824                         if (c != '.')
2825                                 goto dotdot;
2826                 }
2827         }
2828         if (!*dest)
2829                 dest = ".";
2830         path = bltinlookup("CDPATH");
2831         while (path) {
2832                 c = *path;
2833                 p = path_advance(&path, dest);
2834                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2835                         if (c && c != ':')
2836                                 flags |= CD_PRINT;
2837  docd:
2838                         if (!docd(p, flags))
2839                                 goto out;
2840                         goto err;
2841                 }
2842         }
2843
2844  step6:
2845         p = dest;
2846         goto docd;
2847
2848  err:
2849         ash_msg_and_raise_perror("can't cd to %s", dest);
2850         /* NOTREACHED */
2851  out:
2852         if (flags & CD_PRINT)
2853                 out1fmt("%s\n", curdir);
2854         return 0;
2855 }
2856
2857 static int FAST_FUNC
2858 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2859 {
2860         int flags;
2861         const char *dir = curdir;
2862
2863         flags = cdopt();
2864         if (flags) {
2865                 if (physdir == nullstr)
2866                         setpwd(dir, 0);
2867                 dir = physdir;
2868         }
2869         out1fmt("%s\n", dir);
2870         return 0;
2871 }
2872
2873
2874 /* ============ ... */
2875
2876
2877 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2878
2879 /* Syntax classes */
2880 #define CWORD     0             /* character is nothing special */
2881 #define CNL       1             /* newline character */
2882 #define CBACK     2             /* a backslash character */
2883 #define CSQUOTE   3             /* single quote */
2884 #define CDQUOTE   4             /* double quote */
2885 #define CENDQUOTE 5             /* a terminating quote */
2886 #define CBQUOTE   6             /* backwards single quote */
2887 #define CVAR      7             /* a dollar sign */
2888 #define CENDVAR   8             /* a '}' character */
2889 #define CLP       9             /* a left paren in arithmetic */
2890 #define CRP      10             /* a right paren in arithmetic */
2891 #define CENDFILE 11             /* end of file */
2892 #define CCTL     12             /* like CWORD, except it must be escaped */
2893 #define CSPCL    13             /* these terminate a word */
2894 #define CIGN     14             /* character should be ignored */
2895
2896 #define PEOF     256
2897 #if ENABLE_ASH_ALIAS
2898 # define PEOA    257
2899 #endif
2900
2901 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2902
2903 #if ENABLE_FEATURE_SH_MATH
2904 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2905 #else
2906 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2907 #endif
2908 static const uint16_t S_I_T[] ALIGN2 = {
2909 #if ENABLE_ASH_ALIAS
2910         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2911 #endif
2912         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2913         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2914         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2915         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2916         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2917         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2918         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2919         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2920         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2921         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2922         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2923 #if !USE_SIT_FUNCTION
2924         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2925         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2926         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2927 #endif
2928 #undef SIT_ITEM
2929 };
2930 /* Constants below must match table above */
2931 enum {
2932 #if ENABLE_ASH_ALIAS
2933         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2934 #endif
2935         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2936         CNL_CNL_CNL_CNL                    , /*  2 */
2937         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2938         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2939         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2940         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2941         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2942         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2943         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2944         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2945         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2946         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2947         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2948         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2949 };
2950
2951 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2952  * caller must ensure proper cast on it if c is *char_ptr!
2953  */
2954 #if USE_SIT_FUNCTION
2955
2956 static int
2957 SIT(int c, int syntax)
2958 {
2959         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2960         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2961         /*
2962          * This causes '/' to be prepended with CTLESC in dquoted string,
2963          * making "./file"* treated incorrectly because we feed
2964          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2965          * The "homegrown" glob implementation is okay with that,
2966          * but glibc one isn't. With '/' always treated as CWORD,
2967          * both work fine.
2968          */
2969 # if ENABLE_ASH_ALIAS
2970         static const uint8_t syntax_index_table[] ALIGN1 = {
2971                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2972                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2973                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2974                 11, 3                           /* "}~" */
2975         };
2976 # else
2977         static const uint8_t syntax_index_table[] ALIGN1 = {
2978                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2979                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2980                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2981                 10, 2                           /* "}~" */
2982         };
2983 # endif
2984         const char *s;
2985         int indx;
2986
2987         if (c == PEOF)
2988                 return CENDFILE;
2989 # if ENABLE_ASH_ALIAS
2990         if (c == PEOA)
2991                 indx = 0;
2992         else
2993 # endif
2994         {
2995                 /* Cast is purely for paranoia here,
2996                  * just in case someone passed signed char to us */
2997                 if ((unsigned char)c >= CTL_FIRST
2998                  && (unsigned char)c <= CTL_LAST
2999                 ) {
3000                         return CCTL;
3001                 }
3002                 s = strchrnul(spec_symbls, c);
3003                 if (*s == '\0')
3004                         return CWORD;
3005                 indx = syntax_index_table[s - spec_symbls];
3006         }
3007         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3008 }
3009
3010 #else   /* !USE_SIT_FUNCTION */
3011
3012 static const uint8_t syntax_index_table[] ALIGN1 = {
3013         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3014         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3015         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3016         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3017         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3018         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3019         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3020         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3021         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3022         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3023         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3024         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3025         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3029         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3030         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3031         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3032         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3033         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3034         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3035         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3036         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3037         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3038         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3039         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3040         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3041         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3042         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3043         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3044         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3045         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3046         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3047         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3048         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3049         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3050         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3051         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3053         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3054         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3055         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3056         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3057         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3059         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3060         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3061 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3062         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3063         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3064         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3065         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3066         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3067         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3074         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3075         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3076         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3077         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3078         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3079         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3089         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3090         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3092         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3094         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3095         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3096         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3097         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3100         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3102         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3103         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3104         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3105         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3106         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3107         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3108         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3109         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3112         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3122         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3123         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3124         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3125         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3126         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3127         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3128         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3129         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3130         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3131         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3132         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3133         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3134         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3135         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3136         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3137         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3138         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3139         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3140         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3141         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3142         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3143         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3144         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3145         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3146         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3147         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3148         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3149         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3150         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3151         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3152         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3271         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3272 # if ENABLE_ASH_ALIAS
3273         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3274 # endif
3275 };
3276
3277 #if 1
3278 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3279 #else /* debug version, caught one signed char bug */
3280 # define SIT(c, syntax) \
3281         ({ \
3282                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3283                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3284                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3285                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3286                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3287         })
3288 #endif
3289
3290 #endif  /* !USE_SIT_FUNCTION */
3291
3292
3293 /* ============ Alias handling */
3294
3295 #if ENABLE_ASH_ALIAS
3296
3297 #define ALIASINUSE 1
3298 #define ALIASDEAD  2
3299
3300 struct alias {
3301         struct alias *next;
3302         char *name;
3303         char *val;
3304         int flag;
3305 };
3306
3307
3308 static struct alias **atab; // [ATABSIZE];
3309 #define INIT_G_alias() do { \
3310         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3311 } while (0)
3312
3313
3314 static struct alias **
3315 __lookupalias(const char *name)
3316 {
3317         unsigned int hashval;
3318         struct alias **app;
3319         const char *p;
3320         unsigned int ch;
3321
3322         p = name;
3323
3324         ch = (unsigned char)*p;
3325         hashval = ch << 4;
3326         while (ch) {
3327                 hashval += ch;
3328                 ch = (unsigned char)*++p;
3329         }
3330         app = &atab[hashval % ATABSIZE];
3331
3332         for (; *app; app = &(*app)->next) {
3333                 if (strcmp(name, (*app)->name) == 0) {
3334                         break;
3335                 }
3336         }
3337
3338         return app;
3339 }
3340
3341 static struct alias *
3342 lookupalias(const char *name, int check)
3343 {
3344         struct alias *ap = *__lookupalias(name);
3345
3346         if (check && ap && (ap->flag & ALIASINUSE))
3347                 return NULL;
3348         return ap;
3349 }
3350
3351 static struct alias *
3352 freealias(struct alias *ap)
3353 {
3354         struct alias *next;
3355
3356         if (ap->flag & ALIASINUSE) {
3357                 ap->flag |= ALIASDEAD;
3358                 return ap;
3359         }
3360
3361         next = ap->next;
3362         free(ap->name);
3363         free(ap->val);
3364         free(ap);
3365         return next;
3366 }
3367
3368 static void
3369 setalias(const char *name, const char *val)
3370 {
3371         struct alias *ap, **app;
3372
3373         app = __lookupalias(name);
3374         ap = *app;
3375         INT_OFF;
3376         if (ap) {
3377                 if (!(ap->flag & ALIASINUSE)) {
3378                         free(ap->val);
3379                 }
3380                 ap->val = ckstrdup(val);
3381                 ap->flag &= ~ALIASDEAD;
3382         } else {
3383                 /* not found */
3384                 ap = ckzalloc(sizeof(struct alias));
3385                 ap->name = ckstrdup(name);
3386                 ap->val = ckstrdup(val);
3387                 /*ap->flag = 0; - ckzalloc did it */
3388                 /*ap->next = NULL;*/
3389                 *app = ap;
3390         }
3391         INT_ON;
3392 }
3393
3394 static int
3395 unalias(const char *name)
3396 {
3397         struct alias **app;
3398
3399         app = __lookupalias(name);
3400
3401         if (*app) {
3402                 INT_OFF;
3403                 *app = freealias(*app);
3404                 INT_ON;
3405                 return 0;
3406         }
3407
3408         return 1;
3409 }
3410
3411 static void
3412 rmaliases(void)
3413 {
3414         struct alias *ap, **app;
3415         int i;
3416
3417         INT_OFF;
3418         for (i = 0; i < ATABSIZE; i++) {
3419                 app = &atab[i];
3420                 for (ap = *app; ap; ap = *app) {
3421                         *app = freealias(*app);
3422                         if (ap == *app) {
3423                                 app = &ap->next;
3424                         }
3425                 }
3426         }
3427         INT_ON;
3428 }
3429
3430 static void
3431 printalias(const struct alias *ap)
3432 {
3433         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3434 }
3435
3436 /*
3437  * TODO - sort output
3438  */
3439 static int FAST_FUNC
3440 aliascmd(int argc UNUSED_PARAM, char **argv)
3441 {
3442         char *n, *v;
3443         int ret = 0;
3444         struct alias *ap;
3445
3446         if (!argv[1]) {
3447                 int i;
3448
3449                 for (i = 0; i < ATABSIZE; i++) {
3450                         for (ap = atab[i]; ap; ap = ap->next) {
3451                                 printalias(ap);
3452                         }
3453                 }
3454                 return 0;
3455         }
3456         while ((n = *++argv) != NULL) {
3457                 v = strchr(n+1, '=');
3458                 if (v == NULL) { /* n+1: funny ksh stuff */
3459                         ap = *__lookupalias(n);
3460                         if (ap == NULL) {
3461                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3462                                 ret = 1;
3463                         } else
3464                                 printalias(ap);
3465                 } else {
3466                         *v++ = '\0';
3467                         setalias(n, v);
3468                 }
3469         }
3470
3471         return ret;
3472 }
3473
3474 static int FAST_FUNC
3475 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3476 {
3477         int i;
3478
3479         while (nextopt("a") != '\0') {
3480                 rmaliases();
3481                 return 0;
3482         }
3483         for (i = 0; *argptr; argptr++) {
3484                 if (unalias(*argptr)) {
3485                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3486                         i = 1;
3487                 }
3488         }
3489
3490         return i;
3491 }
3492
3493 #endif /* ASH_ALIAS */
3494
3495
3496 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3497 #define FORK_FG    0
3498 #define FORK_BG    1
3499 #define FORK_NOJOB 2
3500
3501 /* mode flags for showjob(s) */
3502 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3503 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3504 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3505 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3506
3507 /*
3508  * A job structure contains information about a job.  A job is either a
3509  * single process or a set of processes contained in a pipeline.  In the
3510  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3511  * array of pids.
3512  */
3513 struct procstat {
3514         pid_t   ps_pid;         /* process id */
3515         int     ps_status;      /* last process status from wait() */
3516         char    *ps_cmd;        /* text of command being run */
3517 };
3518
3519 struct job {
3520         struct procstat ps0;    /* status of process */
3521         struct procstat *ps;    /* status or processes when more than one */
3522 #if JOBS
3523         int stopstatus;         /* status of a stopped job */
3524 #endif
3525         unsigned nprocs;        /* number of processes */
3526
3527 #define JOBRUNNING      0       /* at least one proc running */
3528 #define JOBSTOPPED      1       /* all procs are stopped */
3529 #define JOBDONE         2       /* all procs are completed */
3530         unsigned
3531                 state: 8,
3532 #if JOBS
3533                 sigint: 1,      /* job was killed by SIGINT */
3534                 jobctl: 1,      /* job running under job control */
3535 #endif
3536                 waited: 1,      /* true if this entry has been waited for */
3537                 used: 1,        /* true if this entry is in used */
3538                 changed: 1;     /* true if status has changed */
3539         struct job *prev_job;   /* previous job */
3540 };
3541
3542 static struct job *makejob(/*union node *,*/ int);
3543 static int forkshell(struct job *, union node *, int);
3544 static int waitforjob(struct job *);
3545
3546 #if !JOBS
3547 enum { doing_jobctl = 0 };
3548 #define setjobctl(on) do {} while (0)
3549 #else
3550 static smallint doing_jobctl; //references:8
3551 static void setjobctl(int);
3552 #endif
3553
3554 /*
3555  * Ignore a signal.
3556  */
3557 static void
3558 ignoresig(int signo)
3559 {
3560         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3561         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3562                 /* No, need to do it */
3563                 signal(signo, SIG_IGN);
3564         }
3565         sigmode[signo - 1] = S_HARD_IGN;
3566 }
3567
3568 /*
3569  * Only one usage site - in setsignal()
3570  */
3571 static void
3572 signal_handler(int signo)
3573 {
3574         if (signo == SIGCHLD) {
3575                 got_sigchld = 1;
3576                 if (!trap[SIGCHLD])
3577                         return;
3578         }
3579
3580         gotsig[signo - 1] = 1;
3581         pending_sig = signo;
3582
3583         if (signo == SIGINT && !trap[SIGINT]) {
3584                 if (!suppress_int) {
3585                         pending_sig = 0;
3586                         raise_interrupt(); /* does not return */
3587                 }
3588                 pending_int = 1;
3589         }
3590 }
3591
3592 /*
3593  * Set the signal handler for the specified signal.  The routine figures
3594  * out what it should be set to.
3595  */
3596 static void
3597 setsignal(int signo)
3598 {
3599         char *t;
3600         char cur_act, new_act;
3601         struct sigaction act;
3602
3603         t = trap[signo];
3604         new_act = S_DFL;
3605         if (t != NULL) { /* trap for this sig is set */
3606                 new_act = S_CATCH;
3607                 if (t[0] == '\0') /* trap is "": ignore this sig */
3608                         new_act = S_IGN;
3609         }
3610
3611         if (rootshell && new_act == S_DFL) {
3612                 switch (signo) {
3613                 case SIGINT:
3614                         if (iflag || minusc || sflag == 0)
3615                                 new_act = S_CATCH;
3616                         break;
3617                 case SIGQUIT:
3618 #if DEBUG
3619                         if (debug)
3620                                 break;
3621 #endif
3622                         /* man bash:
3623                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3624                          * commands run by bash have signal handlers
3625                          * set to the values inherited by the shell
3626                          * from its parent". */
3627                         new_act = S_IGN;
3628                         break;
3629                 case SIGTERM:
3630                         if (iflag)
3631                                 new_act = S_IGN;
3632                         break;
3633 #if JOBS
3634                 case SIGTSTP:
3635                 case SIGTTOU:
3636                         if (mflag)
3637                                 new_act = S_IGN;
3638                         break;
3639 #endif
3640                 }
3641         }
3642         /* if !rootshell, we reset SIGQUIT to DFL,
3643          * whereas we have to restore it to what shell got on entry.
3644          * This is handled by the fact that if signal was IGNored on entry,
3645          * then cur_act is S_HARD_IGN and we never change its sigaction
3646          * (see code below).
3647          */
3648
3649         if (signo == SIGCHLD)
3650                 new_act = S_CATCH;
3651
3652         t = &sigmode[signo - 1];
3653         cur_act = *t;
3654         if (cur_act == 0) {
3655                 /* current setting is not yet known */
3656                 if (sigaction(signo, NULL, &act)) {
3657                         /* pretend it worked; maybe we should give a warning,
3658                          * but other shells don't. We don't alter sigmode,
3659                          * so we retry every time.
3660                          * btw, in Linux it never fails. --vda */
3661                         return;
3662                 }
3663                 if (act.sa_handler == SIG_IGN) {
3664                         cur_act = S_HARD_IGN;
3665                         if (mflag
3666                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3667                         ) {
3668                                 cur_act = S_IGN;   /* don't hard ignore these */
3669                         }
3670                 }
3671                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3672                         /* installing SIG_DFL over SIG_DFL is a no-op */
3673                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3674                         *t = S_DFL;
3675                         return;
3676                 }
3677         }
3678         if (cur_act == S_HARD_IGN || cur_act == new_act)
3679                 return;
3680
3681         *t = new_act;
3682
3683         act.sa_handler = SIG_DFL;
3684         switch (new_act) {
3685         case S_CATCH:
3686                 act.sa_handler = signal_handler;
3687                 break;
3688         case S_IGN:
3689                 act.sa_handler = SIG_IGN;
3690                 break;
3691         }
3692         /* flags and mask matter only if !DFL and !IGN, but we do it
3693          * for all cases for more deterministic behavior:
3694          */
3695         act.sa_flags = 0; //TODO: why not SA_RESTART?
3696         sigfillset(&act.sa_mask);
3697
3698         sigaction_set(signo, &act);
3699 }
3700
3701 /* mode flags for set_curjob */
3702 #define CUR_DELETE 2
3703 #define CUR_RUNNING 1
3704 #define CUR_STOPPED 0
3705
3706 #if JOBS
3707 /* pgrp of shell on invocation */
3708 static int initialpgrp; //references:2
3709 static int ttyfd = -1; //5
3710 #endif
3711 /* array of jobs */
3712 static struct job *jobtab; //5
3713 /* size of array */
3714 static unsigned njobs; //4
3715 /* current job */
3716 static struct job *curjob; //lots
3717 /* number of presumed living untracked jobs */
3718 static int jobless; //4
3719
3720 #if 0
3721 /* Bash has a feature: it restores termios after a successful wait for
3722  * a foreground job which had at least one stopped or sigkilled member.
3723  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3724  * properly restoring tty state. Should we do this too?
3725  * A reproducer: ^Z an interactive python:
3726  *
3727  * # python
3728  * Python 2.7.12 (...)
3729  * >>> ^Z
3730  *      { python leaves tty in -icanon -echo state. We do survive that... }
3731  *  [1]+  Stopped                    python
3732  *      { ...however, next program (python #2) does not survive it well: }
3733  * # python
3734  * Python 2.7.12 (...)
3735  * >>> Traceback (most recent call last):
3736  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3737  *   File "<stdin>", line 1, in <module>
3738  * NameError: name 'qwerty' is not defined
3739  *
3740  * The implementation below is modeled on bash code and seems to work.
3741  * However, I'm not sure we should do this. For one: what if I'd fg
3742  * the stopped python instead? It'll be confused by "restored" tty state.
3743  */
3744 static struct termios shell_tty_info;
3745 static void
3746 get_tty_state(void)
3747 {
3748         if (rootshell && ttyfd >= 0)
3749                 tcgetattr(ttyfd, &shell_tty_info);
3750 }
3751 static void
3752 set_tty_state(void)
3753 {
3754         /* if (rootshell) - caller ensures this */
3755         if (ttyfd >= 0)
3756                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3757 }
3758 static int
3759 job_signal_status(struct job *jp)
3760 {
3761         int status;
3762         unsigned i;
3763         struct procstat *ps = jp->ps;
3764         for (i = 0; i < jp->nprocs; i++) {
3765                 status = ps[i].ps_status;
3766                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3767                         return status;
3768         }
3769         return 0;
3770 }
3771 static void
3772 restore_tty_if_stopped_or_signaled(struct job *jp)
3773 {
3774 //TODO: check what happens if we come from waitforjob() in expbackq()
3775         if (rootshell) {
3776                 int s = job_signal_status(jp);
3777                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3778                         set_tty_state();
3779         }
3780 }
3781 #else
3782 # define get_tty_state() ((void)0)
3783 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3784 #endif
3785
3786 static void
3787 set_curjob(struct job *jp, unsigned mode)
3788 {
3789         struct job *jp1;
3790         struct job **jpp, **curp;
3791
3792         /* first remove from list */
3793         jpp = curp = &curjob;
3794         while (1) {
3795                 jp1 = *jpp;
3796                 if (jp1 == jp)
3797                         break;
3798                 jpp = &jp1->prev_job;
3799         }
3800         *jpp = jp1->prev_job;
3801
3802         /* Then re-insert in correct position */
3803         jpp = curp;
3804         switch (mode) {
3805         default:
3806 #if DEBUG
3807                 abort();
3808 #endif
3809         case CUR_DELETE:
3810                 /* job being deleted */
3811                 break;
3812         case CUR_RUNNING:
3813                 /* newly created job or backgrounded job,
3814                  * put after all stopped jobs.
3815                  */
3816                 while (1) {
3817                         jp1 = *jpp;
3818 #if JOBS
3819                         if (!jp1 || jp1->state != JOBSTOPPED)
3820 #endif
3821                                 break;
3822                         jpp = &jp1->prev_job;
3823                 }
3824                 /* FALLTHROUGH */
3825 #if JOBS
3826         case CUR_STOPPED:
3827 #endif
3828                 /* newly stopped job - becomes curjob */
3829                 jp->prev_job = *jpp;
3830                 *jpp = jp;
3831                 break;
3832         }
3833 }
3834
3835 #if JOBS || DEBUG
3836 static int
3837 jobno(const struct job *jp)
3838 {
3839         return jp - jobtab + 1;
3840 }
3841 #endif
3842
3843 /*
3844  * Convert a job name to a job structure.
3845  */
3846 #if !JOBS
3847 #define getjob(name, getctl) getjob(name)
3848 #endif
3849 static struct job *
3850 getjob(const char *name, int getctl)
3851 {
3852         struct job *jp;
3853         struct job *found;
3854         const char *err_msg = "%s: no such job";
3855         unsigned num;
3856         int c;
3857         const char *p;
3858         char *(*match)(const char *, const char *);
3859
3860         jp = curjob;
3861         p = name;
3862         if (!p)
3863                 goto currentjob;
3864
3865         if (*p != '%')
3866                 goto err;
3867
3868         c = *++p;
3869         if (!c)
3870                 goto currentjob;
3871
3872         if (!p[1]) {
3873                 if (c == '+' || c == '%') {
3874  currentjob:
3875                         err_msg = "No current job";
3876                         goto check;
3877                 }
3878                 if (c == '-') {
3879                         if (jp)
3880                                 jp = jp->prev_job;
3881                         err_msg = "No previous job";
3882  check:
3883                         if (!jp)
3884                                 goto err;
3885                         goto gotit;
3886                 }
3887         }
3888
3889         if (is_number(p)) {
3890                 num = atoi(p);
3891                 if (num > 0 && num <= njobs) {
3892                         jp = jobtab + num - 1;
3893                         if (jp->used)
3894                                 goto gotit;
3895                         goto err;
3896                 }
3897         }
3898
3899         match = prefix;
3900         if (*p == '?') {
3901                 match = strstr;
3902                 p++;
3903         }
3904
3905         found = NULL;
3906         while (jp) {
3907                 if (match(jp->ps[0].ps_cmd, p)) {
3908                         if (found)
3909                                 goto err;
3910                         found = jp;
3911                         err_msg = "%s: ambiguous";
3912                 }
3913                 jp = jp->prev_job;
3914         }
3915         if (!found)
3916                 goto err;
3917         jp = found;
3918
3919  gotit:
3920 #if JOBS
3921         err_msg = "job %s not created under job control";
3922         if (getctl && jp->jobctl == 0)
3923                 goto err;
3924 #endif
3925         return jp;
3926  err:
3927         ash_msg_and_raise_error(err_msg, name);
3928 }
3929
3930 /*
3931  * Mark a job structure as unused.
3932  */
3933 static void
3934 freejob(struct job *jp)
3935 {
3936         struct procstat *ps;
3937         int i;
3938
3939         INT_OFF;
3940         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3941                 if (ps->ps_cmd != nullstr)
3942                         free(ps->ps_cmd);
3943         }
3944         if (jp->ps != &jp->ps0)
3945                 free(jp->ps);
3946         jp->used = 0;
3947         set_curjob(jp, CUR_DELETE);
3948         INT_ON;
3949 }
3950
3951 #if JOBS
3952 static void
3953 xtcsetpgrp(int fd, pid_t pgrp)
3954 {
3955         if (tcsetpgrp(fd, pgrp))
3956                 ash_msg_and_raise_perror("can't set tty process group");
3957 }
3958
3959 /*
3960  * Turn job control on and off.
3961  *
3962  * Note:  This code assumes that the third arg to ioctl is a character
3963  * pointer, which is true on Berkeley systems but not System V.  Since
3964  * System V doesn't have job control yet, this isn't a problem now.
3965  *
3966  * Called with interrupts off.
3967  */
3968 static void
3969 setjobctl(int on)
3970 {
3971         int fd;
3972         int pgrp;
3973
3974         if (on == doing_jobctl || rootshell == 0)
3975                 return;
3976         if (on) {
3977                 int ofd;
3978                 ofd = fd = open(_PATH_TTY, O_RDWR);
3979                 if (fd < 0) {
3980         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3981          * That sometimes helps to acquire controlling tty.
3982          * Obviously, a workaround for bugs when someone
3983          * failed to provide a controlling tty to bash! :) */
3984                         fd = 2;
3985                         while (!isatty(fd))
3986                                 if (--fd < 0)
3987                                         goto out;
3988                 }
3989                 /* fd is a tty at this point */
3990                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
3991                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3992                         close(ofd);
3993                 if (fd < 0)
3994                         goto out; /* F_DUPFD failed */
3995                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
3996                         close_on_exec_on(fd);
3997                 while (1) { /* while we are in the background */
3998                         pgrp = tcgetpgrp(fd);
3999                         if (pgrp < 0) {
4000  out:
4001                                 ash_msg("can't access tty; job control turned off");
4002                                 mflag = on = 0;
4003                                 goto close;
4004                         }
4005                         if (pgrp == getpgrp())
4006                                 break;
4007                         killpg(0, SIGTTIN);
4008                 }
4009                 initialpgrp = pgrp;
4010
4011                 setsignal(SIGTSTP);
4012                 setsignal(SIGTTOU);
4013                 setsignal(SIGTTIN);
4014                 pgrp = rootpid;
4015                 setpgid(0, pgrp);
4016                 xtcsetpgrp(fd, pgrp);
4017         } else {
4018                 /* turning job control off */
4019                 fd = ttyfd;
4020                 pgrp = initialpgrp;
4021                 /* was xtcsetpgrp, but this can make exiting ash
4022                  * loop forever if pty is already deleted */
4023                 tcsetpgrp(fd, pgrp);
4024                 setpgid(0, pgrp);
4025                 setsignal(SIGTSTP);
4026                 setsignal(SIGTTOU);
4027                 setsignal(SIGTTIN);
4028  close:
4029                 if (fd >= 0)
4030                         close(fd);
4031                 fd = -1;
4032         }
4033         ttyfd = fd;
4034         doing_jobctl = on;
4035 }
4036
4037 static int FAST_FUNC
4038 killcmd(int argc, char **argv)
4039 {
4040         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4041                 int i = 1;
4042                 do {
4043                         if (argv[i][0] == '%') {
4044                                 /*
4045                                  * "kill %N" - job kill
4046                                  * Converting to pgrp / pid kill
4047                                  */
4048                                 struct job *jp;
4049                                 char *dst;
4050                                 int j, n;
4051
4052                                 jp = getjob(argv[i], 0);
4053                                 /*
4054                                  * In jobs started under job control, we signal
4055                                  * entire process group by kill -PGRP_ID.
4056                                  * This happens, f.e., in interactive shell.
4057                                  *
4058                                  * Otherwise, we signal each child via
4059                                  * kill PID1 PID2 PID3.
4060                                  * Testcases:
4061                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4062                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4063                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4064                                  */
4065                                 n = jp->nprocs; /* can't be 0 (I hope) */
4066                                 if (jp->jobctl)
4067                                         n = 1;
4068                                 dst = alloca(n * sizeof(int)*4);
4069                                 argv[i] = dst;
4070                                 for (j = 0; j < n; j++) {
4071                                         struct procstat *ps = &jp->ps[j];
4072                                         /* Skip non-running and not-stopped members
4073                                          * (i.e. dead members) of the job
4074                                          */
4075                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4076                                                 continue;
4077                                         /*
4078                                          * kill_main has matching code to expect
4079                                          * leading space. Needed to not confuse
4080                                          * negative pids with "kill -SIGNAL_NO" syntax
4081                                          */
4082                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4083                                 }
4084                                 *dst = '\0';
4085                         }
4086                 } while (argv[++i]);
4087         }
4088         return kill_main(argc, argv);
4089 }
4090
4091 static void
4092 showpipe(struct job *jp /*, FILE *out*/)
4093 {
4094         struct procstat *ps;
4095         struct procstat *psend;
4096
4097         psend = jp->ps + jp->nprocs;
4098         for (ps = jp->ps + 1; ps < psend; ps++)
4099                 printf(" | %s", ps->ps_cmd);
4100         newline_and_flush(stdout);
4101         flush_stdout_stderr();
4102 }
4103
4104
4105 static int
4106 restartjob(struct job *jp, int mode)
4107 {
4108         struct procstat *ps;
4109         int i;
4110         int status;
4111         pid_t pgid;
4112
4113         INT_OFF;
4114         if (jp->state == JOBDONE)
4115                 goto out;
4116         jp->state = JOBRUNNING;
4117         pgid = jp->ps[0].ps_pid;
4118         if (mode == FORK_FG) {
4119                 get_tty_state();
4120                 xtcsetpgrp(ttyfd, pgid);
4121         }
4122         killpg(pgid, SIGCONT);
4123         ps = jp->ps;
4124         i = jp->nprocs;
4125         do {
4126                 if (WIFSTOPPED(ps->ps_status)) {
4127                         ps->ps_status = -1;
4128                 }
4129                 ps++;
4130         } while (--i);
4131  out:
4132         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4133         INT_ON;
4134         return status;
4135 }
4136
4137 static int FAST_FUNC
4138 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4139 {
4140         struct job *jp;
4141         int mode;
4142         int retval;
4143
4144         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4145         nextopt(nullstr);
4146         argv = argptr;
4147         do {
4148                 jp = getjob(*argv, 1);
4149                 if (mode == FORK_BG) {
4150                         set_curjob(jp, CUR_RUNNING);
4151                         printf("[%d] ", jobno(jp));
4152                 }
4153                 out1str(jp->ps[0].ps_cmd);
4154                 showpipe(jp /*, stdout*/);
4155                 retval = restartjob(jp, mode);
4156         } while (*argv && *++argv);
4157         return retval;
4158 }
4159 #endif
4160
4161 static int
4162 sprint_status48(char *s, int status, int sigonly)
4163 {
4164         int col;
4165         int st;
4166
4167         col = 0;
4168         if (!WIFEXITED(status)) {
4169 #if JOBS
4170                 if (WIFSTOPPED(status))
4171                         st = WSTOPSIG(status);
4172                 else
4173 #endif
4174                         st = WTERMSIG(status);
4175                 if (sigonly) {
4176                         if (st == SIGINT || st == SIGPIPE)
4177                                 goto out;
4178 #if JOBS
4179                         if (WIFSTOPPED(status))
4180                                 goto out;
4181 #endif
4182                 }
4183                 st &= 0x7f;
4184 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4185                 col = fmtstr(s, 32, strsignal(st));
4186                 if (WCOREDUMP(status)) {
4187                         strcpy(s + col, " (core dumped)");
4188                         col += sizeof(" (core dumped)")-1;
4189                 }
4190         } else if (!sigonly) {
4191                 st = WEXITSTATUS(status);
4192                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4193         }
4194  out:
4195         return col;
4196 }
4197
4198 static int
4199 wait_block_or_sig(int *status)
4200 {
4201         int pid;
4202
4203         do {
4204                 sigset_t mask;
4205
4206                 /* Poll all children for changes in their state */
4207                 got_sigchld = 0;
4208                 /* if job control is active, accept stopped processes too */
4209                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4210                 if (pid != 0)
4211                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4212
4213                 /* Children exist, but none are ready. Sleep until interesting signal */
4214 #if 1
4215                 sigfillset(&mask);
4216                 sigprocmask(SIG_SETMASK, &mask, &mask);
4217                 while (!got_sigchld && !pending_sig)
4218                         sigsuspend(&mask);
4219                 sigprocmask(SIG_SETMASK, &mask, NULL);
4220 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4221                 while (!got_sigchld && !pending_sig)
4222                         pause();
4223 #endif
4224
4225                 /* If it was SIGCHLD, poll children again */
4226         } while (got_sigchld);
4227
4228         return pid;
4229 }
4230
4231 #define DOWAIT_NONBLOCK 0
4232 #define DOWAIT_BLOCK    1
4233 #define DOWAIT_BLOCK_OR_SIG 2
4234
4235 static int
4236 dowait(int block, struct job *job)
4237 {
4238         int pid;
4239         int status;
4240         struct job *jp;
4241         struct job *thisjob = NULL;
4242
4243         TRACE(("dowait(0x%x) called\n", block));
4244
4245         /* It's wrong to call waitpid() outside of INT_OFF region:
4246          * signal can arrive just after syscall return and handler can
4247          * longjmp away, losing stop/exit notification processing.
4248          * Thus, for "jobs" builtin, and for waiting for a fg job,
4249          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4250          *
4251          * However, for "wait" builtin it is wrong to simply call waitpid()
4252          * in INT_OFF region: "wait" needs to wait for any running job
4253          * to change state, but should exit on any trap too.
4254          * In INT_OFF region, a signal just before syscall entry can set
4255          * pending_sig variables, but we can't check them, and we would
4256          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4257          *
4258          * Because of this, we run inside INT_OFF, but use a special routine
4259          * which combines waitpid() and sigsuspend().
4260          * This is the reason why we need to have a handler for SIGCHLD:
4261          * SIG_DFL handler does not wake sigsuspend().
4262          */
4263         INT_OFF;
4264         if (block == DOWAIT_BLOCK_OR_SIG) {
4265                 pid = wait_block_or_sig(&status);
4266         } else {
4267                 int wait_flags = 0;
4268                 if (block == DOWAIT_NONBLOCK)
4269                         wait_flags = WNOHANG;
4270                 /* if job control is active, accept stopped processes too */
4271                 if (doing_jobctl)
4272                         wait_flags |= WUNTRACED;
4273                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4274                 pid = waitpid(-1, &status, wait_flags);
4275         }
4276         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4277                                 pid, status, errno, strerror(errno)));
4278         if (pid <= 0)
4279                 goto out;
4280
4281         thisjob = NULL;
4282         for (jp = curjob; jp; jp = jp->prev_job) {
4283                 int jobstate;
4284                 struct procstat *ps;
4285                 struct procstat *psend;
4286                 if (jp->state == JOBDONE)
4287                         continue;
4288                 jobstate = JOBDONE;
4289                 ps = jp->ps;
4290                 psend = ps + jp->nprocs;
4291                 do {
4292                         if (ps->ps_pid == pid) {
4293                                 TRACE(("Job %d: changing status of proc %d "
4294                                         "from 0x%x to 0x%x\n",
4295                                         jobno(jp), pid, ps->ps_status, status));
4296                                 ps->ps_status = status;
4297                                 thisjob = jp;
4298                         }
4299                         if (ps->ps_status == -1)
4300                                 jobstate = JOBRUNNING;
4301 #if JOBS
4302                         if (jobstate == JOBRUNNING)
4303                                 continue;
4304                         if (WIFSTOPPED(ps->ps_status)) {
4305                                 jp->stopstatus = ps->ps_status;
4306                                 jobstate = JOBSTOPPED;
4307                         }
4308 #endif
4309                 } while (++ps < psend);
4310                 if (!thisjob)
4311                         continue;
4312
4313                 /* Found the job where one of its processes changed its state.
4314                  * Is there at least one live and running process in this job? */
4315                 if (jobstate != JOBRUNNING) {
4316                         /* No. All live processes in the job are stopped
4317                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4318                          */
4319                         thisjob->changed = 1;
4320                         if (thisjob->state != jobstate) {
4321                                 TRACE(("Job %d: changing state from %d to %d\n",
4322                                         jobno(thisjob), thisjob->state, jobstate));
4323                                 thisjob->state = jobstate;
4324 #if JOBS
4325                                 if (jobstate == JOBSTOPPED)
4326                                         set_curjob(thisjob, CUR_STOPPED);
4327 #endif
4328                         }
4329                 }
4330                 goto out;
4331         }
4332         /* The process wasn't found in job list */
4333 #if JOBS
4334         if (!WIFSTOPPED(status))
4335                 jobless--;
4336 #endif
4337  out:
4338         INT_ON;
4339
4340         if (thisjob && thisjob == job) {
4341                 char s[48 + 1];
4342                 int len;
4343
4344                 len = sprint_status48(s, status, 1);
4345                 if (len) {
4346                         s[len] = '\n';
4347                         s[len + 1] = '\0';
4348                         out2str(s);
4349                 }
4350         }
4351         return pid;
4352 }
4353
4354 #if JOBS
4355 static void
4356 showjob(struct job *jp, int mode)
4357 {
4358         struct procstat *ps;
4359         struct procstat *psend;
4360         int col;
4361         int indent_col;
4362         char s[16 + 16 + 48];
4363         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4364
4365         ps = jp->ps;
4366
4367         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4368                 /* just output process (group) id of pipeline */
4369                 fprintf(out, "%d\n", ps->ps_pid);
4370                 return;
4371         }
4372
4373         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4374         indent_col = col;
4375
4376         if (jp == curjob)
4377                 s[col - 3] = '+';
4378         else if (curjob && jp == curjob->prev_job)
4379                 s[col - 3] = '-';
4380
4381         if (mode & SHOW_PIDS)
4382                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4383
4384         psend = ps + jp->nprocs;
4385
4386         if (jp->state == JOBRUNNING) {
4387                 strcpy(s + col, "Running");
4388                 col += sizeof("Running") - 1;
4389         } else {
4390                 int status = psend[-1].ps_status;
4391                 if (jp->state == JOBSTOPPED)
4392                         status = jp->stopstatus;
4393                 col += sprint_status48(s + col, status, 0);
4394         }
4395         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4396
4397         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4398          * or prints several "PID             | <cmdN>" lines,
4399          * depending on SHOW_PIDS bit.
4400          * We do not print status of individual processes
4401          * between PID and <cmdN>. bash does it, but not very well:
4402          * first line shows overall job status, not process status,
4403          * making it impossible to know 1st process status.
4404          */
4405         goto start;
4406         do {
4407                 /* for each process */
4408                 s[0] = '\0';
4409                 col = 33;
4410                 if (mode & SHOW_PIDS)
4411                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4412  start:
4413                 fprintf(out, "%s%*c%s%s",
4414                                 s,
4415                                 33 - col >= 0 ? 33 - col : 0, ' ',
4416                                 ps == jp->ps ? "" : "| ",
4417                                 ps->ps_cmd
4418                 );
4419         } while (++ps != psend);
4420         newline_and_flush(out);
4421
4422         jp->changed = 0;
4423
4424         if (jp->state == JOBDONE) {
4425                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4426                 freejob(jp);
4427         }
4428 }
4429
4430 /*
4431  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4432  * statuses have changed since the last call to showjobs.
4433  */
4434 static void
4435 showjobs(int mode)
4436 {
4437         struct job *jp;
4438
4439         TRACE(("showjobs(0x%x) called\n", mode));
4440
4441         /* Handle all finished jobs */
4442         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4443                 continue;
4444
4445         for (jp = curjob; jp; jp = jp->prev_job) {
4446                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4447                         showjob(jp, mode);
4448                 }
4449         }
4450 }
4451
4452 static int FAST_FUNC
4453 jobscmd(int argc UNUSED_PARAM, char **argv)
4454 {
4455         int mode, m;
4456
4457         mode = 0;
4458         while ((m = nextopt("lp")) != '\0') {
4459                 if (m == 'l')
4460                         mode |= SHOW_PIDS;
4461                 else
4462                         mode |= SHOW_ONLY_PGID;
4463         }
4464
4465         argv = argptr;
4466         if (*argv) {
4467                 do
4468                         showjob(getjob(*argv, 0), mode);
4469                 while (*++argv);
4470         } else {
4471                 showjobs(mode);
4472         }
4473
4474         return 0;
4475 }
4476 #endif /* JOBS */
4477
4478 /* Called only on finished or stopped jobs (no members are running) */
4479 static int
4480 getstatus(struct job *job)
4481 {
4482         int status;
4483         int retval;
4484         struct procstat *ps;
4485
4486         /* Fetch last member's status */
4487         ps = job->ps + job->nprocs - 1;
4488         status = ps->ps_status;
4489         if (pipefail) {
4490                 /* "set -o pipefail" mode: use last _nonzero_ status */
4491                 while (status == 0 && --ps >= job->ps)
4492                         status = ps->ps_status;
4493         }
4494
4495         retval = WEXITSTATUS(status);
4496         if (!WIFEXITED(status)) {
4497 #if JOBS
4498                 retval = WSTOPSIG(status);
4499                 if (!WIFSTOPPED(status))
4500 #endif
4501                 {
4502                         /* XXX: limits number of signals */
4503                         retval = WTERMSIG(status);
4504 #if JOBS
4505                         if (retval == SIGINT)
4506                                 job->sigint = 1;
4507 #endif
4508                 }
4509                 retval += 128;
4510         }
4511         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4512                 jobno(job), job->nprocs, status, retval));
4513         return retval;
4514 }
4515
4516 static int FAST_FUNC
4517 waitcmd(int argc UNUSED_PARAM, char **argv)
4518 {
4519         struct job *job;
4520         int retval;
4521         struct job *jp;
4522
4523         nextopt(nullstr);
4524         retval = 0;
4525
4526         argv = argptr;
4527         if (!*argv) {
4528                 /* wait for all jobs */
4529                 for (;;) {
4530                         jp = curjob;
4531                         while (1) {
4532                                 if (!jp) /* no running procs */
4533                                         goto ret;
4534                                 if (jp->state == JOBRUNNING)
4535                                         break;
4536                                 jp->waited = 1;
4537                                 jp = jp->prev_job;
4538                         }
4539         /* man bash:
4540          * "When bash is waiting for an asynchronous command via
4541          * the wait builtin, the reception of a signal for which a trap
4542          * has been set will cause the wait builtin to return immediately
4543          * with an exit status greater than 128, immediately after which
4544          * the trap is executed."
4545          */
4546                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4547         /* if child sends us a signal *and immediately exits*,
4548          * dowait() returns pid > 0. Check this case,
4549          * not "if (dowait() < 0)"!
4550          */
4551                         if (pending_sig)
4552                                 goto sigout;
4553                 }
4554         }
4555
4556         retval = 127;
4557         do {
4558                 if (**argv != '%') {
4559                         pid_t pid = number(*argv);
4560                         job = curjob;
4561                         while (1) {
4562                                 if (!job)
4563                                         goto repeat;
4564                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4565                                         break;
4566                                 job = job->prev_job;
4567                         }
4568                 } else {
4569                         job = getjob(*argv, 0);
4570                 }
4571                 /* loop until process terminated or stopped */
4572                 while (job->state == JOBRUNNING) {
4573                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4574                         if (pending_sig)
4575                                 goto sigout;
4576                 }
4577                 job->waited = 1;
4578                 retval = getstatus(job);
4579  repeat: ;
4580         } while (*++argv);
4581
4582  ret:
4583         return retval;
4584  sigout:
4585         retval = 128 + pending_sig;
4586         return retval;
4587 }
4588
4589 static struct job *
4590 growjobtab(void)
4591 {
4592         size_t len;
4593         ptrdiff_t offset;
4594         struct job *jp, *jq;
4595
4596         len = njobs * sizeof(*jp);
4597         jq = jobtab;
4598         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4599
4600         offset = (char *)jp - (char *)jq;
4601         if (offset) {
4602                 /* Relocate pointers */
4603                 size_t l = len;
4604
4605                 jq = (struct job *)((char *)jq + l);
4606                 while (l) {
4607                         l -= sizeof(*jp);
4608                         jq--;
4609 #define joff(p) ((struct job *)((char *)(p) + l))
4610 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4611                         if (joff(jp)->ps == &jq->ps0)
4612                                 jmove(joff(jp)->ps);
4613                         if (joff(jp)->prev_job)
4614                                 jmove(joff(jp)->prev_job);
4615                 }
4616                 if (curjob)
4617                         jmove(curjob);
4618 #undef joff
4619 #undef jmove
4620         }
4621
4622         njobs += 4;
4623         jobtab = jp;
4624         jp = (struct job *)((char *)jp + len);
4625         jq = jp + 3;
4626         do {
4627                 jq->used = 0;
4628         } while (--jq >= jp);
4629         return jp;
4630 }
4631
4632 /*
4633  * Return a new job structure.
4634  * Called with interrupts off.
4635  */
4636 static struct job *
4637 makejob(/*union node *node,*/ int nprocs)
4638 {
4639         int i;
4640         struct job *jp;
4641
4642         for (i = njobs, jp = jobtab; ; jp++) {
4643                 if (--i < 0) {
4644                         jp = growjobtab();
4645                         break;
4646                 }
4647                 if (jp->used == 0)
4648                         break;
4649                 if (jp->state != JOBDONE || !jp->waited)
4650                         continue;
4651 #if JOBS
4652                 if (doing_jobctl)
4653                         continue;
4654 #endif
4655                 freejob(jp);
4656                 break;
4657         }
4658         memset(jp, 0, sizeof(*jp));
4659 #if JOBS
4660         /* jp->jobctl is a bitfield.
4661          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4662         if (doing_jobctl)
4663                 jp->jobctl = 1;
4664 #endif
4665         jp->prev_job = curjob;
4666         curjob = jp;
4667         jp->used = 1;
4668         jp->ps = &jp->ps0;
4669         if (nprocs > 1) {
4670                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4671         }
4672         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4673                                 jobno(jp)));
4674         return jp;
4675 }
4676
4677 #if JOBS
4678 /*
4679  * Return a string identifying a command (to be printed by the
4680  * jobs command).
4681  */
4682 static char *cmdnextc;
4683
4684 static void
4685 cmdputs(const char *s)
4686 {
4687         static const char vstype[VSTYPE + 1][3] = {
4688                 "", "}", "-", "+", "?", "=",
4689                 "%", "%%", "#", "##"
4690                 IF_BASH_SUBSTR(, ":")
4691                 IF_BASH_PATTERN_SUBST(, "/", "//")
4692         };
4693
4694         const char *p, *str;
4695         char cc[2];
4696         char *nextc;
4697         unsigned char c;
4698         unsigned char subtype = 0;
4699         int quoted = 0;
4700
4701         cc[1] = '\0';
4702         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4703         p = s;
4704         while ((c = *p++) != '\0') {
4705                 str = NULL;
4706                 switch (c) {
4707                 case CTLESC:
4708                         c = *p++;
4709                         break;
4710                 case CTLVAR:
4711                         subtype = *p++;
4712                         if ((subtype & VSTYPE) == VSLENGTH)
4713                                 str = "${#";
4714                         else
4715                                 str = "${";
4716                         goto dostr;
4717                 case CTLENDVAR:
4718                         str = "\"}" + !(quoted & 1);
4719                         quoted >>= 1;
4720                         subtype = 0;
4721                         goto dostr;
4722                 case CTLBACKQ:
4723                         str = "$(...)";
4724                         goto dostr;
4725 #if ENABLE_FEATURE_SH_MATH
4726                 case CTLARI:
4727                         str = "$((";
4728                         goto dostr;
4729                 case CTLENDARI:
4730                         str = "))";
4731                         goto dostr;
4732 #endif
4733                 case CTLQUOTEMARK:
4734                         quoted ^= 1;
4735                         c = '"';
4736                         break;
4737                 case '=':
4738                         if (subtype == 0)
4739                                 break;
4740                         if ((subtype & VSTYPE) != VSNORMAL)
4741                                 quoted <<= 1;
4742                         str = vstype[subtype & VSTYPE];
4743                         if (subtype & VSNUL)
4744                                 c = ':';
4745                         else
4746                                 goto checkstr;
4747                         break;
4748                 case '\'':
4749                 case '\\':
4750                 case '"':
4751                 case '$':
4752                         /* These can only happen inside quotes */
4753                         cc[0] = c;
4754                         str = cc;
4755 //FIXME:
4756 // $ true $$ &
4757 // $ <cr>
4758 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4759                         c = '\\';
4760                         break;
4761                 default:
4762                         break;
4763                 }
4764                 USTPUTC(c, nextc);
4765  checkstr:
4766                 if (!str)
4767                         continue;
4768  dostr:
4769                 while ((c = *str++) != '\0') {
4770                         USTPUTC(c, nextc);
4771                 }
4772         } /* while *p++ not NUL */
4773
4774         if (quoted & 1) {
4775                 USTPUTC('"', nextc);
4776         }
4777         *nextc = 0;
4778         cmdnextc = nextc;
4779 }
4780
4781 /* cmdtxt() and cmdlist() call each other */
4782 static void cmdtxt(union node *n);
4783
4784 static void
4785 cmdlist(union node *np, int sep)
4786 {
4787         for (; np; np = np->narg.next) {
4788                 if (!sep)
4789                         cmdputs(" ");
4790                 cmdtxt(np);
4791                 if (sep && np->narg.next)
4792                         cmdputs(" ");
4793         }
4794 }
4795
4796 static void
4797 cmdtxt(union node *n)
4798 {
4799         union node *np;
4800         struct nodelist *lp;
4801         const char *p;
4802
4803         if (!n)
4804                 return;
4805         switch (n->type) {
4806         default:
4807 #if DEBUG
4808                 abort();
4809 #endif
4810         case NPIPE:
4811                 lp = n->npipe.cmdlist;
4812                 for (;;) {
4813                         cmdtxt(lp->n);
4814                         lp = lp->next;
4815                         if (!lp)
4816                                 break;
4817                         cmdputs(" | ");
4818                 }
4819                 break;
4820         case NSEMI:
4821                 p = "; ";
4822                 goto binop;
4823         case NAND:
4824                 p = " && ";
4825                 goto binop;
4826         case NOR:
4827                 p = " || ";
4828  binop:
4829                 cmdtxt(n->nbinary.ch1);
4830                 cmdputs(p);
4831                 n = n->nbinary.ch2;
4832                 goto donode;
4833         case NREDIR:
4834         case NBACKGND:
4835                 n = n->nredir.n;
4836                 goto donode;
4837         case NNOT:
4838                 cmdputs("!");
4839                 n = n->nnot.com;
4840  donode:
4841                 cmdtxt(n);
4842                 break;
4843         case NIF:
4844                 cmdputs("if ");
4845                 cmdtxt(n->nif.test);
4846                 cmdputs("; then ");
4847                 if (n->nif.elsepart) {
4848                         cmdtxt(n->nif.ifpart);
4849                         cmdputs("; else ");
4850                         n = n->nif.elsepart;
4851                 } else {
4852                         n = n->nif.ifpart;
4853                 }
4854                 p = "; fi";
4855                 goto dotail;
4856         case NSUBSHELL:
4857                 cmdputs("(");
4858                 n = n->nredir.n;
4859                 p = ")";
4860                 goto dotail;
4861         case NWHILE:
4862                 p = "while ";
4863                 goto until;
4864         case NUNTIL:
4865                 p = "until ";
4866  until:
4867                 cmdputs(p);
4868                 cmdtxt(n->nbinary.ch1);
4869                 n = n->nbinary.ch2;
4870                 p = "; done";
4871  dodo:
4872                 cmdputs("; do ");
4873  dotail:
4874                 cmdtxt(n);
4875                 goto dotail2;
4876         case NFOR:
4877                 cmdputs("for ");
4878                 cmdputs(n->nfor.var);
4879                 cmdputs(" in ");
4880                 cmdlist(n->nfor.args, 1);
4881                 n = n->nfor.body;
4882                 p = "; done";
4883                 goto dodo;
4884         case NDEFUN:
4885                 cmdputs(n->ndefun.text);
4886                 p = "() { ... }";
4887                 goto dotail2;
4888         case NCMD:
4889                 cmdlist(n->ncmd.args, 1);
4890                 cmdlist(n->ncmd.redirect, 0);
4891                 break;
4892         case NARG:
4893                 p = n->narg.text;
4894  dotail2:
4895                 cmdputs(p);
4896                 break;
4897         case NHERE:
4898         case NXHERE:
4899                 p = "<<...";
4900                 goto dotail2;
4901         case NCASE:
4902                 cmdputs("case ");
4903                 cmdputs(n->ncase.expr->narg.text);
4904                 cmdputs(" in ");
4905                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4906                         cmdtxt(np->nclist.pattern);
4907                         cmdputs(") ");
4908                         cmdtxt(np->nclist.body);
4909                         cmdputs(";; ");
4910                 }
4911                 p = "esac";
4912                 goto dotail2;
4913         case NTO:
4914                 p = ">";
4915                 goto redir;
4916         case NCLOBBER:
4917                 p = ">|";
4918                 goto redir;
4919         case NAPPEND:
4920                 p = ">>";
4921                 goto redir;
4922 #if BASH_REDIR_OUTPUT
4923         case NTO2:
4924 #endif
4925         case NTOFD:
4926                 p = ">&";
4927                 goto redir;
4928         case NFROM:
4929                 p = "<";
4930                 goto redir;
4931         case NFROMFD:
4932                 p = "<&";
4933                 goto redir;
4934         case NFROMTO:
4935                 p = "<>";
4936  redir:
4937                 cmdputs(utoa(n->nfile.fd));
4938                 cmdputs(p);
4939                 if (n->type == NTOFD || n->type == NFROMFD) {
4940                         if (n->ndup.dupfd >= 0)
4941                                 cmdputs(utoa(n->ndup.dupfd));
4942                         else
4943                                 cmdputs("-");
4944                         break;
4945                 }
4946                 n = n->nfile.fname;
4947                 goto donode;
4948         }
4949 }
4950
4951 static char *
4952 commandtext(union node *n)
4953 {
4954         char *name;
4955
4956         STARTSTACKSTR(cmdnextc);
4957         cmdtxt(n);
4958         name = stackblock();
4959         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4960         return ckstrdup(name);
4961 }
4962 #endif /* JOBS */
4963
4964 /*
4965  * Fork off a subshell.  If we are doing job control, give the subshell its
4966  * own process group.  Jp is a job structure that the job is to be added to.
4967  * N is the command that will be evaluated by the child.  Both jp and n may
4968  * be NULL.  The mode parameter can be one of the following:
4969  *      FORK_FG - Fork off a foreground process.
4970  *      FORK_BG - Fork off a background process.
4971  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4972  *                   process group even if job control is on.
4973  *
4974  * When job control is turned off, background processes have their standard
4975  * input redirected to /dev/null (except for the second and later processes
4976  * in a pipeline).
4977  *
4978  * Called with interrupts off.
4979  */
4980 /*
4981  * Clear traps on a fork.
4982  */
4983 static void
4984 clear_traps(void)
4985 {
4986         char **tp;
4987
4988         INT_OFF;
4989         for (tp = trap; tp < &trap[NSIG]; tp++) {
4990                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4991                         if (trap_ptr == trap)
4992                                 free(*tp);
4993                         /* else: it "belongs" to trap_ptr vector, don't free */
4994                         *tp = NULL;
4995                         if ((tp - trap) != 0)
4996                                 setsignal(tp - trap);
4997                 }
4998         }
4999         may_have_traps = 0;
5000         INT_ON;
5001 }
5002
5003 /* Lives far away from here, needed for forkchild */
5004 static void closescript(void);
5005
5006 /* Called after fork(), in child */
5007 /* jp and n are NULL when called by openhere() for heredoc support */
5008 static NOINLINE void
5009 forkchild(struct job *jp, union node *n, int mode)
5010 {
5011         int oldlvl;
5012
5013         TRACE(("Child shell %d\n", getpid()));
5014         oldlvl = shlvl;
5015         shlvl++;
5016
5017         /* man bash: "Non-builtin commands run by bash have signal handlers
5018          * set to the values inherited by the shell from its parent".
5019          * Do we do it correctly? */
5020
5021         closescript();
5022
5023         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5024          && n && n->type == NCMD        /* is it single cmd? */
5025         /* && n->ncmd.args->type == NARG - always true? */
5026          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5027          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5028         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5029         ) {
5030                 TRACE(("Trap hack\n"));
5031                 /* Awful hack for `trap` or $(trap).
5032                  *
5033                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5034                  * contains an example where "trap" is executed in a subshell:
5035                  *
5036                  * save_traps=$(trap)
5037                  * ...
5038                  * eval "$save_traps"
5039                  *
5040                  * Standard does not say that "trap" in subshell shall print
5041                  * parent shell's traps. It only says that its output
5042                  * must have suitable form, but then, in the above example
5043                  * (which is not supposed to be normative), it implies that.
5044                  *
5045                  * bash (and probably other shell) does implement it
5046                  * (traps are reset to defaults, but "trap" still shows them),
5047                  * but as a result, "trap" logic is hopelessly messed up:
5048                  *
5049                  * # trap
5050                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5051                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5052                  * # true | trap   <--- trap is in subshell - no output (ditto)
5053                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5054                  * trap -- 'echo Ho' SIGWINCH
5055                  * # echo `(trap)`         <--- in subshell in subshell - output
5056                  * trap -- 'echo Ho' SIGWINCH
5057                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5058                  * trap -- 'echo Ho' SIGWINCH
5059                  *
5060                  * The rules when to forget and when to not forget traps
5061                  * get really complex and nonsensical.
5062                  *
5063                  * Our solution: ONLY bare $(trap) or `trap` is special.
5064                  */
5065                 /* Save trap handler strings for trap builtin to print */
5066                 trap_ptr = xmemdup(trap, sizeof(trap));
5067                 /* Fall through into clearing traps */
5068         }
5069         clear_traps();
5070 #if JOBS
5071         /* do job control only in root shell */
5072         doing_jobctl = 0;
5073         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5074                 pid_t pgrp;
5075
5076                 if (jp->nprocs == 0)
5077                         pgrp = getpid();
5078                 else
5079                         pgrp = jp->ps[0].ps_pid;
5080                 /* this can fail because we are doing it in the parent also */
5081                 setpgid(0, pgrp);
5082                 if (mode == FORK_FG)
5083                         xtcsetpgrp(ttyfd, pgrp);
5084                 setsignal(SIGTSTP);
5085                 setsignal(SIGTTOU);
5086         } else
5087 #endif
5088         if (mode == FORK_BG) {
5089                 /* man bash: "When job control is not in effect,
5090                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5091                 ignoresig(SIGINT);
5092                 ignoresig(SIGQUIT);
5093                 if (jp->nprocs == 0) {
5094                         close(0);
5095                         if (open(bb_dev_null, O_RDONLY) != 0)
5096                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5097                 }
5098         }
5099         if (oldlvl == 0) {
5100                 if (iflag) { /* why if iflag only? */
5101                         setsignal(SIGINT);
5102                         setsignal(SIGTERM);
5103                 }
5104                 /* man bash:
5105                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5106                  * commands run by bash have signal handlers
5107                  * set to the values inherited by the shell
5108                  * from its parent".
5109                  * Take care of the second rule: */
5110                 setsignal(SIGQUIT);
5111         }
5112 #if JOBS
5113         if (n && n->type == NCMD
5114          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5115         ) {
5116                 TRACE(("Job hack\n"));
5117                 /* "jobs": we do not want to clear job list for it,
5118                  * instead we remove only _its_ own_ job from job list.
5119                  * This makes "jobs .... | cat" more useful.
5120                  */
5121                 freejob(curjob);
5122                 return;
5123         }
5124 #endif
5125         for (jp = curjob; jp; jp = jp->prev_job)
5126                 freejob(jp);
5127         jobless = 0;
5128 }
5129
5130 /* Called after fork(), in parent */
5131 #if !JOBS
5132 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5133 #endif
5134 static void
5135 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5136 {
5137         TRACE(("In parent shell: child = %d\n", pid));
5138         if (!jp) {
5139                 /* jp is NULL when called by openhere() for heredoc support */
5140                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5141                         continue;
5142                 jobless++;
5143                 return;
5144         }
5145 #if JOBS
5146         if (mode != FORK_NOJOB && jp->jobctl) {
5147                 int pgrp;
5148
5149                 if (jp->nprocs == 0)
5150                         pgrp = pid;
5151                 else
5152                         pgrp = jp->ps[0].ps_pid;
5153                 /* This can fail because we are doing it in the child also */
5154                 setpgid(pid, pgrp);
5155         }
5156 #endif
5157         if (mode == FORK_BG) {
5158                 backgndpid = pid;               /* set $! */
5159                 set_curjob(jp, CUR_RUNNING);
5160         }
5161         if (jp) {
5162                 struct procstat *ps = &jp->ps[jp->nprocs++];
5163                 ps->ps_pid = pid;
5164                 ps->ps_status = -1;
5165                 ps->ps_cmd = nullstr;
5166 #if JOBS
5167                 if (doing_jobctl && n)
5168                         ps->ps_cmd = commandtext(n);
5169 #endif
5170         }
5171 }
5172
5173 /* jp and n are NULL when called by openhere() for heredoc support */
5174 static int
5175 forkshell(struct job *jp, union node *n, int mode)
5176 {
5177         int pid;
5178
5179         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5180         pid = fork();
5181         if (pid < 0) {
5182                 TRACE(("Fork failed, errno=%d", errno));
5183                 if (jp)
5184                         freejob(jp);
5185                 ash_msg_and_raise_perror("can't fork");
5186         }
5187         if (pid == 0) {
5188                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5189                 forkchild(jp, n, mode);
5190         } else {
5191                 forkparent(jp, n, mode, pid);
5192         }
5193         return pid;
5194 }
5195
5196 /*
5197  * Wait for job to finish.
5198  *
5199  * Under job control we have the problem that while a child process
5200  * is running interrupts generated by the user are sent to the child
5201  * but not to the shell.  This means that an infinite loop started by
5202  * an interactive user may be hard to kill.  With job control turned off,
5203  * an interactive user may place an interactive program inside a loop.
5204  * If the interactive program catches interrupts, the user doesn't want
5205  * these interrupts to also abort the loop.  The approach we take here
5206  * is to have the shell ignore interrupt signals while waiting for a
5207  * foreground process to terminate, and then send itself an interrupt
5208  * signal if the child process was terminated by an interrupt signal.
5209  * Unfortunately, some programs want to do a bit of cleanup and then
5210  * exit on interrupt; unless these processes terminate themselves by
5211  * sending a signal to themselves (instead of calling exit) they will
5212  * confuse this approach.
5213  *
5214  * Called with interrupts off.
5215  */
5216 static int
5217 waitforjob(struct job *jp)
5218 {
5219         int st;
5220
5221         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5222
5223         INT_OFF;
5224         while (jp->state == JOBRUNNING) {
5225                 /* In non-interactive shells, we _can_ get
5226                  * a keyboard signal here and be EINTRed,
5227                  * but we just loop back, waiting for command to complete.
5228                  *
5229                  * man bash:
5230                  * "If bash is waiting for a command to complete and receives
5231                  * a signal for which a trap has been set, the trap
5232                  * will not be executed until the command completes."
5233                  *
5234                  * Reality is that even if trap is not set, bash
5235                  * will not act on the signal until command completes.
5236                  * Try this. sleep5intoff.c:
5237                  * #include <signal.h>
5238                  * #include <unistd.h>
5239                  * int main() {
5240                  *         sigset_t set;
5241                  *         sigemptyset(&set);
5242                  *         sigaddset(&set, SIGINT);
5243                  *         sigaddset(&set, SIGQUIT);
5244                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5245                  *         sleep(5);
5246                  *         return 0;
5247                  * }
5248                  * $ bash -c './sleep5intoff; echo hi'
5249                  * ^C^C^C^C <--- pressing ^C once a second
5250                  * $ _
5251                  * $ bash -c './sleep5intoff; echo hi'
5252                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5253                  * $ _
5254                  */
5255                 dowait(DOWAIT_BLOCK, jp);
5256         }
5257         INT_ON;
5258
5259         st = getstatus(jp);
5260 #if JOBS
5261         if (jp->jobctl) {
5262                 xtcsetpgrp(ttyfd, rootpid);
5263                 restore_tty_if_stopped_or_signaled(jp);
5264
5265                 /*
5266                  * This is truly gross.
5267                  * If we're doing job control, then we did a TIOCSPGRP which
5268                  * caused us (the shell) to no longer be in the controlling
5269                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5270                  * intuit from the subprocess exit status whether a SIGINT
5271                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5272                  */
5273                 if (jp->sigint) /* TODO: do the same with all signals */
5274                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5275         }
5276         if (jp->state == JOBDONE)
5277 #endif
5278                 freejob(jp);
5279         return st;
5280 }
5281
5282 /*
5283  * return 1 if there are stopped jobs, otherwise 0
5284  */
5285 static int
5286 stoppedjobs(void)
5287 {
5288         struct job *jp;
5289         int retval;
5290
5291         retval = 0;
5292         if (job_warning)
5293                 goto out;
5294         jp = curjob;
5295         if (jp && jp->state == JOBSTOPPED) {
5296                 out2str("You have stopped jobs.\n");
5297                 job_warning = 2;
5298                 retval++;
5299         }
5300  out:
5301         return retval;
5302 }
5303
5304
5305 /*
5306  * Code for dealing with input/output redirection.
5307  */
5308
5309 #undef EMPTY
5310 #undef CLOSED
5311 #define EMPTY -2                /* marks an unused slot in redirtab */
5312 #define CLOSED -1               /* marks a slot of previously-closed fd */
5313
5314 /*
5315  * Handle here documents.  Normally we fork off a process to write the
5316  * data to a pipe.  If the document is short, we can stuff the data in
5317  * the pipe without forking.
5318  */
5319 /* openhere needs this forward reference */
5320 static void expandhere(union node *arg, int fd);
5321 static int
5322 openhere(union node *redir)
5323 {
5324         int pip[2];
5325         size_t len = 0;
5326
5327         if (pipe(pip) < 0)
5328                 ash_msg_and_raise_perror("can't create pipe");
5329         if (redir->type == NHERE) {
5330                 len = strlen(redir->nhere.doc->narg.text);
5331                 if (len <= PIPE_BUF) {
5332                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5333                         goto out;
5334                 }
5335         }
5336         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5337                 /* child */
5338                 close(pip[0]);
5339                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5340                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5341                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5342                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5343                 signal(SIGPIPE, SIG_DFL);
5344                 if (redir->type == NHERE)
5345                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5346                 else /* NXHERE */
5347                         expandhere(redir->nhere.doc, pip[1]);
5348                 _exit(EXIT_SUCCESS);
5349         }
5350  out:
5351         close(pip[1]);
5352         return pip[0];
5353 }
5354
5355 static int
5356 openredirect(union node *redir)
5357 {
5358         struct stat sb;
5359         char *fname;
5360         int f;
5361
5362         switch (redir->nfile.type) {
5363 /* Can't happen, our single caller does this itself */
5364 //      case NTOFD:
5365 //      case NFROMFD:
5366 //              return -1;
5367         case NHERE:
5368         case NXHERE:
5369                 return openhere(redir);
5370         }
5371
5372         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5373          * allocated space. Do it only when we know it is safe.
5374          */
5375         fname = redir->nfile.expfname;
5376
5377         switch (redir->nfile.type) {
5378         default:
5379 #if DEBUG
5380                 abort();
5381 #endif
5382         case NFROM:
5383                 f = open(fname, O_RDONLY);
5384                 if (f < 0)
5385                         goto eopen;
5386                 break;
5387         case NFROMTO:
5388                 f = open(fname, O_RDWR|O_CREAT, 0666);
5389                 if (f < 0)
5390                         goto ecreate;
5391                 break;
5392         case NTO:
5393 #if BASH_REDIR_OUTPUT
5394         case NTO2:
5395 #endif
5396                 /* Take care of noclobber mode. */
5397                 if (Cflag) {
5398                         if (stat(fname, &sb) < 0) {
5399                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5400                                 if (f < 0)
5401                                         goto ecreate;
5402                         } else if (!S_ISREG(sb.st_mode)) {
5403                                 f = open(fname, O_WRONLY, 0666);
5404                                 if (f < 0)
5405                                         goto ecreate;
5406                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5407                                         close(f);
5408                                         errno = EEXIST;
5409                                         goto ecreate;
5410                                 }
5411                         } else {
5412                                 errno = EEXIST;
5413                                 goto ecreate;
5414                         }
5415                         break;
5416                 }
5417                 /* FALLTHROUGH */
5418         case NCLOBBER:
5419                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5420                 if (f < 0)
5421                         goto ecreate;
5422                 break;
5423         case NAPPEND:
5424                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5425                 if (f < 0)
5426                         goto ecreate;
5427                 break;
5428         }
5429
5430         return f;
5431  ecreate:
5432         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5433  eopen:
5434         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5435 }
5436
5437 /*
5438  * Copy a file descriptor to be >= 10. Throws exception on error.
5439  */
5440 static int
5441 savefd(int from)
5442 {
5443         int newfd;
5444         int err;
5445
5446         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5447         err = newfd < 0 ? errno : 0;
5448         if (err != EBADF) {
5449                 if (err)
5450                         ash_msg_and_raise_perror("%d", from);
5451                 close(from);
5452                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5453                         close_on_exec_on(newfd);
5454         }
5455
5456         return newfd;
5457 }
5458 static int
5459 dup2_or_raise(int from, int to)
5460 {
5461         int newfd;
5462
5463         newfd = (from != to) ? dup2(from, to) : to;
5464         if (newfd < 0) {
5465                 /* Happens when source fd is not open: try "echo >&99" */
5466                 ash_msg_and_raise_perror("%d", from);
5467         }
5468         return newfd;
5469 }
5470 static int
5471 dup_CLOEXEC(int fd, int avoid_fd)
5472 {
5473         int newfd;
5474  repeat:
5475         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5476         if (newfd >= 0) {
5477                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5478                         close_on_exec_on(newfd);
5479         } else { /* newfd < 0 */
5480                 if (errno == EBUSY)
5481                         goto repeat;
5482                 if (errno == EINTR)
5483                         goto repeat;
5484         }
5485         return newfd;
5486 }
5487 static int
5488 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5489 {
5490         int newfd;
5491  repeat:
5492         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5493         if (newfd < 0) {
5494                 if (errno == EBUSY)
5495                         goto repeat;
5496                 if (errno == EINTR)
5497                         goto repeat;
5498                 /* fd was not open? */
5499                 if (errno == EBADF)
5500                         return fd;
5501                 ash_msg_and_raise_perror("%d", newfd);
5502         }
5503         if (F_DUPFD_CLOEXEC == F_DUPFD)
5504                 close_on_exec_on(newfd);
5505         close(fd);
5506         return newfd;
5507 }
5508
5509 /* Struct def and variable are moved down to the first usage site */
5510 struct squirrel {
5511         int orig_fd;
5512         int moved_to;
5513 };
5514 struct redirtab {
5515         struct redirtab *next;
5516         int pair_count;
5517         struct squirrel two_fd[];
5518 };
5519 #define redirlist (G_var.redirlist)
5520
5521 static void
5522 add_squirrel_closed(struct redirtab *sq, int fd)
5523 {
5524         int i;
5525
5526         if (!sq)
5527                 return;
5528
5529         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5530                 /* If we collide with an already moved fd... */
5531                 if (fd == sq->two_fd[i].orig_fd) {
5532                         /* Examples:
5533                          * "echo 3>FILE 3>&- 3>FILE"
5534                          * "echo 3>&- 3>FILE"
5535                          * No need for last redirect to insert
5536                          * another "need to close 3" indicator.
5537                          */
5538                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5539                         return;
5540                 }
5541         }
5542         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5543         sq->two_fd[i].orig_fd = fd;
5544         sq->two_fd[i].moved_to = CLOSED;
5545 }
5546
5547 static int
5548 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5549 {
5550         int i, new_fd;
5551
5552         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5553                 avoid_fd = 9;
5554
5555 #if JOBS
5556         if (fd == ttyfd) {
5557                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5558                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5559                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5560                 return 1; /* "we closed fd" */
5561         }
5562 #endif
5563         /* Are we called from redirect(0)? E.g. redirect
5564          * in a forked child. No need to save fds,
5565          * we aren't going to use them anymore, ok to trash.
5566          */
5567         if (!sq)
5568                 return 0;
5569
5570         /* If this one of script's fds? */
5571         if (fd != 0) {
5572                 struct parsefile *pf = g_parsefile;
5573                 while (pf) {
5574                         /* We skip fd == 0 case because of the following:
5575                          * $ ash  # running ash interactively
5576                          * $ . ./script.sh
5577                          * and in script.sh: "exec 9>&0".
5578                          * Even though top-level pf_fd _is_ 0,
5579                          * it's still ok to use it: "read" builtin uses it,
5580                          * why should we cripple "exec" builtin?
5581                          */
5582                         if (fd == pf->pf_fd) {
5583                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5584                                 return 1; /* "we closed fd" */
5585                         }
5586                         pf = pf->prev;
5587                 }
5588         }
5589
5590         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5591
5592         /* First: do we collide with some already moved fds? */
5593         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5594                 /* If we collide with an already moved fd... */
5595                 if (fd == sq->two_fd[i].moved_to) {
5596                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5597                         sq->two_fd[i].moved_to = new_fd;
5598                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5599                         if (new_fd < 0) /* what? */
5600                                 xfunc_die();
5601                         return 0; /* "we did not close fd" */
5602                 }
5603                 if (fd == sq->two_fd[i].orig_fd) {
5604                         /* Example: echo Hello >/dev/null 1>&2 */
5605                         TRACE(("redirect_fd %d: already moved\n", fd));
5606                         return 0; /* "we did not close fd" */
5607                 }
5608         }
5609
5610         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5611         new_fd = dup_CLOEXEC(fd, avoid_fd);
5612         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5613         if (new_fd < 0) {
5614                 if (errno != EBADF)
5615                         xfunc_die();
5616                 /* new_fd = CLOSED; - already is -1 */
5617         }
5618         sq->two_fd[i].moved_to = new_fd;
5619         sq->two_fd[i].orig_fd = fd;
5620
5621         /* if we move stderr, let "set -x" code know */
5622         if (fd == preverrout_fd)
5623                 preverrout_fd = new_fd;
5624
5625         return 0; /* "we did not close fd" */
5626 }
5627
5628 static int
5629 internally_opened_fd(int fd, struct redirtab *sq)
5630 {
5631         int i;
5632 #if JOBS
5633         if (fd == ttyfd)
5634                 return 1;
5635 #endif
5636         /* If this one of script's fds? */
5637         if (fd != 0) {
5638                 struct parsefile *pf = g_parsefile;
5639                 while (pf) {
5640                         if (fd == pf->pf_fd)
5641                                 return 1;
5642                         pf = pf->prev;
5643                 }
5644         }
5645
5646         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5647                 if (fd == sq->two_fd[i].moved_to)
5648                         return 1;
5649         }
5650         return 0;
5651 }
5652
5653 /*
5654  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5655  * old file descriptors are stashed away so that the redirection can be
5656  * undone by calling popredir.
5657  */
5658 /* flags passed to redirect */
5659 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5660 static void
5661 redirect(union node *redir, int flags)
5662 {
5663         struct redirtab *sv;
5664
5665         if (!redir)
5666                 return;
5667
5668         sv = NULL;
5669         INT_OFF;
5670         if (flags & REDIR_PUSH)
5671                 sv = redirlist;
5672         do {
5673                 int fd;
5674                 int newfd;
5675                 int close_fd;
5676                 int closed;
5677
5678                 fd = redir->nfile.fd;
5679                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5680                         //bb_error_msg("doing %d > %d", fd, newfd);
5681                         newfd = redir->ndup.dupfd;
5682                         close_fd = -1;
5683                 } else {
5684                         newfd = openredirect(redir); /* always >= 0 */
5685                         if (fd == newfd) {
5686                                 /* open() gave us precisely the fd we wanted.
5687                                  * This means that this fd was not busy
5688                                  * (not opened to anywhere).
5689                                  * Remember to close it on restore:
5690                                  */
5691                                 add_squirrel_closed(sv, fd);
5692                                 continue;
5693                         }
5694                         close_fd = newfd;
5695                 }
5696
5697                 if (fd == newfd)
5698                         continue;
5699
5700                 /* if "N>FILE": move newfd to fd */
5701                 /* if "N>&M": dup newfd to fd */
5702                 /* if "N>&-": close fd (newfd is -1) */
5703
5704  IF_BASH_REDIR_OUTPUT(redirect_more:)
5705
5706                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5707                 if (newfd == -1) {
5708                         /* "N>&-" means "close me" */
5709                         if (!closed) {
5710                                 /* ^^^ optimization: saving may already
5711                                  * have closed it. If not... */
5712                                 close(fd);
5713                         }
5714                 } else {
5715                         /* if newfd is a script fd or saved fd, simulate EBADF */
5716                         if (internally_opened_fd(newfd, sv)) {
5717                                 errno = EBADF;
5718                                 ash_msg_and_raise_perror("%d", newfd);
5719                         }
5720                         dup2_or_raise(newfd, fd);
5721                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5722                                 close(close_fd);
5723 #if BASH_REDIR_OUTPUT
5724                         if (redir->nfile.type == NTO2 && fd == 1) {
5725                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5726                                 fd = 2;
5727                                 newfd = 1;
5728                                 close_fd = -1;
5729                                 goto redirect_more;
5730                         }
5731 #endif
5732                 }
5733         } while ((redir = redir->nfile.next) != NULL);
5734         INT_ON;
5735
5736 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5737 #define REDIR_SAVEFD2 0
5738         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5739         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5740         // not only for calls with flags containing REDIR_SAVEFD2.
5741         // We do this unconditionally (see save_fd_on_redirect()).
5742         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5743         //      preverrout_fd = copied_fd2;
5744 }
5745
5746 static int
5747 redirectsafe(union node *redir, int flags)
5748 {
5749         int err;
5750         volatile int saveint;
5751         struct jmploc *volatile savehandler = exception_handler;
5752         struct jmploc jmploc;
5753
5754         SAVE_INT(saveint);
5755         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5756         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5757         if (!err) {
5758                 exception_handler = &jmploc;
5759                 redirect(redir, flags);
5760         }
5761         exception_handler = savehandler;
5762         if (err && exception_type != EXERROR)
5763                 longjmp(exception_handler->loc, 1);
5764         RESTORE_INT(saveint);
5765         return err;
5766 }
5767
5768 static struct redirtab*
5769 pushredir(union node *redir)
5770 {
5771         struct redirtab *sv;
5772         int i;
5773
5774         if (!redir)
5775                 return redirlist;
5776
5777         i = 0;
5778         do {
5779                 i++;
5780 #if BASH_REDIR_OUTPUT
5781                 if (redir->nfile.type == NTO2)
5782                         i++;
5783 #endif
5784                 redir = redir->nfile.next;
5785         } while (redir);
5786
5787         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5788         sv->pair_count = i;
5789         while (--i >= 0)
5790                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5791         sv->next = redirlist;
5792         redirlist = sv;
5793         return sv->next;
5794 }
5795
5796 /*
5797  * Undo the effects of the last redirection.
5798  */
5799 static void
5800 popredir(int drop)
5801 {
5802         struct redirtab *rp;
5803         int i;
5804
5805         if (redirlist == NULL)
5806                 return;
5807         INT_OFF;
5808         rp = redirlist;
5809         for (i = 0; i < rp->pair_count; i++) {
5810                 int fd = rp->two_fd[i].orig_fd;
5811                 int copy = rp->two_fd[i].moved_to;
5812                 if (copy == CLOSED) {
5813                         if (!drop)
5814                                 close(fd);
5815                         continue;
5816                 }
5817                 if (copy != EMPTY) {
5818                         if (!drop) {
5819                                 /*close(fd);*/
5820                                 dup2_or_raise(copy, fd);
5821                         }
5822                         close(copy);
5823                 }
5824         }
5825         redirlist = rp->next;
5826         free(rp);
5827         INT_ON;
5828 }
5829
5830 static void
5831 unwindredir(struct redirtab *stop)
5832 {
5833         while (redirlist != stop)
5834                 popredir(/*drop:*/ 0);
5835 }
5836
5837
5838 /* ============ Routines to expand arguments to commands
5839  *
5840  * We have to deal with backquotes, shell variables, and file metacharacters.
5841  */
5842
5843 #if ENABLE_FEATURE_SH_MATH
5844 static arith_t
5845 ash_arith(const char *s)
5846 {
5847         arith_state_t math_state;
5848         arith_t result;
5849
5850         math_state.lookupvar = lookupvar;
5851         math_state.setvar    = setvar0;
5852         //math_state.endofname = endofname;
5853
5854         INT_OFF;
5855         result = arith(&math_state, s);
5856         if (math_state.errmsg)
5857                 ash_msg_and_raise_error(math_state.errmsg);
5858         INT_ON;
5859
5860         return result;
5861 }
5862 #endif
5863 #if BASH_SUBSTR
5864 # if ENABLE_FEATURE_SH_MATH
5865 static int substr_atoi(const char *s)
5866 {
5867         arith_t t = ash_arith(s);
5868         if (sizeof(t) > sizeof(int)) {
5869                 /* clamp very large or very large negative nums for ${v:N:M}:
5870                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5871                  */
5872                 if (t > INT_MAX)
5873                         t = INT_MAX;
5874                 if (t < INT_MIN)
5875                         t = INT_MIN;
5876         }
5877         return t;
5878 }
5879 # else
5880 #  define substr_atoi(s) number(s)
5881 # endif
5882 #endif
5883
5884 /*
5885  * expandarg flags
5886  */
5887 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5888 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5889 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5890 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5891 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5892  * POSIX says for this case:
5893  *  Pathname expansion shall not be performed on the word by a
5894  *  non-interactive shell; an interactive shell may perform it, but shall
5895  *  do so only when the expansion would result in one word.
5896  * Currently, our code complies to the above rule by never globbing
5897  * redirection filenames.
5898  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5899  * (this means that on a typical Linux distro, bash almost always
5900  * performs globbing, and thus diverges from what we do).
5901  */
5902 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5903 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5904 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5905 #define EXP_QUOTED      0x80    /* expand word in double quotes */
5906 /*
5907  * rmescape() flags
5908  */
5909 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5910 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5911 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5912 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5913
5914 /* Add CTLESC when necessary. */
5915 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5916 /* Do not skip NUL characters. */
5917 #define QUOTES_KEEPNUL EXP_TILDE
5918
5919 /*
5920  * Structure specifying which parts of the string should be searched
5921  * for IFS characters.
5922  */
5923 struct ifsregion {
5924         struct ifsregion *next; /* next region in list */
5925         int begoff;             /* offset of start of region */
5926         int endoff;             /* offset of end of region */
5927         int nulonly;            /* search for nul bytes only */
5928 };
5929
5930 struct arglist {
5931         struct strlist *list;
5932         struct strlist **lastp;
5933 };
5934
5935 /* output of current string */
5936 static char *expdest;
5937 /* list of back quote expressions */
5938 static struct nodelist *argbackq;
5939 /* first struct in list of ifs regions */
5940 static struct ifsregion ifsfirst;
5941 /* last struct in list */
5942 static struct ifsregion *ifslastp;
5943 /* holds expanded arg list */
5944 static struct arglist exparg;
5945
5946 /*
5947  * Our own itoa().
5948  * cvtnum() is used even if math support is off (to prepare $? values and such).
5949  */
5950 static int
5951 cvtnum(arith_t num)
5952 {
5953         int len;
5954
5955         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5956         len = sizeof(arith_t) * 3;
5957         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5958         if (sizeof(arith_t) < 4) len += 2;
5959
5960         expdest = makestrspace(len, expdest);
5961         len = fmtstr(expdest, len, ARITH_FMT, num);
5962         STADJUST(len, expdest);
5963         return len;
5964 }
5965
5966 /*
5967  * Break the argument string into pieces based upon IFS and add the
5968  * strings to the argument list.  The regions of the string to be
5969  * searched for IFS characters have been stored by recordregion.
5970  */
5971 static void
5972 ifsbreakup(char *string, struct arglist *arglist)
5973 {
5974         struct ifsregion *ifsp;
5975         struct strlist *sp;
5976         char *start;
5977         char *p;
5978         char *q;
5979         const char *ifs, *realifs;
5980         int ifsspc;
5981         int nulonly;
5982
5983         start = string;
5984         if (ifslastp != NULL) {
5985                 ifsspc = 0;
5986                 nulonly = 0;
5987                 realifs = ifsset() ? ifsval() : defifs;
5988                 ifsp = &ifsfirst;
5989                 do {
5990                         int afternul;
5991
5992                         p = string + ifsp->begoff;
5993                         afternul = nulonly;
5994                         nulonly = ifsp->nulonly;
5995                         ifs = nulonly ? nullstr : realifs;
5996                         ifsspc = 0;
5997                         while (p < string + ifsp->endoff) {
5998                                 q = p;
5999                                 if ((unsigned char)*p == CTLESC)
6000                                         p++;
6001                                 if (!strchr(ifs, *p)) {
6002                                         p++;
6003                                         continue;
6004                                 }
6005                                 if (!(afternul || nulonly))
6006                                         ifsspc = (strchr(defifs, *p) != NULL);
6007                                 /* Ignore IFS whitespace at start */
6008                                 if (q == start && ifsspc) {
6009                                         p++;
6010                                         start = p;
6011                                         continue;
6012                                 }
6013                                 *q = '\0';
6014                                 sp = stzalloc(sizeof(*sp));
6015                                 sp->text = start;
6016                                 *arglist->lastp = sp;
6017                                 arglist->lastp = &sp->next;
6018                                 p++;
6019                                 if (!nulonly) {
6020                                         for (;;) {
6021                                                 if (p >= string + ifsp->endoff) {
6022                                                         break;
6023                                                 }
6024                                                 q = p;
6025                                                 if ((unsigned char)*p == CTLESC)
6026                                                         p++;
6027                                                 if (strchr(ifs, *p) == NULL) {
6028                                                         p = q;
6029                                                         break;
6030                                                 }
6031                                                 if (strchr(defifs, *p) == NULL) {
6032                                                         if (ifsspc) {
6033                                                                 p++;
6034                                                                 ifsspc = 0;
6035                                                         } else {
6036                                                                 p = q;
6037                                                                 break;
6038                                                         }
6039                                                 } else
6040                                                         p++;
6041                                         }
6042                                 }
6043                                 start = p;
6044                         } /* while */
6045                         ifsp = ifsp->next;
6046                 } while (ifsp != NULL);
6047                 if (nulonly)
6048                         goto add;
6049         }
6050
6051         if (!*start)
6052                 return;
6053
6054  add:
6055         sp = stzalloc(sizeof(*sp));
6056         sp->text = start;
6057         *arglist->lastp = sp;
6058         arglist->lastp = &sp->next;
6059 }
6060
6061 static void
6062 ifsfree(void)
6063 {
6064         struct ifsregion *p = ifsfirst.next;
6065
6066         if (!p)
6067                 goto out;
6068
6069         INT_OFF;
6070         do {
6071                 struct ifsregion *ifsp;
6072                 ifsp = p->next;
6073                 free(p);
6074                 p = ifsp;
6075         } while (p);
6076         ifsfirst.next = NULL;
6077         INT_ON;
6078  out:
6079         ifslastp = NULL;
6080 }
6081
6082 static size_t
6083 esclen(const char *start, const char *p)
6084 {
6085         size_t esc = 0;
6086
6087         while (p > start && (unsigned char)*--p == CTLESC) {
6088                 esc++;
6089         }
6090         return esc;
6091 }
6092
6093 /*
6094  * Remove any CTLESC characters from a string.
6095  */
6096 #if !BASH_PATTERN_SUBST
6097 #define rmescapes(str, flag, slash_position) \
6098         rmescapes(str, flag)
6099 #endif
6100 static char *
6101 rmescapes(char *str, int flag, int *slash_position)
6102 {
6103         static const char qchars[] ALIGN1 = {
6104                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6105
6106         char *p, *q, *r;
6107         unsigned protect_against_glob;
6108         unsigned globbing;
6109
6110         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6111         if (!p)
6112                 return str;
6113
6114         q = p;
6115         r = str;
6116         if (flag & RMESCAPE_ALLOC) {
6117                 size_t len = p - str;
6118                 size_t fulllen = len + strlen(p) + 1;
6119
6120                 if (flag & RMESCAPE_GROW) {
6121                         int strloc = str - (char *)stackblock();
6122                         r = makestrspace(fulllen, expdest);
6123                         /* p and str may be invalidated by makestrspace */
6124                         str = (char *)stackblock() + strloc;
6125                         p = str + len;
6126                 } else if (flag & RMESCAPE_HEAP) {
6127                         r = ckmalloc(fulllen);
6128                 } else {
6129                         r = stalloc(fulllen);
6130                 }
6131                 q = r;
6132                 if (len > 0) {
6133                         q = (char *)mempcpy(q, str, len);
6134                 }
6135         }
6136
6137         globbing = flag & RMESCAPE_GLOB;
6138         protect_against_glob = globbing;
6139         while (*p) {
6140                 if ((unsigned char)*p == CTLQUOTEMARK) {
6141 // Note: protect_against_glob only affect whether
6142 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6143                         p++;
6144                         protect_against_glob = globbing;
6145                         continue;
6146                 }
6147                 if (*p == '\\') {
6148                         /* naked back slash */
6149                         protect_against_glob = 0;
6150                         goto copy;
6151                 }
6152                 if ((unsigned char)*p == CTLESC) {
6153                         p++;
6154 #if DEBUG
6155                         if (*p == '\0')
6156                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6157 #endif
6158                         if (protect_against_glob) {
6159                                 /*
6160                                  * We used to trust glob() and fnmatch() to eat
6161                                  * superfluous escapes (\z where z has no
6162                                  * special meaning anyway). But this causes
6163                                  * bugs such as string of one greek letter rho
6164                                  * (unicode-encoded as two bytes "cf,81")
6165                                  * getting encoded as "cf,CTLESC,81"
6166                                  * and here, converted to "cf,\,81" -
6167                                  * which does not go well with some flavors
6168                                  * of fnmatch() in unicode locales
6169                                  * (for example, glibc <= 2.22).
6170                                  *
6171                                  * Lets add "\" only on the chars which need it.
6172                                  * Testcases for less obvious chars are shown.
6173                                  */
6174                                 if (*p == '*'
6175                                  || *p == '?'
6176                                  || *p == '['
6177                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6178                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6179                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6180                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6181                                 /* Some libc support [^negate], that's why "^" also needs love */
6182                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6183                                 ) {
6184                                         *q++ = '\\';
6185                                 }
6186                         }
6187                 }
6188 #if BASH_PATTERN_SUBST
6189                 else if (slash_position && p == str + *slash_position) {
6190                         /* stop handling globbing */
6191                         globbing = 0;
6192                         *slash_position = q - r;
6193                         slash_position = NULL;
6194                 }
6195 #endif
6196                 protect_against_glob = globbing;
6197  copy:
6198                 *q++ = *p++;
6199         }
6200         *q = '\0';
6201         if (flag & RMESCAPE_GROW) {
6202                 expdest = r;
6203                 STADJUST(q - r + 1, expdest);
6204         }
6205         return r;
6206 }
6207 #define pmatch(a, b) !fnmatch((a), (b), 0)
6208
6209 /*
6210  * Prepare a pattern for a expmeta (internal glob(3)) call.
6211  *
6212  * Returns an stalloced string.
6213  */
6214 static char *
6215 preglob(const char *pattern, int flag)
6216 {
6217         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6218 }
6219
6220 /*
6221  * Put a string on the stack.
6222  */
6223 static void
6224 memtodest(const char *p, size_t len, int syntax, int quotes)
6225 {
6226         char *q;
6227
6228         if (!len)
6229                 return;
6230
6231         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6232
6233         do {
6234                 unsigned char c = *p++;
6235                 if (c) {
6236                         if (quotes & QUOTES_ESC) {
6237                                 int n = SIT(c, syntax);
6238                                 if (n == CCTL
6239                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6240                                      && n == CBACK
6241                                     )
6242                                 ) {
6243                                         USTPUTC(CTLESC, q);
6244                                 }
6245                         }
6246                 } else if (!(quotes & QUOTES_KEEPNUL))
6247                         continue;
6248                 USTPUTC(c, q);
6249         } while (--len);
6250
6251         expdest = q;
6252 }
6253
6254 static size_t
6255 strtodest(const char *p, int syntax, int quotes)
6256 {
6257         size_t len = strlen(p);
6258         memtodest(p, len, syntax, quotes);
6259         return len;
6260 }
6261
6262 /*
6263  * Record the fact that we have to scan this region of the
6264  * string for IFS characters.
6265  */
6266 static void
6267 recordregion(int start, int end, int nulonly)
6268 {
6269         struct ifsregion *ifsp;
6270
6271         if (ifslastp == NULL) {
6272                 ifsp = &ifsfirst;
6273         } else {
6274                 INT_OFF;
6275                 ifsp = ckzalloc(sizeof(*ifsp));
6276                 /*ifsp->next = NULL; - ckzalloc did it */
6277                 ifslastp->next = ifsp;
6278                 INT_ON;
6279         }
6280         ifslastp = ifsp;
6281         ifslastp->begoff = start;
6282         ifslastp->endoff = end;
6283         ifslastp->nulonly = nulonly;
6284 }
6285
6286 static void
6287 removerecordregions(int endoff)
6288 {
6289         if (ifslastp == NULL)
6290                 return;
6291
6292         if (ifsfirst.endoff > endoff) {
6293                 while (ifsfirst.next) {
6294                         struct ifsregion *ifsp;
6295                         INT_OFF;
6296                         ifsp = ifsfirst.next->next;
6297                         free(ifsfirst.next);
6298                         ifsfirst.next = ifsp;
6299                         INT_ON;
6300                 }
6301                 if (ifsfirst.begoff > endoff) {
6302                         ifslastp = NULL;
6303                 } else {
6304                         ifslastp = &ifsfirst;
6305                         ifsfirst.endoff = endoff;
6306                 }
6307                 return;
6308         }
6309
6310         ifslastp = &ifsfirst;
6311         while (ifslastp->next && ifslastp->next->begoff < endoff)
6312                 ifslastp = ifslastp->next;
6313         while (ifslastp->next) {
6314                 struct ifsregion *ifsp;
6315                 INT_OFF;
6316                 ifsp = ifslastp->next->next;
6317                 free(ifslastp->next);
6318                 ifslastp->next = ifsp;
6319                 INT_ON;
6320         }
6321         if (ifslastp->endoff > endoff)
6322                 ifslastp->endoff = endoff;
6323 }
6324
6325 static char *
6326 exptilde(char *startp, char *p, int flags)
6327 {
6328         unsigned char c;
6329         char *name;
6330         struct passwd *pw;
6331         const char *home;
6332         int quotes = flags & QUOTES_ESC;
6333
6334         name = p + 1;
6335
6336         while ((c = *++p) != '\0') {
6337                 switch (c) {
6338                 case CTLESC:
6339                         return startp;
6340                 case CTLQUOTEMARK:
6341                         return startp;
6342                 case ':':
6343                         if (flags & EXP_VARTILDE)
6344                                 goto done;
6345                         break;
6346                 case '/':
6347                 case CTLENDVAR:
6348                         goto done;
6349                 }
6350         }
6351  done:
6352         *p = '\0';
6353         if (*name == '\0') {
6354                 home = lookupvar("HOME");
6355         } else {
6356                 pw = getpwnam(name);
6357                 if (pw == NULL)
6358                         goto lose;
6359                 home = pw->pw_dir;
6360         }
6361         if (!home || !*home)
6362                 goto lose;
6363         *p = c;
6364         strtodest(home, SQSYNTAX, quotes);
6365         return p;
6366  lose:
6367         *p = c;
6368         return startp;
6369 }
6370
6371 /*
6372  * Execute a command inside back quotes.  If it's a builtin command, we
6373  * want to save its output in a block obtained from malloc.  Otherwise
6374  * we fork off a subprocess and get the output of the command via a pipe.
6375  * Should be called with interrupts off.
6376  */
6377 struct backcmd {                /* result of evalbackcmd */
6378         int fd;                 /* file descriptor to read from */
6379         int nleft;              /* number of chars in buffer */
6380         char *buf;              /* buffer */
6381         struct job *jp;         /* job structure for command */
6382 };
6383
6384 /* These forward decls are needed to use "eval" code for backticks handling: */
6385 /* flags in argument to evaltree */
6386 #define EV_EXIT    01           /* exit after evaluating tree */
6387 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6388 static int evaltree(union node *, int);
6389
6390 /* An evaltree() which is known to never return.
6391  * Used to use an alias:
6392  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6393  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6394  */
6395 static ALWAYS_INLINE NORETURN void
6396 evaltreenr(union node *n, int flags)
6397 {
6398         evaltree(n, flags);
6399         bb_unreachable(abort());
6400         /* NOTREACHED */
6401 }
6402
6403 static void FAST_FUNC
6404 evalbackcmd(union node *n, struct backcmd *result)
6405 {
6406         int pip[2];
6407         struct job *jp;
6408
6409         result->fd = -1;
6410         result->buf = NULL;
6411         result->nleft = 0;
6412         result->jp = NULL;
6413         if (n == NULL) {
6414                 goto out;
6415         }
6416
6417         if (pipe(pip) < 0)
6418                 ash_msg_and_raise_perror("can't create pipe");
6419         jp = makejob(/*n,*/ 1);
6420         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6421                 /* child */
6422                 FORCE_INT_ON;
6423                 close(pip[0]);
6424                 if (pip[1] != 1) {
6425                         /*close(1);*/
6426                         dup2_or_raise(pip[1], 1);
6427                         close(pip[1]);
6428                 }
6429 /* TODO: eflag clearing makes the following not abort:
6430  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6431  * which is what bash does (unless it is in POSIX mode).
6432  * dash deleted "eflag = 0" line in the commit
6433  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6434  *  [EVAL] Don't clear eflag in evalbackcmd
6435  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6436  */
6437                 eflag = 0;
6438                 ifsfree();
6439                 evaltreenr(n, EV_EXIT);
6440                 /* NOTREACHED */
6441         }
6442         /* parent */
6443         close(pip[1]);
6444         result->fd = pip[0];
6445         result->jp = jp;
6446
6447  out:
6448         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6449                 result->fd, result->buf, result->nleft, result->jp));
6450 }
6451
6452 /*
6453  * Expand stuff in backwards quotes.
6454  */
6455 static void
6456 expbackq(union node *cmd, int flag)
6457 {
6458         struct backcmd in;
6459         int i;
6460         char buf[128];
6461         char *p;
6462         char *dest;
6463         int startloc;
6464         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6465         struct stackmark smark;
6466
6467         INT_OFF;
6468         startloc = expdest - (char *)stackblock();
6469         pushstackmark(&smark, startloc);
6470         evalbackcmd(cmd, &in);
6471         popstackmark(&smark);
6472
6473         p = in.buf;
6474         i = in.nleft;
6475         if (i == 0)
6476                 goto read;
6477         for (;;) {
6478                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6479  read:
6480                 if (in.fd < 0)
6481                         break;
6482                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6483                 TRACE(("expbackq: read returns %d\n", i));
6484                 if (i <= 0)
6485                         break;
6486                 p = buf;
6487         }
6488
6489         free(in.buf);
6490         if (in.fd >= 0) {
6491                 close(in.fd);
6492                 back_exitstatus = waitforjob(in.jp);
6493         }
6494         INT_ON;
6495
6496         /* Eat all trailing newlines */
6497         dest = expdest;
6498         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6499                 STUNPUTC(dest);
6500         expdest = dest;
6501
6502         if (!(flag & EXP_QUOTED))
6503                 recordregion(startloc, dest - (char *)stackblock(), 0);
6504         TRACE(("evalbackq: size:%d:'%.*s'\n",
6505                 (int)((dest - (char *)stackblock()) - startloc),
6506                 (int)((dest - (char *)stackblock()) - startloc),
6507                 stackblock() + startloc));
6508 }
6509
6510 #if ENABLE_FEATURE_SH_MATH
6511 /*
6512  * Expand arithmetic expression.  Backup to start of expression,
6513  * evaluate, place result in (backed up) result, adjust string position.
6514  */
6515 static void
6516 expari(int flag)
6517 {
6518         char *p, *start;
6519         int begoff;
6520         int len;
6521
6522         /* ifsfree(); */
6523
6524         /*
6525          * This routine is slightly over-complicated for
6526          * efficiency.  Next we scan backwards looking for the
6527          * start of arithmetic.
6528          */
6529         start = stackblock();
6530         p = expdest - 1;
6531         *p = '\0';
6532         p--;
6533         while (1) {
6534                 int esc;
6535
6536                 while ((unsigned char)*p != CTLARI) {
6537                         p--;
6538 #if DEBUG
6539                         if (p < start) {
6540                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6541                         }
6542 #endif
6543                 }
6544
6545                 esc = esclen(start, p);
6546                 if (!(esc % 2)) {
6547                         break;
6548                 }
6549
6550                 p -= esc + 1;
6551         }
6552
6553         begoff = p - start;
6554
6555         removerecordregions(begoff);
6556
6557         expdest = p;
6558
6559         if (flag & QUOTES_ESC)
6560                 rmescapes(p + 1, 0, NULL);
6561
6562         len = cvtnum(ash_arith(p + 1));
6563
6564         if (!(flag & EXP_QUOTED))
6565                 recordregion(begoff, begoff + len, 0);
6566 }
6567 #endif
6568
6569 /* argstr needs it */
6570 static char *evalvar(char *p, int flags);
6571
6572 /*
6573  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6574  * characters to allow for further processing.  Otherwise treat
6575  * $@ like $* since no splitting will be performed.
6576  */
6577 static void
6578 argstr(char *p, int flags)
6579 {
6580         static const char spclchars[] ALIGN1 = {
6581                 '=',
6582                 ':',
6583                 CTLQUOTEMARK,
6584                 CTLENDVAR,
6585                 CTLESC,
6586                 CTLVAR,
6587                 CTLBACKQ,
6588 #if ENABLE_FEATURE_SH_MATH
6589                 CTLENDARI,
6590 #endif
6591                 '\0'
6592         };
6593         const char *reject = spclchars;
6594         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6595         int inquotes;
6596         size_t length;
6597         int startloc;
6598
6599         if (!(flags & EXP_VARTILDE)) {
6600                 reject += 2;
6601         } else if (flags & EXP_VARTILDE2) {
6602                 reject++;
6603         }
6604         inquotes = 0;
6605         length = 0;
6606         if (flags & EXP_TILDE) {
6607                 char *q;
6608
6609                 flags &= ~EXP_TILDE;
6610  tilde:
6611                 q = p;
6612                 if (*q == '~')
6613                         p = exptilde(p, q, flags);
6614         }
6615  start:
6616         startloc = expdest - (char *)stackblock();
6617         for (;;) {
6618                 unsigned char c;
6619
6620                 length += strcspn(p + length, reject);
6621                 c = p[length];
6622                 if (c) {
6623                         if (!(c & 0x80)
6624                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6625                         ) {
6626                                 /* c == '=' || c == ':' || c == CTLENDARI */
6627                                 length++;
6628                         }
6629                 }
6630                 if (length > 0) {
6631                         int newloc;
6632                         expdest = stack_nputstr(p, length, expdest);
6633                         newloc = expdest - (char *)stackblock();
6634                         if (breakall && !inquotes && newloc > startloc) {
6635                                 recordregion(startloc, newloc, 0);
6636                         }
6637                         startloc = newloc;
6638                 }
6639                 p += length + 1;
6640                 length = 0;
6641
6642                 switch (c) {
6643                 case '\0':
6644                         goto breakloop;
6645                 case '=':
6646                         if (flags & EXP_VARTILDE2) {
6647                                 p--;
6648                                 continue;
6649                         }
6650                         flags |= EXP_VARTILDE2;
6651                         reject++;
6652                         /* fall through */
6653                 case ':':
6654                         /*
6655                          * sort of a hack - expand tildes in variable
6656                          * assignments (after the first '=' and after ':'s).
6657                          */
6658                         if (*--p == '~') {
6659                                 goto tilde;
6660                         }
6661                         continue;
6662                 }
6663
6664                 switch (c) {
6665                 case CTLENDVAR: /* ??? */
6666                         goto breakloop;
6667                 case CTLQUOTEMARK:
6668                         /* "$@" syntax adherence hack */
6669                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6670                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6671                                 goto start;
6672                         }
6673                         inquotes ^= EXP_QUOTED;
6674  addquote:
6675                         if (flags & QUOTES_ESC) {
6676                                 p--;
6677                                 length++;
6678                                 startloc++;
6679                         }
6680                         break;
6681                 case CTLESC:
6682                         startloc++;
6683                         length++;
6684                         goto addquote;
6685                 case CTLVAR:
6686                         TRACE(("argstr: evalvar('%s')\n", p));
6687                         p = evalvar(p, flags | inquotes);
6688                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6689                         goto start;
6690                 case CTLBACKQ:
6691                         expbackq(argbackq->n, flags | inquotes);
6692                         argbackq = argbackq->next;
6693                         goto start;
6694 #if ENABLE_FEATURE_SH_MATH
6695                 case CTLENDARI:
6696                         p--;
6697                         expari(flags | inquotes);
6698                         goto start;
6699 #endif
6700                 }
6701         }
6702  breakloop: ;
6703 }
6704
6705 static char *
6706 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6707                 char *pattern, int quotes, int zero)
6708 {
6709         char *loc, *loc2;
6710         char c;
6711
6712         loc = startp;
6713         loc2 = rmesc;
6714         do {
6715                 int match;
6716                 const char *s = loc2;
6717
6718                 c = *loc2;
6719                 if (zero) {
6720                         *loc2 = '\0';
6721                         s = rmesc;
6722                 }
6723                 match = pmatch(pattern, s);
6724
6725                 *loc2 = c;
6726                 if (match)
6727                         return loc;
6728                 if (quotes && (unsigned char)*loc == CTLESC)
6729                         loc++;
6730                 loc++;
6731                 loc2++;
6732         } while (c);
6733         return NULL;
6734 }
6735
6736 static char *
6737 scanright(char *startp, char *rmesc, char *rmescend,
6738                 char *pattern, int quotes, int match_at_start)
6739 {
6740 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6741         int try2optimize = match_at_start;
6742 #endif
6743         int esc = 0;
6744         char *loc;
6745         char *loc2;
6746
6747         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6748          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6749          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6750          * Logic:
6751          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6752          * and on each iteration they go back two/one char until they reach the beginning.
6753          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6754          */
6755         /* TODO: document in what other circumstances we are called. */
6756
6757         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6758                 int match;
6759                 char c = *loc2;
6760                 const char *s = loc2;
6761                 if (match_at_start) {
6762                         *loc2 = '\0';
6763                         s = rmesc;
6764                 }
6765                 match = pmatch(pattern, s);
6766                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6767                 *loc2 = c;
6768                 if (match)
6769                         return loc;
6770 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6771                 if (try2optimize) {
6772                         /* Maybe we can optimize this:
6773                          * if pattern ends with unescaped *, we can avoid checking
6774                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6775                          * it won't match truncated "raw_value_of_" strings too.
6776                          */
6777                         unsigned plen = strlen(pattern);
6778                         /* Does it end with "*"? */
6779                         if (plen != 0 && pattern[--plen] == '*') {
6780                                 /* "xxxx*" is not escaped */
6781                                 /* "xxx\*" is escaped */
6782                                 /* "xx\\*" is not escaped */
6783                                 /* "x\\\*" is escaped */
6784                                 int slashes = 0;
6785                                 while (plen != 0 && pattern[--plen] == '\\')
6786                                         slashes++;
6787                                 if (!(slashes & 1))
6788                                         break; /* ends with unescaped "*" */
6789                         }
6790                         try2optimize = 0;
6791                 }
6792 #endif
6793                 loc--;
6794                 if (quotes) {
6795                         if (--esc < 0) {
6796                                 esc = esclen(startp, loc);
6797                         }
6798                         if (esc % 2) {
6799                                 esc--;
6800                                 loc--;
6801                         }
6802                 }
6803         }
6804         return NULL;
6805 }
6806
6807 static void varunset(const char *, const char *, const char *, int) NORETURN;
6808 static void
6809 varunset(const char *end, const char *var, const char *umsg, int varflags)
6810 {
6811         const char *msg;
6812         const char *tail;
6813
6814         tail = nullstr;
6815         msg = "parameter not set";
6816         if (umsg) {
6817                 if ((unsigned char)*end == CTLENDVAR) {
6818                         if (varflags & VSNUL)
6819                                 tail = " or null";
6820                 } else {
6821                         msg = umsg;
6822                 }
6823         }
6824         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6825 }
6826
6827 static const char *
6828 subevalvar(char *p, char *varname, int strloc, int subtype,
6829                 int startloc, int varflags, int flag)
6830 {
6831         struct nodelist *saveargbackq = argbackq;
6832         int quotes = flag & QUOTES_ESC;
6833         char *startp;
6834         char *loc;
6835         char *rmesc, *rmescend;
6836         char *str;
6837         int amount, resetloc;
6838         int argstr_flags;
6839         IF_BASH_PATTERN_SUBST(int workloc;)
6840         IF_BASH_PATTERN_SUBST(int slash_pos;)
6841         IF_BASH_PATTERN_SUBST(char *repl;)
6842         int zero;
6843         char *(*scan)(char*, char*, char*, char*, int, int);
6844
6845         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6846         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6847
6848 #if BASH_PATTERN_SUBST
6849         /* For "${v/pattern/repl}", we must find the delimiter _before_
6850          * argstr() call expands possible variable references in pattern:
6851          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6852          */
6853         repl = NULL;
6854         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6855                 /* Find '/' and replace with NUL */
6856                 repl = p;
6857                 for (;;) {
6858                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6859                         if (*repl == '\0') {
6860                                 repl = NULL;
6861                                 break;
6862                         }
6863                         if (*repl == '/') {
6864                                 *repl = '\0';
6865                                 break;
6866                         }
6867                         if ((unsigned char)*repl == CTLESC && repl[1])
6868                                 repl++;
6869                         repl++;
6870                 }
6871         }
6872 #endif
6873         argstr_flags = EXP_TILDE;
6874         if (subtype != VSASSIGN
6875          && subtype != VSQUESTION
6876 #if BASH_SUBSTR
6877          && subtype != VSSUBSTR
6878 #endif
6879         ) {
6880                 /* EXP_CASE keeps CTLESC's */
6881                 argstr_flags = EXP_TILDE | EXP_CASE;
6882         }
6883         argstr(p, argstr_flags);
6884         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6885 #if BASH_PATTERN_SUBST
6886         slash_pos = -1;
6887         if (repl) {
6888                 slash_pos = expdest - ((char *)stackblock() + strloc);
6889                 STPUTC('/', expdest);
6890                 //bb_error_msg("repl+1:'%s'", repl + 1);
6891                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6892                 *repl = '/';
6893         }
6894 #endif
6895         STPUTC('\0', expdest);
6896         argbackq = saveargbackq;
6897         startp = (char *)stackblock() + startloc;
6898         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6899
6900         switch (subtype) {
6901         case VSASSIGN:
6902                 setvar0(varname, startp);
6903                 amount = startp - expdest;
6904                 STADJUST(amount, expdest);
6905                 return startp;
6906
6907         case VSQUESTION:
6908                 varunset(p, varname, startp, varflags);
6909                 /* NOTREACHED */
6910
6911 #if BASH_SUBSTR
6912         case VSSUBSTR: {
6913                 int pos, len, orig_len;
6914                 char *colon;
6915
6916                 loc = str = stackblock() + strloc;
6917
6918                 /* Read POS in ${var:POS:LEN} */
6919                 colon = strchr(loc, ':');
6920                 if (colon) *colon = '\0';
6921                 pos = substr_atoi(loc);
6922                 if (colon) *colon = ':';
6923
6924                 /* Read LEN in ${var:POS:LEN} */
6925                 len = str - startp - 1;
6926                 /* *loc != '\0', guaranteed by parser */
6927                 if (quotes) {
6928                         char *ptr;
6929                         /* Adjust the length by the number of escapes */
6930                         for (ptr = startp; ptr < (str - 1); ptr++) {
6931                                 if ((unsigned char)*ptr == CTLESC) {
6932                                         len--;
6933                                         ptr++;
6934                                 }
6935                         }
6936                 }
6937                 orig_len = len;
6938                 if (*loc++ == ':') {
6939                         /* ${var::LEN} */
6940                         len = substr_atoi(loc);
6941                 } else {
6942                         /* Skip POS in ${var:POS:LEN} */
6943                         len = orig_len;
6944                         while (*loc && *loc != ':')
6945                                 loc++;
6946                         if (*loc++ == ':')
6947                                 len = substr_atoi(loc);
6948                 }
6949                 if (pos < 0) {
6950                         /* ${VAR:$((-n)):l} starts n chars from the end */
6951                         pos = orig_len + pos;
6952                 }
6953                 if ((unsigned)pos >= orig_len) {
6954                         /* apart from obvious ${VAR:999999:l},
6955                          * covers ${VAR:$((-9999999)):l} - result is ""
6956                          * (bash compat)
6957                          */
6958                         pos = 0;
6959                         len = 0;
6960                 }
6961                 if (len < 0) {
6962                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6963                         len = (orig_len - pos) + len;
6964                 }
6965                 if ((unsigned)len > (orig_len - pos))
6966                         len = orig_len - pos;
6967
6968                 for (str = startp; pos; str++, pos--) {
6969                         if (quotes && (unsigned char)*str == CTLESC)
6970                                 str++;
6971                 }
6972                 for (loc = startp; len; len--) {
6973                         if (quotes && (unsigned char)*str == CTLESC)
6974                                 *loc++ = *str++;
6975                         *loc++ = *str++;
6976                 }
6977                 *loc = '\0';
6978                 amount = loc - expdest;
6979                 STADJUST(amount, expdest);
6980                 return loc;
6981         }
6982 #endif /* BASH_SUBSTR */
6983         }
6984
6985         resetloc = expdest - (char *)stackblock();
6986
6987 #if BASH_PATTERN_SUBST
6988         repl = NULL;
6989
6990         /* We'll comeback here if we grow the stack while handling
6991          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6992          * stack will need rebasing, and we'll need to remove our work
6993          * areas each time
6994          */
6995  restart:
6996 #endif
6997
6998         amount = expdest - ((char *)stackblock() + resetloc);
6999         STADJUST(-amount, expdest);
7000         startp = (char *)stackblock() + startloc;
7001
7002         rmesc = startp;
7003         rmescend = (char *)stackblock() + strloc;
7004         //bb_error_msg("str7:'%s'", rmescend);
7005         if (quotes) {
7006 //TODO: how to handle slash_pos here if string changes (shortens?)
7007                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7008                 if (rmesc != startp) {
7009                         rmescend = expdest;
7010                         startp = (char *)stackblock() + startloc;
7011                 }
7012         }
7013         rmescend--;
7014         str = (char *)stackblock() + strloc;
7015         /*
7016          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7017          * The result is a_\_z_c (not a\_\_z_c)!
7018          *
7019          * The search pattern and replace string treat backslashes differently!
7020          * "&slash_pos" causes rmescapes() to work differently on the pattern
7021          * and string.  It's only used on the first call.
7022          */
7023         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7024         rmescapes(str, RMESCAPE_GLOB,
7025                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7026         );
7027
7028 #if BASH_PATTERN_SUBST
7029         workloc = expdest - (char *)stackblock();
7030         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7031                 int len;
7032                 char *idx, *end;
7033
7034                 if (!repl) {
7035                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7036                         repl = nullstr;
7037                         if (slash_pos >= 0) {
7038                                 repl = str + slash_pos;
7039                                 *repl++ = '\0';
7040                         }
7041                 }
7042                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7043
7044                 /* If there's no pattern to match, return the expansion unmolested */
7045                 if (str[0] == '\0')
7046                         return NULL;
7047
7048                 len = 0;
7049                 idx = startp;
7050                 end = str - 1;
7051                 while (idx < end) {
7052  try_to_match:
7053                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7054                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7055                         if (!loc) {
7056                                 /* No match, advance */
7057                                 char *restart_detect = stackblock();
7058  skip_matching:
7059                                 STPUTC(*idx, expdest);
7060                                 if (quotes && (unsigned char)*idx == CTLESC) {
7061                                         idx++;
7062                                         len++;
7063                                         STPUTC(*idx, expdest);
7064                                 }
7065                                 if (stackblock() != restart_detect)
7066                                         goto restart;
7067                                 idx++;
7068                                 len++;
7069                                 rmesc++;
7070                                 /* continue; - prone to quadratic behavior, smarter code: */
7071                                 if (idx >= end)
7072                                         break;
7073                                 if (str[0] == '*') {
7074                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7075                                          * it would never match "ong_string" etc, no point in trying.
7076                                          */
7077                                         goto skip_matching;
7078                                 }
7079                                 goto try_to_match;
7080                         }
7081
7082                         if (subtype == VSREPLACEALL) {
7083                                 while (idx < loc) {
7084                                         if (quotes && (unsigned char)*idx == CTLESC)
7085                                                 idx++;
7086                                         idx++;
7087                                         rmesc++;
7088                                 }
7089                         } else {
7090                                 idx = loc;
7091                         }
7092
7093                         //bb_error_msg("repl:'%s'", repl);
7094                         for (loc = (char*)repl; *loc; loc++) {
7095                                 char *restart_detect = stackblock();
7096                                 if (quotes && *loc == '\\') {
7097                                         STPUTC(CTLESC, expdest);
7098                                         len++;
7099                                 }
7100                                 STPUTC(*loc, expdest);
7101                                 if (stackblock() != restart_detect)
7102                                         goto restart;
7103                                 len++;
7104                         }
7105
7106                         if (subtype == VSREPLACE) {
7107                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7108                                 while (*idx) {
7109                                         char *restart_detect = stackblock();
7110                                         STPUTC(*idx, expdest);
7111                                         if (stackblock() != restart_detect)
7112                                                 goto restart;
7113                                         len++;
7114                                         idx++;
7115                                 }
7116                                 break;
7117                         }
7118                 }
7119
7120                 /* We've put the replaced text into a buffer at workloc, now
7121                  * move it to the right place and adjust the stack.
7122                  */
7123                 STPUTC('\0', expdest);
7124                 startp = (char *)stackblock() + startloc;
7125                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7126                 //bb_error_msg("startp:'%s'", startp);
7127                 amount = expdest - (startp + len);
7128                 STADJUST(-amount, expdest);
7129                 return startp;
7130         }
7131 #endif /* BASH_PATTERN_SUBST */
7132
7133         subtype -= VSTRIMRIGHT;
7134 #if DEBUG
7135         if (subtype < 0 || subtype > 7)
7136                 abort();
7137 #endif
7138         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7139         zero = subtype >> 1;
7140         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7141         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7142
7143         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7144         if (loc) {
7145                 if (zero) {
7146                         memmove(startp, loc, str - loc);
7147                         loc = startp + (str - loc) - 1;
7148                 }
7149                 *loc = '\0';
7150                 amount = loc - expdest;
7151                 STADJUST(amount, expdest);
7152         }
7153         return loc;
7154 }
7155
7156 /*
7157  * Add the value of a specialized variable to the stack string.
7158  * name parameter (examples):
7159  * ash -c 'echo $1'      name:'1='
7160  * ash -c 'echo $qwe'    name:'qwe='
7161  * ash -c 'echo $$'      name:'$='
7162  * ash -c 'echo ${$}'    name:'$='
7163  * ash -c 'echo ${$##q}' name:'$=q'
7164  * ash -c 'echo ${#$}'   name:'$='
7165  * note: examples with bad shell syntax:
7166  * ash -c 'echo ${#$1}'  name:'$=1'
7167  * ash -c 'echo ${#1#}'  name:'1=#'
7168  */
7169 static NOINLINE ssize_t
7170 varvalue(char *name, int varflags, int flags, int *quotedp)
7171 {
7172         const char *p;
7173         int num;
7174         int i;
7175         ssize_t len = 0;
7176         int sep;
7177         int quoted = *quotedp;
7178         int subtype = varflags & VSTYPE;
7179         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7180         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7181         int syntax;
7182
7183         sep = (flags & EXP_FULL) << CHAR_BIT;
7184         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7185
7186         switch (*name) {
7187         case '$':
7188                 num = rootpid;
7189                 goto numvar;
7190         case '?':
7191                 num = exitstatus;
7192                 goto numvar;
7193         case '#':
7194                 num = shellparam.nparam;
7195                 goto numvar;
7196         case '!':
7197                 num = backgndpid;
7198                 if (num == 0)
7199                         return -1;
7200  numvar:
7201                 len = cvtnum(num);
7202                 goto check_1char_name;
7203         case '-':
7204                 expdest = makestrspace(NOPTS, expdest);
7205                 for (i = NOPTS - 1; i >= 0; i--) {
7206                         if (optlist[i] && optletters(i)) {
7207                                 USTPUTC(optletters(i), expdest);
7208                                 len++;
7209                         }
7210                 }
7211  check_1char_name:
7212 #if 0
7213                 /* handles cases similar to ${#$1} */
7214                 if (name[2] != '\0')
7215                         raise_error_syntax("bad substitution");
7216 #endif
7217                 break;
7218         case '@':
7219                 if (quoted && sep)
7220                         goto param;
7221                 /* fall through */
7222         case '*': {
7223                 char **ap;
7224                 char sepc;
7225
7226                 if (quoted)
7227                         sep = 0;
7228                 sep |= ifsset() ? ifsval()[0] : ' ';
7229  param:
7230                 sepc = sep;
7231                 *quotedp = !sepc;
7232                 ap = shellparam.p;
7233                 if (!ap)
7234                         return -1;
7235                 while ((p = *ap++) != NULL) {
7236                         len += strtodest(p, syntax, quotes);
7237
7238                         if (*ap && sep) {
7239                                 len++;
7240                                 memtodest(&sepc, 1, syntax, quotes);
7241                         }
7242                 }
7243                 break;
7244         } /* case '*' */
7245         case '0':
7246         case '1':
7247         case '2':
7248         case '3':
7249         case '4':
7250         case '5':
7251         case '6':
7252         case '7':
7253         case '8':
7254         case '9':
7255                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7256                 if (num < 0 || num > shellparam.nparam)
7257                         return -1;
7258                 p = num ? shellparam.p[num - 1] : arg0;
7259                 goto value;
7260         default:
7261                 /* NB: name has form "VAR=..." */
7262                 p = lookupvar(name);
7263  value:
7264                 if (!p)
7265                         return -1;
7266
7267                 len = strtodest(p, syntax, quotes);
7268 #if ENABLE_UNICODE_SUPPORT
7269                 if (subtype == VSLENGTH && len > 0) {
7270                         reinit_unicode_for_ash();
7271                         if (unicode_status == UNICODE_ON) {
7272                                 STADJUST(-len, expdest);
7273                                 discard = 0;
7274                                 len = unicode_strlen(p);
7275                         }
7276                 }
7277 #endif
7278                 break;
7279         }
7280
7281         if (discard)
7282                 STADJUST(-len, expdest);
7283         return len;
7284 }
7285
7286 /*
7287  * Expand a variable, and return a pointer to the next character in the
7288  * input string.
7289  */
7290 static char *
7291 evalvar(char *p, int flag)
7292 {
7293         char varflags;
7294         char subtype;
7295         int quoted;
7296         char easy;
7297         char *var;
7298         int patloc;
7299         int startloc;
7300         ssize_t varlen;
7301
7302         varflags = (unsigned char) *p++;
7303         subtype = varflags & VSTYPE;
7304
7305         if (!subtype)
7306                 raise_error_syntax("bad substitution");
7307
7308         quoted = flag & EXP_QUOTED;
7309         var = p;
7310         easy = (!quoted || (*var == '@' && shellparam.nparam));
7311         startloc = expdest - (char *)stackblock();
7312         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7313
7314  again:
7315         varlen = varvalue(var, varflags, flag, &quoted);
7316         if (varflags & VSNUL)
7317                 varlen--;
7318
7319         if (subtype == VSPLUS) {
7320                 varlen = -1 - varlen;
7321                 goto vsplus;
7322         }
7323
7324         if (subtype == VSMINUS) {
7325  vsplus:
7326                 if (varlen < 0) {
7327                         argstr(
7328                                 p,
7329                                 flag | EXP_TILDE | EXP_WORD
7330                         );
7331                         goto end;
7332                 }
7333                 goto record;
7334         }
7335
7336         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7337                 if (varlen >= 0)
7338                         goto record;
7339
7340                 subevalvar(p, var, 0, subtype, startloc, varflags,
7341                            flag & ~QUOTES_ESC);
7342                 varflags &= ~VSNUL;
7343                 /*
7344                  * Remove any recorded regions beyond
7345                  * start of variable
7346                  */
7347                 removerecordregions(startloc);
7348                 goto again;
7349         }
7350
7351         if (varlen < 0 && uflag)
7352                 varunset(p, var, 0, 0);
7353
7354         if (subtype == VSLENGTH) {
7355                 cvtnum(varlen > 0 ? varlen : 0);
7356                 goto record;
7357         }
7358
7359         if (subtype == VSNORMAL) {
7360  record:
7361                 if (!easy)
7362                         goto end;
7363                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7364                 goto end;
7365         }
7366
7367 #if DEBUG
7368         switch (subtype) {
7369         case VSTRIMLEFT:
7370         case VSTRIMLEFTMAX:
7371         case VSTRIMRIGHT:
7372         case VSTRIMRIGHTMAX:
7373 #if BASH_SUBSTR
7374         case VSSUBSTR:
7375 #endif
7376 #if BASH_PATTERN_SUBST
7377         case VSREPLACE:
7378         case VSREPLACEALL:
7379 #endif
7380                 break;
7381         default:
7382                 abort();
7383         }
7384 #endif
7385
7386         if (varlen >= 0) {
7387                 /*
7388                  * Terminate the string and start recording the pattern
7389                  * right after it
7390                  */
7391                 STPUTC('\0', expdest);
7392                 patloc = expdest - (char *)stackblock();
7393                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7394                                 startloc, varflags, flag)) {
7395                         int amount = expdest - (
7396                                 (char *)stackblock() + patloc - 1
7397                         );
7398                         STADJUST(-amount, expdest);
7399                 }
7400                 /* Remove any recorded regions beyond start of variable */
7401                 removerecordregions(startloc);
7402                 goto record;
7403         }
7404
7405  end:
7406         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7407                 int nesting = 1;
7408                 for (;;) {
7409                         unsigned char c = *p++;
7410                         if (c == CTLESC)
7411                                 p++;
7412                         else if (c == CTLBACKQ) {
7413                                 if (varlen >= 0)
7414                                         argbackq = argbackq->next;
7415                         } else if (c == CTLVAR) {
7416                                 if ((*p++ & VSTYPE) != VSNORMAL)
7417                                         nesting++;
7418                         } else if (c == CTLENDVAR) {
7419                                 if (--nesting == 0)
7420                                         break;
7421                         }
7422                 }
7423         }
7424         return p;
7425 }
7426
7427 /*
7428  * Add a file name to the list.
7429  */
7430 static void
7431 addfname(const char *name)
7432 {
7433         struct strlist *sp;
7434
7435         sp = stzalloc(sizeof(*sp));
7436         sp->text = sstrdup(name);
7437         *exparg.lastp = sp;
7438         exparg.lastp = &sp->next;
7439 }
7440
7441 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7442 static int
7443 hasmeta(const char *p)
7444 {
7445         static const char chars[] ALIGN1 = {
7446                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7447         };
7448
7449         for (;;) {
7450                 p = strpbrk(p, chars);
7451                 if (!p)
7452                         break;
7453                 switch ((unsigned char)*p) {
7454                 case CTLQUOTEMARK:
7455                         for (;;) {
7456                                 p++;
7457                                 if ((unsigned char)*p == CTLQUOTEMARK)
7458                                         break;
7459                                 if ((unsigned char)*p == CTLESC)
7460                                         p++;
7461                                 if (*p == '\0') /* huh? */
7462                                         return 0;
7463                         }
7464                         break;
7465                 case '\\':
7466                 case CTLESC:
7467                         p++;
7468                         if (*p == '\0')
7469                                 return 0;
7470                         break;
7471                 case '[':
7472                         if (!strchr(p + 1, ']')) {
7473                                 /* It's not a properly closed [] pattern,
7474                                  * but other metas may follow. Continue checking.
7475                                  * my[file* _is_ globbed by bash
7476                                  * and matches filenames like "my[file1".
7477                                  */
7478                                 break;
7479                         }
7480                         /* fallthrough */
7481                 default:
7482                 /* case '*': */
7483                 /* case '?': */
7484                         return 1;
7485                 }
7486                 p++;
7487         }
7488
7489         return 0;
7490 }
7491
7492 /* If we want to use glob() from libc... */
7493 #if !ENABLE_ASH_INTERNAL_GLOB
7494
7495 /* Add the result of glob() to the list */
7496 static void
7497 addglob(const glob_t *pglob)
7498 {
7499         char **p = pglob->gl_pathv;
7500
7501         do {
7502                 addfname(*p);
7503         } while (*++p);
7504 }
7505 static void
7506 expandmeta(struct strlist *str /*, int flag*/)
7507 {
7508         /* TODO - EXP_REDIR */
7509
7510         while (str) {
7511                 char *p;
7512                 glob_t pglob;
7513                 int i;
7514
7515                 if (fflag)
7516                         goto nometa;
7517
7518                 if (!hasmeta(str->text))
7519                         goto nometa;
7520
7521                 INT_OFF;
7522                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7523 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7524 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7525 //
7526 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7527 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7528 // Which means you need to unescape the string, right? Not so fast:
7529 // if there _is_ a file named "file\?" (with backslash), it is returned
7530 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7531 // You DON'T KNOW by looking at the result whether you need to unescape it.
7532 //
7533 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7534 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7535 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7536 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7537 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7538 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7539                 i = glob(p, 0, NULL, &pglob);
7540                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7541                 if (p != str->text)
7542                         free(p);
7543                 switch (i) {
7544                 case 0:
7545 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7546                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7547                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7548                                 goto nometa2;
7549 #endif
7550                         addglob(&pglob);
7551                         globfree(&pglob);
7552                         INT_ON;
7553                         break;
7554                 case GLOB_NOMATCH:
7555  //nometa2:
7556                         globfree(&pglob);
7557                         INT_ON;
7558  nometa:
7559                         *exparg.lastp = str;
7560                         rmescapes(str->text, 0, NULL);
7561                         exparg.lastp = &str->next;
7562                         break;
7563                 default:        /* GLOB_NOSPACE */
7564                         globfree(&pglob);
7565                         INT_ON;
7566                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7567                 }
7568                 str = str->next;
7569         }
7570 }
7571
7572 #else
7573 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7574
7575 /*
7576  * Do metacharacter (i.e. *, ?, [...]) expansion.
7577  */
7578 typedef struct exp_t {
7579         char *dir;
7580         unsigned dir_max;
7581 } exp_t;
7582 static void
7583 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7584 {
7585 #define expdir exp->dir
7586 #define expdir_max exp->dir_max
7587         char *enddir = expdir + expdir_len;
7588         char *p;
7589         const char *cp;
7590         char *start;
7591         char *endname;
7592         int metaflag;
7593         struct stat statb;
7594         DIR *dirp;
7595         struct dirent *dp;
7596         int atend;
7597         int matchdot;
7598         int esc;
7599
7600         metaflag = 0;
7601         start = name;
7602         for (p = name; esc = 0, *p; p += esc + 1) {
7603                 if (*p == '*' || *p == '?')
7604                         metaflag = 1;
7605                 else if (*p == '[') {
7606                         char *q = p + 1;
7607                         if (*q == '!')
7608                                 q++;
7609                         for (;;) {
7610                                 if (*q == '\\')
7611                                         q++;
7612                                 if (*q == '/' || *q == '\0')
7613                                         break;
7614                                 if (*++q == ']') {
7615                                         metaflag = 1;
7616                                         break;
7617                                 }
7618                         }
7619                 } else {
7620                         if (*p == '\\')
7621                                 esc++;
7622                         if (p[esc] == '/') {
7623                                 if (metaflag)
7624                                         break;
7625                                 start = p + esc + 1;
7626                         }
7627                 }
7628         }
7629         if (metaflag == 0) {    /* we've reached the end of the file name */
7630                 if (!expdir_len)
7631                         return;
7632                 p = name;
7633                 do {
7634                         if (*p == '\\')
7635                                 p++;
7636                         *enddir++ = *p;
7637                 } while (*p++);
7638                 if (lstat(expdir, &statb) == 0)
7639                         addfname(expdir);
7640                 return;
7641         }
7642         endname = p;
7643         if (name < start) {
7644                 p = name;
7645                 do {
7646                         if (*p == '\\')
7647                                 p++;
7648                         *enddir++ = *p++;
7649                 } while (p < start);
7650         }
7651         *enddir = '\0';
7652         cp = expdir;
7653         expdir_len = enddir - cp;
7654         if (!expdir_len)
7655                 cp = ".";
7656         dirp = opendir(cp);
7657         if (dirp == NULL)
7658                 return;
7659         if (*endname == 0) {
7660                 atend = 1;
7661         } else {
7662                 atend = 0;
7663                 *endname = '\0';
7664                 endname += esc + 1;
7665         }
7666         name_len -= endname - name;
7667         matchdot = 0;
7668         p = start;
7669         if (*p == '\\')
7670                 p++;
7671         if (*p == '.')
7672                 matchdot++;
7673         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7674                 if (dp->d_name[0] == '.' && !matchdot)
7675                         continue;
7676                 if (pmatch(start, dp->d_name)) {
7677                         if (atend) {
7678                                 strcpy(enddir, dp->d_name);
7679                                 addfname(expdir);
7680                         } else {
7681                                 unsigned offset;
7682                                 unsigned len;
7683
7684                                 p = stpcpy(enddir, dp->d_name);
7685                                 *p = '/';
7686
7687                                 offset = p - expdir + 1;
7688                                 len = offset + name_len + NAME_MAX;
7689                                 if (len > expdir_max) {
7690                                         len += PATH_MAX;
7691                                         expdir = ckrealloc(expdir, len);
7692                                         expdir_max = len;
7693                                 }
7694
7695                                 expmeta(exp, endname, name_len, offset);
7696                                 enddir = expdir + expdir_len;
7697                         }
7698                 }
7699         }
7700         closedir(dirp);
7701         if (!atend)
7702                 endname[-esc - 1] = esc ? '\\' : '/';
7703 #undef expdir
7704 #undef expdir_max
7705 }
7706
7707 static struct strlist *
7708 msort(struct strlist *list, int len)
7709 {
7710         struct strlist *p, *q = NULL;
7711         struct strlist **lpp;
7712         int half;
7713         int n;
7714
7715         if (len <= 1)
7716                 return list;
7717         half = len >> 1;
7718         p = list;
7719         for (n = half; --n >= 0;) {
7720                 q = p;
7721                 p = p->next;
7722         }
7723         q->next = NULL;                 /* terminate first half of list */
7724         q = msort(list, half);          /* sort first half of list */
7725         p = msort(p, len - half);               /* sort second half */
7726         lpp = &list;
7727         for (;;) {
7728 #if ENABLE_LOCALE_SUPPORT
7729                 if (strcoll(p->text, q->text) < 0)
7730 #else
7731                 if (strcmp(p->text, q->text) < 0)
7732 #endif
7733                                                 {
7734                         *lpp = p;
7735                         lpp = &p->next;
7736                         p = *lpp;
7737                         if (p == NULL) {
7738                                 *lpp = q;
7739                                 break;
7740                         }
7741                 } else {
7742                         *lpp = q;
7743                         lpp = &q->next;
7744                         q = *lpp;
7745                         if (q == NULL) {
7746                                 *lpp = p;
7747                                 break;
7748                         }
7749                 }
7750         }
7751         return list;
7752 }
7753
7754 /*
7755  * Sort the results of file name expansion.  It calculates the number of
7756  * strings to sort and then calls msort (short for merge sort) to do the
7757  * work.
7758  */
7759 static struct strlist *
7760 expsort(struct strlist *str)
7761 {
7762         int len;
7763         struct strlist *sp;
7764
7765         len = 0;
7766         for (sp = str; sp; sp = sp->next)
7767                 len++;
7768         return msort(str, len);
7769 }
7770
7771 static void
7772 expandmeta(struct strlist *str /*, int flag*/)
7773 {
7774         /* TODO - EXP_REDIR */
7775
7776         while (str) {
7777                 exp_t exp;
7778                 struct strlist **savelastp;
7779                 struct strlist *sp;
7780                 char *p;
7781                 unsigned len;
7782
7783                 if (fflag)
7784                         goto nometa;
7785                 if (!hasmeta(str->text))
7786                         goto nometa;
7787                 savelastp = exparg.lastp;
7788
7789                 INT_OFF;
7790                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7791                 len = strlen(p);
7792                 exp.dir_max = len + PATH_MAX;
7793                 exp.dir = ckmalloc(exp.dir_max);
7794
7795                 expmeta(&exp, p, len, 0);
7796                 free(exp.dir);
7797                 if (p != str->text)
7798                         free(p);
7799                 INT_ON;
7800                 if (exparg.lastp == savelastp) {
7801                         /*
7802                          * no matches
7803                          */
7804  nometa:
7805                         *exparg.lastp = str;
7806                         rmescapes(str->text, 0, NULL);
7807                         exparg.lastp = &str->next;
7808                 } else {
7809                         *exparg.lastp = NULL;
7810                         *savelastp = sp = expsort(*savelastp);
7811                         while (sp->next != NULL)
7812                                 sp = sp->next;
7813                         exparg.lastp = &sp->next;
7814                 }
7815                 str = str->next;
7816         }
7817 }
7818 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7819
7820 /*
7821  * Perform variable substitution and command substitution on an argument,
7822  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7823  * perform splitting and file name expansion.  When arglist is NULL, perform
7824  * here document expansion.
7825  */
7826 static void
7827 expandarg(union node *arg, struct arglist *arglist, int flag)
7828 {
7829         struct strlist *sp;
7830         char *p;
7831
7832         argbackq = arg->narg.backquote;
7833         STARTSTACKSTR(expdest);
7834         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7835         argstr(arg->narg.text, flag);
7836         p = _STPUTC('\0', expdest);
7837         expdest = p - 1;
7838         if (arglist == NULL) {
7839                 /* here document expanded */
7840                 goto out;
7841         }
7842         p = grabstackstr(p);
7843         TRACE(("expandarg: p:'%s'\n", p));
7844         exparg.lastp = &exparg.list;
7845         /*
7846          * TODO - EXP_REDIR
7847          */
7848         if (flag & EXP_FULL) {
7849                 ifsbreakup(p, &exparg);
7850                 *exparg.lastp = NULL;
7851                 exparg.lastp = &exparg.list;
7852                 expandmeta(exparg.list /*, flag*/);
7853         } else {
7854                 sp = stzalloc(sizeof(*sp));
7855                 sp->text = p;
7856                 *exparg.lastp = sp;
7857                 exparg.lastp = &sp->next;
7858         }
7859         *exparg.lastp = NULL;
7860         if (exparg.list) {
7861                 *arglist->lastp = exparg.list;
7862                 arglist->lastp = exparg.lastp;
7863         }
7864
7865  out:
7866         ifsfree();
7867 }
7868
7869 /*
7870  * Expand shell variables and backquotes inside a here document.
7871  */
7872 static void
7873 expandhere(union node *arg, int fd)
7874 {
7875         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7876         full_write(fd, stackblock(), expdest - (char *)stackblock());
7877 }
7878
7879 /*
7880  * Returns true if the pattern matches the string.
7881  */
7882 static int
7883 patmatch(char *pattern, const char *string)
7884 {
7885         char *p = preglob(pattern, 0);
7886         int r = pmatch(p, string);
7887         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7888         return r;
7889 }
7890
7891 /*
7892  * See if a pattern matches in a case statement.
7893  */
7894 static int
7895 casematch(union node *pattern, char *val)
7896 {
7897         struct stackmark smark;
7898         int result;
7899
7900         setstackmark(&smark);
7901         argbackq = pattern->narg.backquote;
7902         STARTSTACKSTR(expdest);
7903         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7904         STACKSTRNUL(expdest);
7905         ifsfree();
7906         result = patmatch(stackblock(), val);
7907         popstackmark(&smark);
7908         return result;
7909 }
7910
7911
7912 /* ============ find_command */
7913
7914 struct builtincmd {
7915         const char *name;
7916         int (*builtin)(int, char **) FAST_FUNC;
7917         /* unsigned flags; */
7918 };
7919 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7920 /* "regular" builtins always take precedence over commands,
7921  * regardless of PATH=....%builtin... position */
7922 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7923 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7924
7925 struct cmdentry {
7926         smallint cmdtype;       /* CMDxxx */
7927         union param {
7928                 int index;
7929                 /* index >= 0 for commands without path (slashes) */
7930                 /* (TODO: what exactly does the value mean? PATH position?) */
7931                 /* index == -1 for commands with slashes */
7932                 /* index == (-2 - applet_no) for NOFORK applets */
7933                 const struct builtincmd *cmd;
7934                 struct funcnode *func;
7935         } u;
7936 };
7937 /* values of cmdtype */
7938 #define CMDUNKNOWN      -1      /* no entry in table for command */
7939 #define CMDNORMAL       0       /* command is an executable program */
7940 #define CMDFUNCTION     1       /* command is a shell function */
7941 #define CMDBUILTIN      2       /* command is a shell builtin */
7942
7943 /* action to find_command() */
7944 #define DO_ERR          0x01    /* prints errors */
7945 #define DO_ABS          0x02    /* checks absolute paths */
7946 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7947 #define DO_ALTPATH      0x08    /* using alternate path */
7948 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7949
7950 static void find_command(char *, struct cmdentry *, int, const char *);
7951
7952
7953 /* ============ Hashing commands */
7954
7955 /*
7956  * When commands are first encountered, they are entered in a hash table.
7957  * This ensures that a full path search will not have to be done for them
7958  * on each invocation.
7959  *
7960  * We should investigate converting to a linear search, even though that
7961  * would make the command name "hash" a misnomer.
7962  */
7963
7964 struct tblentry {
7965         struct tblentry *next;  /* next entry in hash chain */
7966         union param param;      /* definition of builtin function */
7967         smallint cmdtype;       /* CMDxxx */
7968         char rehash;            /* if set, cd done since entry created */
7969         char cmdname[1];        /* name of command */
7970 };
7971
7972 static struct tblentry **cmdtable;
7973 #define INIT_G_cmdtable() do { \
7974         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7975 } while (0)
7976
7977 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7978
7979
7980 static void
7981 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7982 {
7983 #if ENABLE_FEATURE_SH_STANDALONE
7984         if (applet_no >= 0) {
7985                 if (APPLET_IS_NOEXEC(applet_no)) {
7986                         clearenv();
7987                         while (*envp)
7988                                 putenv(*envp++);
7989                         popredir(/*drop:*/ 1);
7990                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7991                 }
7992                 /* re-exec ourselves with the new arguments */
7993                 execve(bb_busybox_exec_path, argv, envp);
7994                 /* If they called chroot or otherwise made the binary no longer
7995                  * executable, fall through */
7996         }
7997 #endif
7998
7999  repeat:
8000 #ifdef SYSV
8001         do {
8002                 execve(cmd, argv, envp);
8003         } while (errno == EINTR);
8004 #else
8005         execve(cmd, argv, envp);
8006 #endif
8007         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8008                 /* Run "cmd" as a shell script:
8009                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8010                  * "If the execve() function fails with ENOEXEC, the shell
8011                  * shall execute a command equivalent to having a shell invoked
8012                  * with the command name as its first operand,
8013                  * with any remaining arguments passed to the new shell"
8014                  *
8015                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8016                  * just call ourselves.
8017                  *
8018                  * Note that bash reads ~80 chars of the file, and if it sees
8019                  * a zero byte before it sees newline, it doesn't try to
8020                  * interpret it, but fails with "cannot execute binary file"
8021                  * message and exit code 126. For one, this prevents attempts
8022                  * to interpret foreign ELF binaries as shell scripts.
8023                  */
8024                 argv[0] = (char*) cmd;
8025                 cmd = bb_busybox_exec_path;
8026                 /* NB: this is only possible because all callers of shellexec()
8027                  * ensure that the argv[-1] slot exists!
8028                  */
8029                 argv--;
8030                 argv[0] = (char*) "ash";
8031                 goto repeat;
8032         }
8033 }
8034
8035 /*
8036  * Exec a program.  Never returns.  If you change this routine, you may
8037  * have to change the find_command routine as well.
8038  * argv[-1] must exist and be writable! See tryexec() for why.
8039  */
8040 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8041 static void shellexec(char *prog, char **argv, const char *path, int idx)
8042 {
8043         char *cmdname;
8044         int e;
8045         char **envp;
8046         int exerrno;
8047         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8048
8049         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8050         if (strchr(prog, '/') != NULL
8051 #if ENABLE_FEATURE_SH_STANDALONE
8052          || (applet_no = find_applet_by_name(prog)) >= 0
8053 #endif
8054         ) {
8055                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8056                 if (applet_no >= 0) {
8057                         /* We tried execing ourself, but it didn't work.
8058                          * Maybe /proc/self/exe doesn't exist?
8059                          * Try $PATH search.
8060                          */
8061                         goto try_PATH;
8062                 }
8063                 e = errno;
8064         } else {
8065  try_PATH:
8066                 e = ENOENT;
8067                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8068                         if (--idx < 0 && pathopt == NULL) {
8069                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8070                                 if (errno != ENOENT && errno != ENOTDIR)
8071                                         e = errno;
8072                         }
8073                         stunalloc(cmdname);
8074                 }
8075         }
8076
8077         /* Map to POSIX errors */
8078         switch (e) {
8079         case EACCES:
8080                 exerrno = 126;
8081                 break;
8082         case ENOENT:
8083                 exerrno = 127;
8084                 break;
8085         default:
8086                 exerrno = 2;
8087                 break;
8088         }
8089         exitstatus = exerrno;
8090         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8091                 prog, e, suppress_int));
8092         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8093         /* NOTREACHED */
8094 }
8095
8096 static void
8097 printentry(struct tblentry *cmdp)
8098 {
8099         int idx;
8100         const char *path;
8101         char *name;
8102
8103         idx = cmdp->param.index;
8104         path = pathval();
8105         do {
8106                 name = path_advance(&path, cmdp->cmdname);
8107                 stunalloc(name);
8108         } while (--idx >= 0);
8109         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8110 }
8111
8112 /*
8113  * Clear out command entries.  The argument specifies the first entry in
8114  * PATH which has changed.
8115  */
8116 static void
8117 clearcmdentry(int firstchange)
8118 {
8119         struct tblentry **tblp;
8120         struct tblentry **pp;
8121         struct tblentry *cmdp;
8122
8123         INT_OFF;
8124         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8125                 pp = tblp;
8126                 while ((cmdp = *pp) != NULL) {
8127                         if ((cmdp->cmdtype == CMDNORMAL &&
8128                              cmdp->param.index >= firstchange)
8129                          || (cmdp->cmdtype == CMDBUILTIN &&
8130                              builtinloc >= firstchange)
8131                         ) {
8132                                 *pp = cmdp->next;
8133                                 free(cmdp);
8134                         } else {
8135                                 pp = &cmdp->next;
8136                         }
8137                 }
8138         }
8139         INT_ON;
8140 }
8141
8142 /*
8143  * Locate a command in the command hash table.  If "add" is nonzero,
8144  * add the command to the table if it is not already present.  The
8145  * variable "lastcmdentry" is set to point to the address of the link
8146  * pointing to the entry, so that delete_cmd_entry can delete the
8147  * entry.
8148  *
8149  * Interrupts must be off if called with add != 0.
8150  */
8151 static struct tblentry **lastcmdentry;
8152
8153 static struct tblentry *
8154 cmdlookup(const char *name, int add)
8155 {
8156         unsigned int hashval;
8157         const char *p;
8158         struct tblentry *cmdp;
8159         struct tblentry **pp;
8160
8161         p = name;
8162         hashval = (unsigned char)*p << 4;
8163         while (*p)
8164                 hashval += (unsigned char)*p++;
8165         hashval &= 0x7FFF;
8166         pp = &cmdtable[hashval % CMDTABLESIZE];
8167         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8168                 if (strcmp(cmdp->cmdname, name) == 0)
8169                         break;
8170                 pp = &cmdp->next;
8171         }
8172         if (add && cmdp == NULL) {
8173                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8174                                 + strlen(name)
8175                                 /* + 1 - already done because
8176                                  * tblentry::cmdname is char[1] */);
8177                 /*cmdp->next = NULL; - ckzalloc did it */
8178                 cmdp->cmdtype = CMDUNKNOWN;
8179                 strcpy(cmdp->cmdname, name);
8180         }
8181         lastcmdentry = pp;
8182         return cmdp;
8183 }
8184
8185 /*
8186  * Delete the command entry returned on the last lookup.
8187  */
8188 static void
8189 delete_cmd_entry(void)
8190 {
8191         struct tblentry *cmdp;
8192
8193         INT_OFF;
8194         cmdp = *lastcmdentry;
8195         *lastcmdentry = cmdp->next;
8196         if (cmdp->cmdtype == CMDFUNCTION)
8197                 freefunc(cmdp->param.func);
8198         free(cmdp);
8199         INT_ON;
8200 }
8201
8202 /*
8203  * Add a new command entry, replacing any existing command entry for
8204  * the same name - except special builtins.
8205  */
8206 static void
8207 addcmdentry(char *name, struct cmdentry *entry)
8208 {
8209         struct tblentry *cmdp;
8210
8211         cmdp = cmdlookup(name, 1);
8212         if (cmdp->cmdtype == CMDFUNCTION) {
8213                 freefunc(cmdp->param.func);
8214         }
8215         cmdp->cmdtype = entry->cmdtype;
8216         cmdp->param = entry->u;
8217         cmdp->rehash = 0;
8218 }
8219
8220 static int FAST_FUNC
8221 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8222 {
8223         struct tblentry **pp;
8224         struct tblentry *cmdp;
8225         int c;
8226         struct cmdentry entry;
8227         char *name;
8228
8229         if (nextopt("r") != '\0') {
8230                 clearcmdentry(0);
8231                 return 0;
8232         }
8233
8234         if (*argptr == NULL) {
8235                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8236                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8237                                 if (cmdp->cmdtype == CMDNORMAL)
8238                                         printentry(cmdp);
8239                         }
8240                 }
8241                 return 0;
8242         }
8243
8244         c = 0;
8245         while ((name = *argptr) != NULL) {
8246                 cmdp = cmdlookup(name, 0);
8247                 if (cmdp != NULL
8248                  && (cmdp->cmdtype == CMDNORMAL
8249                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8250                 ) {
8251                         delete_cmd_entry();
8252                 }
8253                 find_command(name, &entry, DO_ERR, pathval());
8254                 if (entry.cmdtype == CMDUNKNOWN)
8255                         c = 1;
8256                 argptr++;
8257         }
8258         return c;
8259 }
8260
8261 /*
8262  * Called when a cd is done.  Marks all commands so the next time they
8263  * are executed they will be rehashed.
8264  */
8265 static void
8266 hashcd(void)
8267 {
8268         struct tblentry **pp;
8269         struct tblentry *cmdp;
8270
8271         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8272                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8273                         if (cmdp->cmdtype == CMDNORMAL
8274                          || (cmdp->cmdtype == CMDBUILTIN
8275                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8276                              && builtinloc > 0)
8277                         ) {
8278                                 cmdp->rehash = 1;
8279                         }
8280                 }
8281         }
8282 }
8283
8284 /*
8285  * Fix command hash table when PATH changed.
8286  * Called before PATH is changed.  The argument is the new value of PATH;
8287  * pathval() still returns the old value at this point.
8288  * Called with interrupts off.
8289  */
8290 static void FAST_FUNC
8291 changepath(const char *new)
8292 {
8293         const char *old;
8294         int firstchange;
8295         int idx;
8296         int idx_bltin;
8297
8298         old = pathval();
8299         firstchange = 9999;     /* assume no change */
8300         idx = 0;
8301         idx_bltin = -1;
8302         for (;;) {
8303                 if (*old != *new) {
8304                         firstchange = idx;
8305                         if ((*old == '\0' && *new == ':')
8306                          || (*old == ':' && *new == '\0')
8307                         ) {
8308                                 firstchange++;
8309                         }
8310                         old = new;      /* ignore subsequent differences */
8311                 }
8312                 if (*new == '\0')
8313                         break;
8314                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8315                         idx_bltin = idx;
8316                 if (*new == ':')
8317                         idx++;
8318                 new++;
8319                 old++;
8320         }
8321         if (builtinloc < 0 && idx_bltin >= 0)
8322                 builtinloc = idx_bltin;             /* zap builtins */
8323         if (builtinloc >= 0 && idx_bltin < 0)
8324                 firstchange = 0;
8325         clearcmdentry(firstchange);
8326         builtinloc = idx_bltin;
8327 }
8328 enum {
8329         TEOF,
8330         TNL,
8331         TREDIR,
8332         TWORD,
8333         TSEMI,
8334         TBACKGND,
8335         TAND,
8336         TOR,
8337         TPIPE,
8338         TLP,
8339         TRP,
8340         TENDCASE,
8341         TENDBQUOTE,
8342         TNOT,
8343         TCASE,
8344         TDO,
8345         TDONE,
8346         TELIF,
8347         TELSE,
8348         TESAC,
8349         TFI,
8350         TFOR,
8351 #if BASH_FUNCTION
8352         TFUNCTION,
8353 #endif
8354         TIF,
8355         TIN,
8356         TTHEN,
8357         TUNTIL,
8358         TWHILE,
8359         TBEGIN,
8360         TEND
8361 };
8362 typedef smallint token_id_t;
8363
8364 /* Nth bit indicates if token marks the end of a list */
8365 enum {
8366         tokendlist = 0
8367         /*  0 */ | (1u << TEOF)
8368         /*  1 */ | (0u << TNL)
8369         /*  2 */ | (0u << TREDIR)
8370         /*  3 */ | (0u << TWORD)
8371         /*  4 */ | (0u << TSEMI)
8372         /*  5 */ | (0u << TBACKGND)
8373         /*  6 */ | (0u << TAND)
8374         /*  7 */ | (0u << TOR)
8375         /*  8 */ | (0u << TPIPE)
8376         /*  9 */ | (0u << TLP)
8377         /* 10 */ | (1u << TRP)
8378         /* 11 */ | (1u << TENDCASE)
8379         /* 12 */ | (1u << TENDBQUOTE)
8380         /* 13 */ | (0u << TNOT)
8381         /* 14 */ | (0u << TCASE)
8382         /* 15 */ | (1u << TDO)
8383         /* 16 */ | (1u << TDONE)
8384         /* 17 */ | (1u << TELIF)
8385         /* 18 */ | (1u << TELSE)
8386         /* 19 */ | (1u << TESAC)
8387         /* 20 */ | (1u << TFI)
8388         /* 21 */ | (0u << TFOR)
8389 #if BASH_FUNCTION
8390         /* 22 */ | (0u << TFUNCTION)
8391 #endif
8392         /* 23 */ | (0u << TIF)
8393         /* 24 */ | (0u << TIN)
8394         /* 25 */ | (1u << TTHEN)
8395         /* 26 */ | (0u << TUNTIL)
8396         /* 27 */ | (0u << TWHILE)
8397         /* 28 */ | (0u << TBEGIN)
8398         /* 29 */ | (1u << TEND)
8399         , /* thus far 29 bits used */
8400 };
8401
8402 static const char *const tokname_array[] = {
8403         "end of file",
8404         "newline",
8405         "redirection",
8406         "word",
8407         ";",
8408         "&",
8409         "&&",
8410         "||",
8411         "|",
8412         "(",
8413         ")",
8414         ";;",
8415         "`",
8416 #define KWDOFFSET 13
8417         /* the following are keywords */
8418         "!",
8419         "case",
8420         "do",
8421         "done",
8422         "elif",
8423         "else",
8424         "esac",
8425         "fi",
8426         "for",
8427 #if BASH_FUNCTION
8428         "function",
8429 #endif
8430         "if",
8431         "in",
8432         "then",
8433         "until",
8434         "while",
8435         "{",
8436         "}",
8437 };
8438
8439 /* Wrapper around strcmp for qsort/bsearch/... */
8440 static int
8441 pstrcmp(const void *a, const void *b)
8442 {
8443         return strcmp((char*)a, *(char**)b);
8444 }
8445
8446 static const char *const *
8447 findkwd(const char *s)
8448 {
8449         return bsearch(s, tokname_array + KWDOFFSET,
8450                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8451                         sizeof(tokname_array[0]), pstrcmp);
8452 }
8453
8454 /*
8455  * Locate and print what a word is...
8456  */
8457 static int
8458 describe_command(char *command, const char *path, int describe_command_verbose)
8459 {
8460         struct cmdentry entry;
8461 #if ENABLE_ASH_ALIAS
8462         const struct alias *ap;
8463 #endif
8464
8465         path = path ? path : pathval();
8466
8467         if (describe_command_verbose) {
8468                 out1str(command);
8469         }
8470
8471         /* First look at the keywords */
8472         if (findkwd(command)) {
8473                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8474                 goto out;
8475         }
8476
8477 #if ENABLE_ASH_ALIAS
8478         /* Then look at the aliases */
8479         ap = lookupalias(command, 0);
8480         if (ap != NULL) {
8481                 if (!describe_command_verbose) {
8482                         out1str("alias ");
8483                         printalias(ap);
8484                         return 0;
8485                 }
8486                 out1fmt(" is an alias for %s", ap->val);
8487                 goto out;
8488         }
8489 #endif
8490         /* Brute force */
8491         find_command(command, &entry, DO_ABS, path);
8492
8493         switch (entry.cmdtype) {
8494         case CMDNORMAL: {
8495                 int j = entry.u.index;
8496                 char *p;
8497                 if (j < 0) {
8498                         p = command;
8499                 } else {
8500                         do {
8501                                 p = path_advance(&path, command);
8502                                 stunalloc(p);
8503                         } while (--j >= 0);
8504                 }
8505                 if (describe_command_verbose) {
8506                         out1fmt(" is %s", p);
8507                 } else {
8508                         out1str(p);
8509                 }
8510                 break;
8511         }
8512
8513         case CMDFUNCTION:
8514                 if (describe_command_verbose) {
8515                         out1str(" is a shell function");
8516                 } else {
8517                         out1str(command);
8518                 }
8519                 break;
8520
8521         case CMDBUILTIN:
8522                 if (describe_command_verbose) {
8523                         out1fmt(" is a %sshell builtin",
8524                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8525                                         "special " : nullstr
8526                         );
8527                 } else {
8528                         out1str(command);
8529                 }
8530                 break;
8531
8532         default:
8533                 if (describe_command_verbose) {
8534                         out1str(": not found\n");
8535                 }
8536                 return 127;
8537         }
8538  out:
8539         out1str("\n");
8540         return 0;
8541 }
8542
8543 static int FAST_FUNC
8544 typecmd(int argc UNUSED_PARAM, char **argv)
8545 {
8546         int i = 1;
8547         int err = 0;
8548         int verbose = 1;
8549
8550         /* type -p ... ? (we don't bother checking for 'p') */
8551         if (argv[1] && argv[1][0] == '-') {
8552                 i++;
8553                 verbose = 0;
8554         }
8555         while (argv[i]) {
8556                 err |= describe_command(argv[i++], NULL, verbose);
8557         }
8558         return err;
8559 }
8560
8561 #if ENABLE_ASH_CMDCMD
8562 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8563 static char **
8564 parse_command_args(char **argv, const char **path)
8565 {
8566         char *cp, c;
8567
8568         for (;;) {
8569                 cp = *++argv;
8570                 if (!cp)
8571                         return NULL;
8572                 if (*cp++ != '-')
8573                         break;
8574                 c = *cp++;
8575                 if (!c)
8576                         break;
8577                 if (c == '-' && !*cp) {
8578                         if (!*++argv)
8579                                 return NULL;
8580                         break;
8581                 }
8582                 do {
8583                         switch (c) {
8584                         case 'p':
8585                                 *path = bb_default_path;
8586                                 break;
8587                         default:
8588                                 /* run 'typecmd' for other options */
8589                                 return NULL;
8590                         }
8591                         c = *cp++;
8592                 } while (c);
8593         }
8594         return argv;
8595 }
8596
8597 static int FAST_FUNC
8598 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8599 {
8600         char *cmd;
8601         int c;
8602         enum {
8603                 VERIFY_BRIEF = 1,
8604                 VERIFY_VERBOSE = 2,
8605         } verify = 0;
8606         const char *path = NULL;
8607
8608         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8609          * never reaches this function.
8610          */
8611
8612         while ((c = nextopt("pvV")) != '\0')
8613                 if (c == 'V')
8614                         verify |= VERIFY_VERBOSE;
8615                 else if (c == 'v')
8616                         /*verify |= VERIFY_BRIEF*/;
8617 #if DEBUG
8618                 else if (c != 'p')
8619                         abort();
8620 #endif
8621                 else
8622                         path = bb_default_path;
8623
8624         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8625         cmd = *argptr;
8626         if (/*verify && */ cmd)
8627                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8628
8629         return 0;
8630 }
8631 #endif
8632
8633
8634 /*static int funcblocksize;     // size of structures in function */
8635 /*static int funcstringsize;    // size of strings in node */
8636 static void *funcblock;         /* block to allocate function from */
8637 static char *funcstring_end;    /* end of block to allocate strings from */
8638
8639 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8640         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8641         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8642         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8643         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8644         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8645         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8646         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8647         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8648         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8649         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8650         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8651         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8652         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8653         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8654         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8655         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8656         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8657 #if BASH_REDIR_OUTPUT
8658         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8659 #endif
8660         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8661         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8662         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8663         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8664         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8665         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8666         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8667         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8668         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8669 };
8670
8671 static int calcsize(int funcblocksize, union node *n);
8672
8673 static int
8674 sizenodelist(int funcblocksize, struct nodelist *lp)
8675 {
8676         while (lp) {
8677                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8678                 funcblocksize = calcsize(funcblocksize, lp->n);
8679                 lp = lp->next;
8680         }
8681         return funcblocksize;
8682 }
8683
8684 static int
8685 calcsize(int funcblocksize, union node *n)
8686 {
8687         if (n == NULL)
8688                 return funcblocksize;
8689         funcblocksize += nodesize[n->type];
8690         switch (n->type) {
8691         case NCMD:
8692                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8693                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8694                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8695                 break;
8696         case NPIPE:
8697                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8698                 break;
8699         case NREDIR:
8700         case NBACKGND:
8701         case NSUBSHELL:
8702                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8703                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8704                 break;
8705         case NAND:
8706         case NOR:
8707         case NSEMI:
8708         case NWHILE:
8709         case NUNTIL:
8710                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8711                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8712                 break;
8713         case NIF:
8714                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8715                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8716                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8717                 break;
8718         case NFOR:
8719                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8720                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8721                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8722                 break;
8723         case NCASE:
8724                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8725                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8726                 break;
8727         case NCLIST:
8728                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8729                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8730                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8731                 break;
8732         case NDEFUN:
8733                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8734                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8735                 break;
8736         case NARG:
8737                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8738                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8739                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8740                 break;
8741         case NTO:
8742 #if BASH_REDIR_OUTPUT
8743         case NTO2:
8744 #endif
8745         case NCLOBBER:
8746         case NFROM:
8747         case NFROMTO:
8748         case NAPPEND:
8749                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8750                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8751                 break;
8752         case NTOFD:
8753         case NFROMFD:
8754                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8755                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8756         break;
8757         case NHERE:
8758         case NXHERE:
8759                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8760                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8761                 break;
8762         case NNOT:
8763                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8764                 break;
8765         };
8766         return funcblocksize;
8767 }
8768
8769 static char *
8770 nodeckstrdup(char *s)
8771 {
8772         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8773         return strcpy(funcstring_end, s);
8774 }
8775
8776 static union node *copynode(union node *);
8777
8778 static struct nodelist *
8779 copynodelist(struct nodelist *lp)
8780 {
8781         struct nodelist *start;
8782         struct nodelist **lpp;
8783
8784         lpp = &start;
8785         while (lp) {
8786                 *lpp = funcblock;
8787                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8788                 (*lpp)->n = copynode(lp->n);
8789                 lp = lp->next;
8790                 lpp = &(*lpp)->next;
8791         }
8792         *lpp = NULL;
8793         return start;
8794 }
8795
8796 static union node *
8797 copynode(union node *n)
8798 {
8799         union node *new;
8800
8801         if (n == NULL)
8802                 return NULL;
8803         new = funcblock;
8804         funcblock = (char *) funcblock + nodesize[n->type];
8805
8806         switch (n->type) {
8807         case NCMD:
8808                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8809                 new->ncmd.args = copynode(n->ncmd.args);
8810                 new->ncmd.assign = copynode(n->ncmd.assign);
8811                 new->ncmd.linno = n->ncmd.linno;
8812                 break;
8813         case NPIPE:
8814                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8815                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8816                 break;
8817         case NREDIR:
8818         case NBACKGND:
8819         case NSUBSHELL:
8820                 new->nredir.redirect = copynode(n->nredir.redirect);
8821                 new->nredir.n = copynode(n->nredir.n);
8822                 new->nredir.linno = n->nredir.linno;
8823                 break;
8824         case NAND:
8825         case NOR:
8826         case NSEMI:
8827         case NWHILE:
8828         case NUNTIL:
8829                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8830                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8831                 break;
8832         case NIF:
8833                 new->nif.elsepart = copynode(n->nif.elsepart);
8834                 new->nif.ifpart = copynode(n->nif.ifpart);
8835                 new->nif.test = copynode(n->nif.test);
8836                 break;
8837         case NFOR:
8838                 new->nfor.var = nodeckstrdup(n->nfor.var);
8839                 new->nfor.body = copynode(n->nfor.body);
8840                 new->nfor.args = copynode(n->nfor.args);
8841                 new->nfor.linno = n->nfor.linno;
8842                 break;
8843         case NCASE:
8844                 new->ncase.cases = copynode(n->ncase.cases);
8845                 new->ncase.expr = copynode(n->ncase.expr);
8846                 new->ncase.linno = n->ncase.linno;
8847                 break;
8848         case NCLIST:
8849                 new->nclist.body = copynode(n->nclist.body);
8850                 new->nclist.pattern = copynode(n->nclist.pattern);
8851                 new->nclist.next = copynode(n->nclist.next);
8852                 break;
8853         case NDEFUN:
8854                 new->ndefun.body = copynode(n->ndefun.body);
8855                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8856                 new->ndefun.linno = n->ndefun.linno;
8857                 break;
8858         case NARG:
8859                 new->narg.backquote = copynodelist(n->narg.backquote);
8860                 new->narg.text = nodeckstrdup(n->narg.text);
8861                 new->narg.next = copynode(n->narg.next);
8862                 break;
8863         case NTO:
8864 #if BASH_REDIR_OUTPUT
8865         case NTO2:
8866 #endif
8867         case NCLOBBER:
8868         case NFROM:
8869         case NFROMTO:
8870         case NAPPEND:
8871                 new->nfile.fname = copynode(n->nfile.fname);
8872                 new->nfile.fd = n->nfile.fd;
8873                 new->nfile.next = copynode(n->nfile.next);
8874                 break;
8875         case NTOFD:
8876         case NFROMFD:
8877                 new->ndup.vname = copynode(n->ndup.vname);
8878                 new->ndup.dupfd = n->ndup.dupfd;
8879                 new->ndup.fd = n->ndup.fd;
8880                 new->ndup.next = copynode(n->ndup.next);
8881                 break;
8882         case NHERE:
8883         case NXHERE:
8884                 new->nhere.doc = copynode(n->nhere.doc);
8885                 new->nhere.fd = n->nhere.fd;
8886                 new->nhere.next = copynode(n->nhere.next);
8887                 break;
8888         case NNOT:
8889                 new->nnot.com = copynode(n->nnot.com);
8890                 break;
8891         };
8892         new->type = n->type;
8893         return new;
8894 }
8895
8896 /*
8897  * Make a copy of a parse tree.
8898  */
8899 static struct funcnode *
8900 copyfunc(union node *n)
8901 {
8902         struct funcnode *f;
8903         size_t blocksize;
8904
8905         /*funcstringsize = 0;*/
8906         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8907         f = ckzalloc(blocksize /* + funcstringsize */);
8908         funcblock = (char *) f + offsetof(struct funcnode, n);
8909         funcstring_end = (char *) f + blocksize;
8910         copynode(n);
8911         /* f->count = 0; - ckzalloc did it */
8912         return f;
8913 }
8914
8915 /*
8916  * Define a shell function.
8917  */
8918 static void
8919 defun(union node *func)
8920 {
8921         struct cmdentry entry;
8922
8923         INT_OFF;
8924         entry.cmdtype = CMDFUNCTION;
8925         entry.u.func = copyfunc(func);
8926         addcmdentry(func->ndefun.text, &entry);
8927         INT_ON;
8928 }
8929
8930 /* Reasons for skipping commands (see comment on breakcmd routine) */
8931 #define SKIPBREAK      (1 << 0)
8932 #define SKIPCONT       (1 << 1)
8933 #define SKIPFUNC       (1 << 2)
8934 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8935 static int skipcount;           /* number of levels to skip */
8936 static int loopnest;            /* current loop nesting level */
8937 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8938
8939 /* Forward decl way out to parsing code - dotrap needs it */
8940 static int evalstring(char *s, int flags);
8941
8942 /* Called to execute a trap.
8943  * Single callsite - at the end of evaltree().
8944  * If we return non-zero, evaltree raises EXEXIT exception.
8945  *
8946  * Perhaps we should avoid entering new trap handlers
8947  * while we are executing a trap handler. [is it a TODO?]
8948  */
8949 static void
8950 dotrap(void)
8951 {
8952         uint8_t *g;
8953         int sig;
8954         uint8_t last_status;
8955
8956         if (!pending_sig)
8957                 return;
8958
8959         last_status = exitstatus;
8960         pending_sig = 0;
8961         barrier();
8962
8963         TRACE(("dotrap entered\n"));
8964         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8965                 char *p;
8966
8967                 if (!*g)
8968                         continue;
8969
8970                 if (evalskip) {
8971                         pending_sig = sig;
8972                         break;
8973                 }
8974
8975                 p = trap[sig];
8976                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8977                  * don't upset it by resetting gotsig[SIGINT-1] */
8978                 if (sig == SIGINT && !p)
8979                         continue;
8980
8981                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8982                 *g = 0;
8983                 if (!p)
8984                         continue;
8985                 evalstring(p, 0);
8986         }
8987         exitstatus = last_status;
8988         TRACE(("dotrap returns\n"));
8989 }
8990
8991 /* forward declarations - evaluation is fairly recursive business... */
8992 static int evalloop(union node *, int);
8993 static int evalfor(union node *, int);
8994 static int evalcase(union node *, int);
8995 static int evalsubshell(union node *, int);
8996 static void expredir(union node *);
8997 static int evalpipe(union node *, int);
8998 static int evalcommand(union node *, int);
8999 static int evalbltin(const struct builtincmd *, int, char **, int);
9000 static void prehash(union node *);
9001
9002 /*
9003  * Evaluate a parse tree.  The value is left in the global variable
9004  * exitstatus.
9005  */
9006 static int
9007 evaltree(union node *n, int flags)
9008 {
9009         int checkexit = 0;
9010         int (*evalfn)(union node *, int);
9011         int status = 0;
9012
9013         if (n == NULL) {
9014                 TRACE(("evaltree(NULL) called\n"));
9015                 goto out;
9016         }
9017         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9018
9019         dotrap();
9020
9021         switch (n->type) {
9022         default:
9023 #if DEBUG
9024                 out1fmt("Node type = %d\n", n->type);
9025                 fflush_all();
9026                 break;
9027 #endif
9028         case NNOT:
9029                 status = !evaltree(n->nnot.com, EV_TESTED);
9030                 goto setstatus;
9031         case NREDIR:
9032                 errlinno = lineno = n->nredir.linno;
9033                 if (funcline)
9034                         lineno -= funcline - 1;
9035                 expredir(n->nredir.redirect);
9036                 pushredir(n->nredir.redirect);
9037                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9038                 if (!status) {
9039                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9040                 }
9041                 if (n->nredir.redirect)
9042                         popredir(/*drop:*/ 0);
9043                 goto setstatus;
9044         case NCMD:
9045                 evalfn = evalcommand;
9046  checkexit:
9047                 if (eflag && !(flags & EV_TESTED))
9048                         checkexit = ~0;
9049                 goto calleval;
9050         case NFOR:
9051                 evalfn = evalfor;
9052                 goto calleval;
9053         case NWHILE:
9054         case NUNTIL:
9055                 evalfn = evalloop;
9056                 goto calleval;
9057         case NSUBSHELL:
9058         case NBACKGND:
9059                 evalfn = evalsubshell;
9060                 goto checkexit;
9061         case NPIPE:
9062                 evalfn = evalpipe;
9063                 goto checkexit;
9064         case NCASE:
9065                 evalfn = evalcase;
9066                 goto calleval;
9067         case NAND:
9068         case NOR:
9069         case NSEMI: {
9070
9071 #if NAND + 1 != NOR
9072 #error NAND + 1 != NOR
9073 #endif
9074 #if NOR + 1 != NSEMI
9075 #error NOR + 1 != NSEMI
9076 #endif
9077                 unsigned is_or = n->type - NAND;
9078                 status = evaltree(
9079                         n->nbinary.ch1,
9080                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9081                 );
9082                 if ((!status) == is_or || evalskip)
9083                         break;
9084                 n = n->nbinary.ch2;
9085  evaln:
9086                 evalfn = evaltree;
9087  calleval:
9088                 status = evalfn(n, flags);
9089                 goto setstatus;
9090         }
9091         case NIF:
9092                 status = evaltree(n->nif.test, EV_TESTED);
9093                 if (evalskip)
9094                         break;
9095                 if (!status) {
9096                         n = n->nif.ifpart;
9097                         goto evaln;
9098                 }
9099                 if (n->nif.elsepart) {
9100                         n = n->nif.elsepart;
9101                         goto evaln;
9102                 }
9103                 status = 0;
9104                 goto setstatus;
9105         case NDEFUN:
9106                 defun(n);
9107                 /* Not necessary. To test it:
9108                  * "false; f() { qwerty; }; echo $?" should print 0.
9109                  */
9110                 /* status = 0; */
9111  setstatus:
9112                 exitstatus = status;
9113                 break;
9114         }
9115  out:
9116         /* Order of checks below is important:
9117          * signal handlers trigger before exit caused by "set -e".
9118          */
9119         dotrap();
9120
9121         if (checkexit & status)
9122                 raise_exception(EXEXIT);
9123         if (flags & EV_EXIT)
9124                 raise_exception(EXEXIT);
9125
9126         TRACE(("leaving evaltree (no interrupts)\n"));
9127         return exitstatus;
9128 }
9129
9130 static int
9131 skiploop(void)
9132 {
9133         int skip = evalskip;
9134
9135         switch (skip) {
9136         case 0:
9137                 break;
9138         case SKIPBREAK:
9139         case SKIPCONT:
9140                 if (--skipcount <= 0) {
9141                         evalskip = 0;
9142                         break;
9143                 }
9144                 skip = SKIPBREAK;
9145                 break;
9146         }
9147         return skip;
9148 }
9149
9150 static int
9151 evalloop(union node *n, int flags)
9152 {
9153         int skip;
9154         int status;
9155
9156         loopnest++;
9157         status = 0;
9158         flags &= EV_TESTED;
9159         do {
9160                 int i;
9161
9162                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9163                 skip = skiploop();
9164                 if (skip == SKIPFUNC)
9165                         status = i;
9166                 if (skip)
9167                         continue;
9168                 if (n->type != NWHILE)
9169                         i = !i;
9170                 if (i != 0)
9171                         break;
9172                 status = evaltree(n->nbinary.ch2, flags);
9173                 skip = skiploop();
9174         } while (!(skip & ~SKIPCONT));
9175         loopnest--;
9176
9177         return status;
9178 }
9179
9180 static int
9181 evalfor(union node *n, int flags)
9182 {
9183         struct arglist arglist;
9184         union node *argp;
9185         struct strlist *sp;
9186         struct stackmark smark;
9187         int status = 0;
9188
9189         errlinno = lineno = n->ncase.linno;
9190         if (funcline)
9191                 lineno -= funcline - 1;
9192
9193         setstackmark(&smark);
9194         arglist.list = NULL;
9195         arglist.lastp = &arglist.list;
9196         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9197                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9198         }
9199         *arglist.lastp = NULL;
9200
9201         loopnest++;
9202         flags &= EV_TESTED;
9203         for (sp = arglist.list; sp; sp = sp->next) {
9204                 setvar0(n->nfor.var, sp->text);
9205                 status = evaltree(n->nfor.body, flags);
9206                 if (skiploop() & ~SKIPCONT)
9207                         break;
9208         }
9209         loopnest--;
9210         popstackmark(&smark);
9211
9212         return status;
9213 }
9214
9215 static int
9216 evalcase(union node *n, int flags)
9217 {
9218         union node *cp;
9219         union node *patp;
9220         struct arglist arglist;
9221         struct stackmark smark;
9222         int status = 0;
9223
9224         errlinno = lineno = n->ncase.linno;
9225         if (funcline)
9226                 lineno -= funcline - 1;
9227
9228         setstackmark(&smark);
9229         arglist.list = NULL;
9230         arglist.lastp = &arglist.list;
9231         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9232         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9233                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9234                         if (casematch(patp, arglist.list->text)) {
9235                                 /* Ensure body is non-empty as otherwise
9236                                  * EV_EXIT may prevent us from setting the
9237                                  * exit status.
9238                                  */
9239                                 if (evalskip == 0 && cp->nclist.body) {
9240                                         status = evaltree(cp->nclist.body, flags);
9241                                 }
9242                                 goto out;
9243                         }
9244                 }
9245         }
9246  out:
9247         popstackmark(&smark);
9248
9249         return status;
9250 }
9251
9252 /*
9253  * Kick off a subshell to evaluate a tree.
9254  */
9255 static int
9256 evalsubshell(union node *n, int flags)
9257 {
9258         struct job *jp;
9259         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9260         int status;
9261
9262         errlinno = lineno = n->nredir.linno;
9263         if (funcline)
9264                 lineno -= funcline - 1;
9265
9266         expredir(n->nredir.redirect);
9267         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9268                 goto nofork;
9269         INT_OFF;
9270         if (backgnd == FORK_FG)
9271                 get_tty_state();
9272         jp = makejob(/*n,*/ 1);
9273         if (forkshell(jp, n, backgnd) == 0) {
9274                 /* child */
9275                 INT_ON;
9276                 flags |= EV_EXIT;
9277                 if (backgnd)
9278                         flags &= ~EV_TESTED;
9279  nofork:
9280                 redirect(n->nredir.redirect, 0);
9281                 evaltreenr(n->nredir.n, flags);
9282                 /* never returns */
9283         }
9284         /* parent */
9285         status = 0;
9286         if (backgnd == FORK_FG)
9287                 status = waitforjob(jp);
9288         INT_ON;
9289         return status;
9290 }
9291
9292 /*
9293  * Compute the names of the files in a redirection list.
9294  */
9295 static void fixredir(union node *, const char *, int);
9296 static void
9297 expredir(union node *n)
9298 {
9299         union node *redir;
9300
9301         for (redir = n; redir; redir = redir->nfile.next) {
9302                 struct arglist fn;
9303
9304                 fn.list = NULL;
9305                 fn.lastp = &fn.list;
9306                 switch (redir->type) {
9307                 case NFROMTO:
9308                 case NFROM:
9309                 case NTO:
9310 #if BASH_REDIR_OUTPUT
9311                 case NTO2:
9312 #endif
9313                 case NCLOBBER:
9314                 case NAPPEND:
9315                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9316                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9317 #if BASH_REDIR_OUTPUT
9318  store_expfname:
9319 #endif
9320 #if 0
9321 // By the design of stack allocator, the loop of this kind:
9322 //      while true; do while true; do break; done </dev/null; done
9323 // will look like a memory leak: ash plans to free expfname's
9324 // of "/dev/null" as soon as it finishes running the loop
9325 // (in this case, never).
9326 // This "fix" is wrong:
9327                         if (redir->nfile.expfname)
9328                                 stunalloc(redir->nfile.expfname);
9329 // It results in corrupted state of stacked allocations.
9330 #endif
9331                         redir->nfile.expfname = fn.list->text;
9332                         break;
9333                 case NFROMFD:
9334                 case NTOFD: /* >& */
9335                         if (redir->ndup.vname) {
9336                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9337                                 if (fn.list == NULL)
9338                                         ash_msg_and_raise_error("redir error");
9339 #if BASH_REDIR_OUTPUT
9340 //FIXME: we used expandarg with different args!
9341                                 if (!isdigit_str9(fn.list->text)) {
9342                                         /* >&file, not >&fd */
9343                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9344                                                 ash_msg_and_raise_error("redir error");
9345                                         redir->type = NTO2;
9346                                         goto store_expfname;
9347                                 }
9348 #endif
9349                                 fixredir(redir, fn.list->text, 1);
9350                         }
9351                         break;
9352                 }
9353         }
9354 }
9355
9356 /*
9357  * Evaluate a pipeline.  All the processes in the pipeline are children
9358  * of the process creating the pipeline.  (This differs from some versions
9359  * of the shell, which make the last process in a pipeline the parent
9360  * of all the rest.)
9361  */
9362 static int
9363 evalpipe(union node *n, int flags)
9364 {
9365         struct job *jp;
9366         struct nodelist *lp;
9367         int pipelen;
9368         int prevfd;
9369         int pip[2];
9370         int status = 0;
9371
9372         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9373         pipelen = 0;
9374         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9375                 pipelen++;
9376         flags |= EV_EXIT;
9377         INT_OFF;
9378         if (n->npipe.pipe_backgnd == 0)
9379                 get_tty_state();
9380         jp = makejob(/*n,*/ pipelen);
9381         prevfd = -1;
9382         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9383                 prehash(lp->n);
9384                 pip[1] = -1;
9385                 if (lp->next) {
9386                         if (pipe(pip) < 0) {
9387                                 close(prevfd);
9388                                 ash_msg_and_raise_perror("can't create pipe");
9389                         }
9390                 }
9391                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9392                         /* child */
9393                         INT_ON;
9394                         if (pip[1] >= 0) {
9395                                 close(pip[0]);
9396                         }
9397                         if (prevfd > 0) {
9398                                 dup2(prevfd, 0);
9399                                 close(prevfd);
9400                         }
9401                         if (pip[1] > 1) {
9402                                 dup2(pip[1], 1);
9403                                 close(pip[1]);
9404                         }
9405                         evaltreenr(lp->n, flags);
9406                         /* never returns */
9407                 }
9408                 /* parent */
9409                 if (prevfd >= 0)
9410                         close(prevfd);
9411                 prevfd = pip[0];
9412                 /* Don't want to trigger debugging */
9413                 if (pip[1] != -1)
9414                         close(pip[1]);
9415         }
9416         if (n->npipe.pipe_backgnd == 0) {
9417                 status = waitforjob(jp);
9418                 TRACE(("evalpipe:  job done exit status %d\n", status));
9419         }
9420         INT_ON;
9421
9422         return status;
9423 }
9424
9425 /*
9426  * Controls whether the shell is interactive or not.
9427  */
9428 static void
9429 setinteractive(int on)
9430 {
9431         static smallint is_interactive;
9432
9433         if (++on == is_interactive)
9434                 return;
9435         is_interactive = on;
9436         setsignal(SIGINT);
9437         setsignal(SIGQUIT);
9438         setsignal(SIGTERM);
9439 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9440         if (is_interactive > 1) {
9441                 /* Looks like they want an interactive shell */
9442                 static smallint did_banner;
9443
9444                 if (!did_banner) {
9445                         /* note: ash and hush share this string */
9446                         out1fmt("\n\n%s %s\n"
9447                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9448                                 "\n",
9449                                 bb_banner,
9450                                 "built-in shell (ash)"
9451                         );
9452                         did_banner = 1;
9453                 }
9454         }
9455 #endif
9456 }
9457
9458 static void
9459 optschanged(void)
9460 {
9461 #if DEBUG
9462         opentrace();
9463 #endif
9464         setinteractive(iflag);
9465         setjobctl(mflag);
9466 #if ENABLE_FEATURE_EDITING_VI
9467         if (viflag)
9468                 line_input_state->flags |= VI_MODE;
9469         else
9470                 line_input_state->flags &= ~VI_MODE;
9471 #else
9472         viflag = 0; /* forcibly keep the option off */
9473 #endif
9474 }
9475
9476 struct localvar_list {
9477         struct localvar_list *next;
9478         struct localvar *lv;
9479 };
9480
9481 static struct localvar_list *localvar_stack;
9482
9483 /*
9484  * Called after a function returns.
9485  * Interrupts must be off.
9486  */
9487 static void
9488 poplocalvars(int keep)
9489 {
9490         struct localvar_list *ll;
9491         struct localvar *lvp, *next;
9492         struct var *vp;
9493
9494         INT_OFF;
9495         ll = localvar_stack;
9496         localvar_stack = ll->next;
9497
9498         next = ll->lv;
9499         free(ll);
9500
9501         while ((lvp = next) != NULL) {
9502                 next = lvp->next;
9503                 vp = lvp->vp;
9504                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9505                 if (keep) {
9506                         int bits = VSTRFIXED;
9507
9508                         if (lvp->flags != VUNSET) {
9509                                 if (vp->var_text == lvp->text)
9510                                         bits |= VTEXTFIXED;
9511                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9512                                         free((char*)lvp->text);
9513                         }
9514
9515                         vp->flags &= ~bits;
9516                         vp->flags |= (lvp->flags & bits);
9517
9518                         if ((vp->flags &
9519                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9520                                 unsetvar(vp->var_text);
9521                 } else if (vp == NULL) {        /* $- saved */
9522                         memcpy(optlist, lvp->text, sizeof(optlist));
9523                         free((char*)lvp->text);
9524                         optschanged();
9525                 } else if (lvp->flags == VUNSET) {
9526                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9527                         unsetvar(vp->var_text);
9528                 } else {
9529                         if (vp->var_func)
9530                                 vp->var_func(var_end(lvp->text));
9531                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9532                                 free((char*)vp->var_text);
9533                         vp->flags = lvp->flags;
9534                         vp->var_text = lvp->text;
9535                 }
9536                 free(lvp);
9537         }
9538         INT_ON;
9539 }
9540
9541 /*
9542  * Create a new localvar environment.
9543  */
9544 static struct localvar_list *
9545 pushlocalvars(void)
9546 {
9547         struct localvar_list *ll;
9548
9549         INT_OFF;
9550         ll = ckzalloc(sizeof(*ll));
9551         /*ll->lv = NULL; - zalloc did it */
9552         ll->next = localvar_stack;
9553         localvar_stack = ll;
9554         INT_ON;
9555
9556         return ll->next;
9557 }
9558
9559 static void
9560 unwindlocalvars(struct localvar_list *stop)
9561 {
9562         while (localvar_stack != stop)
9563                 poplocalvars(0);
9564 }
9565
9566 static int
9567 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9568 {
9569         volatile struct shparam saveparam;
9570         struct jmploc *volatile savehandler;
9571         struct jmploc jmploc;
9572         int e;
9573         int savefuncline;
9574
9575         saveparam = shellparam;
9576         savefuncline = funcline;
9577         savehandler = exception_handler;
9578         e = setjmp(jmploc.loc);
9579         if (e) {
9580                 goto funcdone;
9581         }
9582         INT_OFF;
9583         exception_handler = &jmploc;
9584         shellparam.malloced = 0;
9585         func->count++;
9586         funcline = func->n.ndefun.linno;
9587         INT_ON;
9588         shellparam.nparam = argc - 1;
9589         shellparam.p = argv + 1;
9590 #if ENABLE_ASH_GETOPTS
9591         shellparam.optind = 1;
9592         shellparam.optoff = -1;
9593 #endif
9594         pushlocalvars();
9595         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9596         poplocalvars(0);
9597  funcdone:
9598         INT_OFF;
9599         funcline = savefuncline;
9600         freefunc(func);
9601         freeparam(&shellparam);
9602         shellparam = saveparam;
9603         exception_handler = savehandler;
9604         INT_ON;
9605         evalskip &= ~SKIPFUNC;
9606         return e;
9607 }
9608
9609 /*
9610  * Make a variable a local variable.  When a variable is made local, it's
9611  * value and flags are saved in a localvar structure.  The saved values
9612  * will be restored when the shell function returns.  We handle the name
9613  * "-" as a special case: it makes changes to "set +-options" local
9614  * (options will be restored on return from the function).
9615  */
9616 static void
9617 mklocal(char *name)
9618 {
9619         struct localvar *lvp;
9620         struct var **vpp;
9621         struct var *vp;
9622         char *eq = strchr(name, '=');
9623
9624         INT_OFF;
9625         /* Cater for duplicate "local". Examples:
9626          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9627          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9628          */
9629         lvp = localvar_stack->lv;
9630         while (lvp) {
9631                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9632                         if (eq)
9633                                 setvareq(name, 0);
9634                         /* else:
9635                          * it's a duplicate "local VAR" declaration, do nothing
9636                          */
9637                         goto ret;
9638                 }
9639                 lvp = lvp->next;
9640         }
9641
9642         lvp = ckzalloc(sizeof(*lvp));
9643         if (LONE_DASH(name)) {
9644                 char *p;
9645                 p = ckmalloc(sizeof(optlist));
9646                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9647                 vp = NULL;
9648         } else {
9649                 vpp = hashvar(name);
9650                 vp = *findvar(vpp, name);
9651                 if (vp == NULL) {
9652                         /* variable did not exist yet */
9653                         if (eq)
9654                                 vp = setvareq(name, VSTRFIXED);
9655                         else
9656                                 vp = setvar(name, NULL, VSTRFIXED);
9657                         lvp->flags = VUNSET;
9658                 } else {
9659                         lvp->text = vp->var_text;
9660                         lvp->flags = vp->flags;
9661                         /* make sure neither "struct var" nor string gets freed
9662                          * during (un)setting:
9663                          */
9664                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9665                         if (eq)
9666                                 setvareq(name, 0);
9667                         else
9668                                 /* "local VAR" unsets VAR: */
9669                                 setvar0(name, NULL);
9670                 }
9671         }
9672         lvp->vp = vp;
9673         lvp->next = localvar_stack->lv;
9674         localvar_stack->lv = lvp;
9675  ret:
9676         INT_ON;
9677 }
9678
9679 /*
9680  * The "local" command.
9681  */
9682 static int FAST_FUNC
9683 localcmd(int argc UNUSED_PARAM, char **argv)
9684 {
9685         char *name;
9686
9687         if (!localvar_stack)
9688                 ash_msg_and_raise_error("not in a function");
9689
9690         argv = argptr;
9691         while ((name = *argv++) != NULL) {
9692                 mklocal(name);
9693         }
9694         return 0;
9695 }
9696
9697 static int FAST_FUNC
9698 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9699 {
9700         return 1;
9701 }
9702
9703 static int FAST_FUNC
9704 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9705 {
9706         return 0;
9707 }
9708
9709 static int FAST_FUNC
9710 execcmd(int argc UNUSED_PARAM, char **argv)
9711 {
9712         optionarg = NULL;
9713         while (nextopt("a:") != '\0')
9714                 /* nextopt() sets optionarg to "-a ARGV0" */;
9715
9716         argv = argptr;
9717         if (argv[0]) {
9718                 char *prog;
9719
9720                 iflag = 0;              /* exit on error */
9721                 mflag = 0;
9722                 optschanged();
9723                 /* We should set up signals for "exec CMD"
9724                  * the same way as for "CMD" without "exec".
9725                  * But optschanged->setinteractive->setsignal
9726                  * still thought we are a root shell. Therefore, for example,
9727                  * SIGQUIT is still set to IGN. Fix it:
9728                  */
9729                 shlvl++;
9730                 setsignal(SIGQUIT);
9731                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9732                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9733                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9734
9735                 prog = argv[0];
9736                 if (optionarg)
9737                         argv[0] = optionarg;
9738                 shellexec(prog, argv, pathval(), 0);
9739                 /* NOTREACHED */
9740         }
9741         return 0;
9742 }
9743
9744 /*
9745  * The return command.
9746  */
9747 static int FAST_FUNC
9748 returncmd(int argc UNUSED_PARAM, char **argv)
9749 {
9750         /*
9751          * If called outside a function, do what ksh does;
9752          * skip the rest of the file.
9753          */
9754         evalskip = SKIPFUNC;
9755         return argv[1] ? number(argv[1]) : exitstatus;
9756 }
9757
9758 /* Forward declarations for builtintab[] */
9759 static int breakcmd(int, char **) FAST_FUNC;
9760 static int dotcmd(int, char **) FAST_FUNC;
9761 static int evalcmd(int, char **, int) FAST_FUNC;
9762 static int exitcmd(int, char **) FAST_FUNC;
9763 static int exportcmd(int, char **) FAST_FUNC;
9764 #if ENABLE_ASH_GETOPTS
9765 static int getoptscmd(int, char **) FAST_FUNC;
9766 #endif
9767 #if ENABLE_ASH_HELP
9768 static int helpcmd(int, char **) FAST_FUNC;
9769 #endif
9770 #if MAX_HISTORY
9771 static int historycmd(int, char **) FAST_FUNC;
9772 #endif
9773 #if ENABLE_FEATURE_SH_MATH
9774 static int letcmd(int, char **) FAST_FUNC;
9775 #endif
9776 static int readcmd(int, char **) FAST_FUNC;
9777 static int setcmd(int, char **) FAST_FUNC;
9778 static int shiftcmd(int, char **) FAST_FUNC;
9779 static int timescmd(int, char **) FAST_FUNC;
9780 static int trapcmd(int, char **) FAST_FUNC;
9781 static int umaskcmd(int, char **) FAST_FUNC;
9782 static int unsetcmd(int, char **) FAST_FUNC;
9783 static int ulimitcmd(int, char **) FAST_FUNC;
9784
9785 #define BUILTIN_NOSPEC          "0"
9786 #define BUILTIN_SPECIAL         "1"
9787 #define BUILTIN_REGULAR         "2"
9788 #define BUILTIN_SPEC_REG        "3"
9789 #define BUILTIN_ASSIGN          "4"
9790 #define BUILTIN_SPEC_ASSG       "5"
9791 #define BUILTIN_REG_ASSG        "6"
9792 #define BUILTIN_SPEC_REG_ASSG   "7"
9793
9794 /* Stubs for calling non-FAST_FUNC's */
9795 #if ENABLE_ASH_ECHO
9796 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9797 #endif
9798 #if ENABLE_ASH_PRINTF
9799 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9800 #endif
9801 #if ENABLE_ASH_TEST || BASH_TEST2
9802 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9803 #endif
9804
9805 /* Keep these in proper order since it is searched via bsearch() */
9806 static const struct builtincmd builtintab[] = {
9807         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9808         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9809 #if ENABLE_ASH_TEST
9810         { BUILTIN_REGULAR       "["       , testcmd    },
9811 #endif
9812 #if BASH_TEST2
9813         { BUILTIN_REGULAR       "[["      , testcmd    },
9814 #endif
9815 #if ENABLE_ASH_ALIAS
9816         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9817 #endif
9818 #if JOBS
9819         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9820 #endif
9821         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9822         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9823         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9824 #if ENABLE_ASH_CMDCMD
9825         { BUILTIN_REGULAR       "command" , commandcmd },
9826 #endif
9827         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9828 #if ENABLE_ASH_ECHO
9829         { BUILTIN_REGULAR       "echo"    , echocmd    },
9830 #endif
9831         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9832         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9833         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9834         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9835         { BUILTIN_REGULAR       "false"   , falsecmd   },
9836 #if JOBS
9837         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9838 #endif
9839 #if ENABLE_ASH_GETOPTS
9840         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9841 #endif
9842         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9843 #if ENABLE_ASH_HELP
9844         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9845 #endif
9846 #if MAX_HISTORY
9847         { BUILTIN_NOSPEC        "history" , historycmd },
9848 #endif
9849 #if JOBS
9850         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9851         { BUILTIN_REGULAR       "kill"    , killcmd    },
9852 #endif
9853 #if ENABLE_FEATURE_SH_MATH
9854         { BUILTIN_NOSPEC        "let"     , letcmd     },
9855 #endif
9856         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9857 #if ENABLE_ASH_PRINTF
9858         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9859 #endif
9860         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9861         { BUILTIN_REGULAR       "read"    , readcmd    },
9862         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9863         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9864         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9865         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9866 #if BASH_SOURCE
9867         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9868 #endif
9869 #if ENABLE_ASH_TEST
9870         { BUILTIN_REGULAR       "test"    , testcmd    },
9871 #endif
9872         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9873         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9874         { BUILTIN_REGULAR       "true"    , truecmd    },
9875         { BUILTIN_NOSPEC        "type"    , typecmd    },
9876         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9877         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9878 #if ENABLE_ASH_ALIAS
9879         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9880 #endif
9881         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9882         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9883 };
9884
9885 /* Should match the above table! */
9886 #define COMMANDCMD (builtintab + \
9887         /* . : */       2 + \
9888         /* [ */         1 * ENABLE_ASH_TEST + \
9889         /* [[ */        1 * BASH_TEST2 + \
9890         /* alias */     1 * ENABLE_ASH_ALIAS + \
9891         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9892         /* break cd cddir  */   3)
9893 #define EVALCMD (COMMANDCMD + \
9894         /* command */   1 * ENABLE_ASH_CMDCMD + \
9895         /* continue */  1 + \
9896         /* echo */      1 * ENABLE_ASH_ECHO + \
9897         0)
9898 #define EXECCMD (EVALCMD + \
9899         /* eval */      1)
9900
9901 /*
9902  * Search the table of builtin commands.
9903  */
9904 static int
9905 pstrcmp1(const void *a, const void *b)
9906 {
9907         return strcmp((char*)a, *(char**)b + 1);
9908 }
9909 static struct builtincmd *
9910 find_builtin(const char *name)
9911 {
9912         struct builtincmd *bp;
9913
9914         bp = bsearch(
9915                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9916                 pstrcmp1
9917         );
9918         return bp;
9919 }
9920
9921 /*
9922  * Execute a simple command.
9923  */
9924 static int
9925 isassignment(const char *p)
9926 {
9927         const char *q = endofname(p);
9928         if (p == q)
9929                 return 0;
9930         return *q == '=';
9931 }
9932 static int FAST_FUNC
9933 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9934 {
9935         /* Preserve exitstatus of a previous possible redirection
9936          * as POSIX mandates */
9937         return back_exitstatus;
9938 }
9939 static int
9940 evalcommand(union node *cmd, int flags)
9941 {
9942         static const struct builtincmd null_bltin = {
9943                 "\0\0", bltincmd /* why three NULs? */
9944         };
9945         struct localvar_list *localvar_stop;
9946         struct redirtab *redir_stop;
9947         struct stackmark smark;
9948         union node *argp;
9949         struct arglist arglist;
9950         struct arglist varlist;
9951         char **argv;
9952         int argc;
9953         const struct strlist *sp;
9954         struct cmdentry cmdentry;
9955         struct job *jp;
9956         char *lastarg;
9957         const char *path;
9958         int spclbltin;
9959         int status;
9960         char **nargv;
9961         smallint cmd_is_exec;
9962
9963         errlinno = lineno = cmd->ncmd.linno;
9964         if (funcline)
9965                 lineno -= funcline - 1;
9966
9967         /* First expand the arguments. */
9968         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9969         setstackmark(&smark);
9970         localvar_stop = pushlocalvars();
9971         back_exitstatus = 0;
9972
9973         cmdentry.cmdtype = CMDBUILTIN;
9974         cmdentry.u.cmd = &null_bltin;
9975         varlist.lastp = &varlist.list;
9976         *varlist.lastp = NULL;
9977         arglist.lastp = &arglist.list;
9978         *arglist.lastp = NULL;
9979
9980         argc = 0;
9981         if (cmd->ncmd.args) {
9982                 struct builtincmd *bcmd;
9983                 smallint pseudovarflag;
9984
9985                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9986                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9987
9988                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9989                         struct strlist **spp;
9990
9991                         spp = arglist.lastp;
9992                         if (pseudovarflag && isassignment(argp->narg.text))
9993                                 expandarg(argp, &arglist, EXP_VARTILDE);
9994                         else
9995                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9996
9997                         for (sp = *spp; sp; sp = sp->next)
9998                                 argc++;
9999                 }
10000         }
10001
10002         /* Reserve one extra spot at the front for shellexec. */
10003         nargv = stalloc(sizeof(char *) * (argc + 2));
10004         argv = ++nargv;
10005         for (sp = arglist.list; sp; sp = sp->next) {
10006                 TRACE(("evalcommand arg: %s\n", sp->text));
10007                 *nargv++ = sp->text;
10008         }
10009         *nargv = NULL;
10010
10011         lastarg = NULL;
10012         if (iflag && funcline == 0 && argc > 0)
10013                 lastarg = nargv[-1];
10014
10015         expredir(cmd->ncmd.redirect);
10016         redir_stop = pushredir(cmd->ncmd.redirect);
10017         preverrout_fd = 2;
10018         if (BASH_XTRACEFD && xflag) {
10019                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10020                  * we do not emulate this. We only use its value.
10021                  */
10022                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10023                 if (xtracefd && is_number(xtracefd))
10024                         preverrout_fd = atoi(xtracefd);
10025
10026         }
10027         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10028
10029         path = vpath.var_text;
10030         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10031                 struct strlist **spp;
10032                 char *p;
10033
10034                 spp = varlist.lastp;
10035                 expandarg(argp, &varlist, EXP_VARTILDE);
10036
10037                 mklocal((*spp)->text);
10038
10039                 /*
10040                  * Modify the command lookup path, if a PATH= assignment
10041                  * is present
10042                  */
10043                 p = (*spp)->text;
10044                 if (varcmp(p, path) == 0)
10045                         path = p;
10046         }
10047
10048         /* Print the command if xflag is set. */
10049         if (xflag) {
10050                 const char *pfx = "";
10051
10052                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10053
10054                 sp = varlist.list;
10055                 while (sp) {
10056                         char *varval = sp->text;
10057                         char *eq = strchrnul(varval, '=');
10058                         if (*eq)
10059                                 eq++;
10060                         fdprintf(preverrout_fd, "%s%.*s%s",
10061                                 pfx,
10062                                 (int)(eq - varval), varval,
10063                                 maybe_single_quote(eq)
10064                         );
10065                         sp = sp->next;
10066                         pfx = " ";
10067                 }
10068
10069                 sp = arglist.list;
10070                 while (sp) {
10071                         fdprintf(preverrout_fd, "%s%s",
10072                                 pfx,
10073                                 /* always quote if matches reserved word: */
10074                                 findkwd(sp->text)
10075                                 ? single_quote(sp->text)
10076                                 : maybe_single_quote(sp->text)
10077                         );
10078                         sp = sp->next;
10079                         pfx = " ";
10080                 }
10081                 safe_write(preverrout_fd, "\n", 1);
10082         }
10083
10084         cmd_is_exec = 0;
10085         spclbltin = -1;
10086
10087         /* Now locate the command. */
10088         if (argc) {
10089                 int cmd_flag = DO_ERR;
10090 #if ENABLE_ASH_CMDCMD
10091                 const char *oldpath = path + 5;
10092 #endif
10093                 path += 5;
10094                 for (;;) {
10095                         find_command(argv[0], &cmdentry, cmd_flag, path);
10096                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10097                                 flush_stdout_stderr();
10098                                 status = 127;
10099                                 goto bail;
10100                         }
10101
10102                         /* implement bltin and command here */
10103                         if (cmdentry.cmdtype != CMDBUILTIN)
10104                                 break;
10105                         if (spclbltin < 0)
10106                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10107                         if (cmdentry.u.cmd == EXECCMD)
10108                                 cmd_is_exec = 1;
10109 #if ENABLE_ASH_CMDCMD
10110                         if (cmdentry.u.cmd == COMMANDCMD) {
10111                                 path = oldpath;
10112                                 nargv = parse_command_args(argv, &path);
10113                                 if (!nargv)
10114                                         break;
10115                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10116                                  * nargv => "PROG". path is updated if -p.
10117                                  */
10118                                 argc -= nargv - argv;
10119                                 argv = nargv;
10120                                 cmd_flag |= DO_NOFUNC;
10121                         } else
10122 #endif
10123                                 break;
10124                 }
10125         }
10126
10127         if (status) {
10128  bail:
10129                 exitstatus = status;
10130
10131                 /* We have a redirection error. */
10132                 if (spclbltin > 0)
10133                         raise_exception(EXERROR);
10134
10135                 goto out;
10136         }
10137
10138         /* Execute the command. */
10139         switch (cmdentry.cmdtype) {
10140         default: {
10141
10142 #if ENABLE_FEATURE_SH_STANDALONE \
10143  && ENABLE_FEATURE_SH_NOFORK \
10144  && NUM_APPLETS > 1
10145 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10146  *     around run_nofork_applet() call.
10147  * (2) Should this check also be done in forkshell()?
10148  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10149  */
10150                 /* find_command() encodes applet_no as (-2 - applet_no) */
10151                 int applet_no = (- cmdentry.u.index - 2);
10152                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10153                         char **sv_environ;
10154
10155                         INT_OFF;
10156                         sv_environ = environ;
10157                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10158                         /*
10159                          * Run <applet>_main().
10160                          * Signals (^C) can't interrupt here.
10161                          * Otherwise we can mangle stdio or malloc internal state.
10162                          * This makes applets which can run for a long time
10163                          * and/or wait for user input ineligible for NOFORK:
10164                          * for example, "yes" or "rm" (rm -i waits for input).
10165                          */
10166                         status = run_nofork_applet(applet_no, argv);
10167                         environ = sv_environ;
10168                         /*
10169                          * Try enabling NOFORK for "yes" applet.
10170                          * ^C _will_ stop it (write returns EINTR),
10171                          * but this causes stdout FILE to be stuck
10172                          * and needing clearerr(). What if other applets
10173                          * also can get EINTRs? Do we need to switch
10174                          * our signals to SA_RESTART?
10175                          */
10176                         /*clearerr(stdout);*/
10177                         INT_ON;
10178                         break;
10179                 }
10180 #endif
10181                 /* Can we avoid forking? For example, very last command
10182                  * in a script or a subshell does not need forking,
10183                  * we can just exec it.
10184                  */
10185                 if (!(flags & EV_EXIT) || may_have_traps) {
10186                         /* No, forking off a child is necessary */
10187                         INT_OFF;
10188                         get_tty_state();
10189                         jp = makejob(/*cmd,*/ 1);
10190                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10191                                 /* parent */
10192                                 status = waitforjob(jp);
10193                                 INT_ON;
10194                                 TRACE(("forked child exited with %d\n", status));
10195                                 break;
10196                         }
10197                         /* child */
10198                         FORCE_INT_ON;
10199                         /* fall through to exec'ing external program */
10200                 }
10201                 listsetvar(varlist.list, VEXPORT|VSTACK);
10202                 shellexec(argv[0], argv, path, cmdentry.u.index);
10203                 /* NOTREACHED */
10204         } /* default */
10205         case CMDBUILTIN:
10206                 if (spclbltin > 0 || argc == 0) {
10207                         poplocalvars(1);
10208                         if (cmd_is_exec && argc > 1)
10209                                 listsetvar(varlist.list, VEXPORT);
10210                 }
10211
10212                 /* Tight loop with builtins only:
10213                  * "while kill -0 $child; do true; done"
10214                  * will never exit even if $child died, unless we do this
10215                  * to reap the zombie and make kill detect that it's gone: */
10216                 dowait(DOWAIT_NONBLOCK, NULL);
10217
10218                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10219                         if (exception_type == EXERROR && spclbltin <= 0) {
10220                                 FORCE_INT_ON;
10221                                 goto readstatus;
10222                         }
10223  raise:
10224                         longjmp(exception_handler->loc, 1);
10225                 }
10226                 goto readstatus;
10227
10228         case CMDFUNCTION:
10229                 poplocalvars(1);
10230                 /* See above for the rationale */
10231                 dowait(DOWAIT_NONBLOCK, NULL);
10232                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10233                         goto raise;
10234  readstatus:
10235                 status = exitstatus;
10236                 break;
10237         } /* switch */
10238
10239  out:
10240         if (cmd->ncmd.redirect)
10241                 popredir(/*drop:*/ cmd_is_exec);
10242         unwindredir(redir_stop);
10243         unwindlocalvars(localvar_stop);
10244         if (lastarg) {
10245                 /* dsl: I think this is intended to be used to support
10246                  * '_' in 'vi' command mode during line editing...
10247                  * However I implemented that within libedit itself.
10248                  */
10249                 setvar0("_", lastarg);
10250         }
10251         popstackmark(&smark);
10252
10253         return status;
10254 }
10255
10256 static int
10257 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10258 {
10259         char *volatile savecmdname;
10260         struct jmploc *volatile savehandler;
10261         struct jmploc jmploc;
10262         int status;
10263         int i;
10264
10265         savecmdname = commandname;
10266         savehandler = exception_handler;
10267         i = setjmp(jmploc.loc);
10268         if (i)
10269                 goto cmddone;
10270         exception_handler = &jmploc;
10271         commandname = argv[0];
10272         argptr = argv + 1;
10273         optptr = NULL;                  /* initialize nextopt */
10274         if (cmd == EVALCMD)
10275                 status = evalcmd(argc, argv, flags);
10276         else
10277                 status = (*cmd->builtin)(argc, argv);
10278         flush_stdout_stderr();
10279         status |= ferror(stdout);
10280         exitstatus = status;
10281  cmddone:
10282         clearerr(stdout);
10283         commandname = savecmdname;
10284         exception_handler = savehandler;
10285
10286         return i;
10287 }
10288
10289 static int
10290 goodname(const char *p)
10291 {
10292         return endofname(p)[0] == '\0';
10293 }
10294
10295
10296 /*
10297  * Search for a command.  This is called before we fork so that the
10298  * location of the command will be available in the parent as well as
10299  * the child.  The check for "goodname" is an overly conservative
10300  * check that the name will not be subject to expansion.
10301  */
10302 static void
10303 prehash(union node *n)
10304 {
10305         struct cmdentry entry;
10306
10307         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10308                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10309 }
10310
10311
10312 /* ============ Builtin commands
10313  *
10314  * Builtin commands whose functions are closely tied to evaluation
10315  * are implemented here.
10316  */
10317
10318 /*
10319  * Handle break and continue commands.  Break, continue, and return are
10320  * all handled by setting the evalskip flag.  The evaluation routines
10321  * above all check this flag, and if it is set they start skipping
10322  * commands rather than executing them.  The variable skipcount is
10323  * the number of loops to break/continue, or the number of function
10324  * levels to return.  (The latter is always 1.)  It should probably
10325  * be an error to break out of more loops than exist, but it isn't
10326  * in the standard shell so we don't make it one here.
10327  */
10328 static int FAST_FUNC
10329 breakcmd(int argc UNUSED_PARAM, char **argv)
10330 {
10331         int n = argv[1] ? number(argv[1]) : 1;
10332
10333         if (n <= 0)
10334                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10335         if (n > loopnest)
10336                 n = loopnest;
10337         if (n > 0) {
10338                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10339                 skipcount = n;
10340         }
10341         return 0;
10342 }
10343
10344
10345 /*
10346  * This implements the input routines used by the parser.
10347  */
10348
10349 enum {
10350         INPUT_PUSH_FILE = 1,
10351         INPUT_NOFILE_OK = 2,
10352 };
10353
10354 static smallint checkkwd;
10355 /* values of checkkwd variable */
10356 #define CHKALIAS        0x1
10357 #define CHKKWD          0x2
10358 #define CHKNL           0x4
10359 #define CHKEOFMARK      0x8
10360
10361 /*
10362  * Push a string back onto the input at this current parsefile level.
10363  * We handle aliases this way.
10364  */
10365 #if !ENABLE_ASH_ALIAS
10366 #define pushstring(s, ap) pushstring(s)
10367 #endif
10368 static void
10369 pushstring(char *s, struct alias *ap)
10370 {
10371         struct strpush *sp;
10372         int len;
10373
10374         len = strlen(s);
10375         INT_OFF;
10376         if (g_parsefile->strpush) {
10377                 sp = ckzalloc(sizeof(*sp));
10378                 sp->prev = g_parsefile->strpush;
10379         } else {
10380                 sp = &(g_parsefile->basestrpush);
10381         }
10382         g_parsefile->strpush = sp;
10383         sp->prev_string = g_parsefile->next_to_pgetc;
10384         sp->prev_left_in_line = g_parsefile->left_in_line;
10385         sp->unget = g_parsefile->unget;
10386         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10387 #if ENABLE_ASH_ALIAS
10388         sp->ap = ap;
10389         if (ap) {
10390                 ap->flag |= ALIASINUSE;
10391                 sp->string = s;
10392         }
10393 #endif
10394         g_parsefile->next_to_pgetc = s;
10395         g_parsefile->left_in_line = len;
10396         g_parsefile->unget = 0;
10397         INT_ON;
10398 }
10399
10400 static void
10401 popstring(void)
10402 {
10403         struct strpush *sp = g_parsefile->strpush;
10404
10405         INT_OFF;
10406 #if ENABLE_ASH_ALIAS
10407         if (sp->ap) {
10408                 if (g_parsefile->next_to_pgetc[-1] == ' '
10409                  || g_parsefile->next_to_pgetc[-1] == '\t'
10410                 ) {
10411                         checkkwd |= CHKALIAS;
10412                 }
10413                 if (sp->string != sp->ap->val) {
10414                         free(sp->string);
10415                 }
10416                 sp->ap->flag &= ~ALIASINUSE;
10417                 if (sp->ap->flag & ALIASDEAD) {
10418                         unalias(sp->ap->name);
10419                 }
10420         }
10421 #endif
10422         g_parsefile->next_to_pgetc = sp->prev_string;
10423         g_parsefile->left_in_line = sp->prev_left_in_line;
10424         g_parsefile->unget = sp->unget;
10425         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10426         g_parsefile->strpush = sp->prev;
10427         if (sp != &(g_parsefile->basestrpush))
10428                 free(sp);
10429         INT_ON;
10430 }
10431
10432 static int
10433 preadfd(void)
10434 {
10435         int nr;
10436         char *buf = g_parsefile->buf;
10437
10438         g_parsefile->next_to_pgetc = buf;
10439 #if ENABLE_FEATURE_EDITING
10440  retry:
10441         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10442                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10443         else {
10444 # if ENABLE_ASH_IDLE_TIMEOUT
10445                 int timeout = -1;
10446                 if (iflag) {
10447                         const char *tmout_var = lookupvar("TMOUT");
10448                         if (tmout_var) {
10449                                 timeout = atoi(tmout_var) * 1000;
10450                                 if (timeout <= 0)
10451                                         timeout = -1;
10452                         }
10453                 }
10454                 line_input_state->timeout = timeout;
10455 # endif
10456 # if ENABLE_FEATURE_TAB_COMPLETION
10457                 line_input_state->path_lookup = pathval();
10458 # endif
10459                 reinit_unicode_for_ash();
10460                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10461                 if (nr == 0) {
10462                         /* ^C pressed, "convert" to SIGINT */
10463                         write(STDOUT_FILENO, "^C", 2);
10464                         if (trap[SIGINT]) {
10465                                 buf[0] = '\n';
10466                                 buf[1] = '\0';
10467                                 raise(SIGINT);
10468                                 return 1;
10469                         }
10470                         exitstatus = 128 + SIGINT;
10471                         bb_putchar('\n');
10472                         goto retry;
10473                 }
10474                 if (nr < 0) {
10475                         if (errno == 0) {
10476                                 /* Ctrl+D pressed */
10477                                 nr = 0;
10478                         }
10479 # if ENABLE_ASH_IDLE_TIMEOUT
10480                         else if (errno == EAGAIN && timeout > 0) {
10481                                 puts("\007timed out waiting for input: auto-logout");
10482                                 exitshell();
10483                         }
10484 # endif
10485                 }
10486         }
10487 #else
10488         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10489 #endif
10490
10491 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10492         if (nr < 0) {
10493                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10494                         int flags = fcntl(0, F_GETFL);
10495                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10496                                 flags &= ~O_NONBLOCK;
10497                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10498                                         out2str("sh: turning off NDELAY mode\n");
10499                                         goto retry;
10500                                 }
10501                         }
10502                 }
10503         }
10504 #endif
10505         return nr;
10506 }
10507
10508 /*
10509  * Refill the input buffer and return the next input character:
10510  *
10511  * 1) If a string was pushed back on the input, pop it;
10512  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10513  *    or we are reading from a string so we can't refill the buffer,
10514  *    return EOF.
10515  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10516  * 4) Process input up to the next newline, deleting nul characters.
10517  */
10518 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10519 #define pgetc_debug(...) ((void)0)
10520 static int pgetc(void);
10521 static int
10522 preadbuffer(void)
10523 {
10524         char *q;
10525         int more;
10526
10527         if (g_parsefile->strpush) {
10528 #if ENABLE_ASH_ALIAS
10529                 if (g_parsefile->left_in_line == -1
10530                  && g_parsefile->strpush->ap
10531                  && g_parsefile->next_to_pgetc[-1] != ' '
10532                  && g_parsefile->next_to_pgetc[-1] != '\t'
10533                 ) {
10534                         pgetc_debug("preadbuffer PEOA");
10535                         return PEOA;
10536                 }
10537 #endif
10538                 popstring();
10539                 return pgetc();
10540         }
10541         /* on both branches above g_parsefile->left_in_line < 0.
10542          * "pgetc" needs refilling.
10543          */
10544
10545         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10546          * pungetc() may increment it a few times.
10547          * Assuming it won't increment it to less than -90.
10548          */
10549         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10550                 pgetc_debug("preadbuffer PEOF1");
10551                 /* even in failure keep left_in_line and next_to_pgetc
10552                  * in lock step, for correct multi-layer pungetc.
10553                  * left_in_line was decremented before preadbuffer(),
10554                  * must inc next_to_pgetc: */
10555                 g_parsefile->next_to_pgetc++;
10556                 return PEOF;
10557         }
10558
10559         more = g_parsefile->left_in_buffer;
10560         if (more <= 0) {
10561                 flush_stdout_stderr();
10562  again:
10563                 more = preadfd();
10564                 if (more <= 0) {
10565                         /* don't try reading again */
10566                         g_parsefile->left_in_line = -99;
10567                         pgetc_debug("preadbuffer PEOF2");
10568                         g_parsefile->next_to_pgetc++;
10569                         return PEOF;
10570                 }
10571         }
10572
10573         /* Find out where's the end of line.
10574          * Set g_parsefile->left_in_line
10575          * and g_parsefile->left_in_buffer acordingly.
10576          * NUL chars are deleted.
10577          */
10578         q = g_parsefile->next_to_pgetc;
10579         for (;;) {
10580                 char c;
10581
10582                 more--;
10583
10584                 c = *q;
10585                 if (c == '\0') {
10586                         memmove(q, q + 1, more);
10587                 } else {
10588                         q++;
10589                         if (c == '\n') {
10590                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10591                                 break;
10592                         }
10593                 }
10594
10595                 if (more <= 0) {
10596                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10597                         if (g_parsefile->left_in_line < 0)
10598                                 goto again;
10599                         break;
10600                 }
10601         }
10602         g_parsefile->left_in_buffer = more;
10603
10604         if (vflag) {
10605                 char save = *q;
10606                 *q = '\0';
10607                 out2str(g_parsefile->next_to_pgetc);
10608                 *q = save;
10609         }
10610
10611         pgetc_debug("preadbuffer at %d:%p'%s'",
10612                         g_parsefile->left_in_line,
10613                         g_parsefile->next_to_pgetc,
10614                         g_parsefile->next_to_pgetc);
10615         return (unsigned char)*g_parsefile->next_to_pgetc++;
10616 }
10617
10618 static void
10619 nlprompt(void)
10620 {
10621         g_parsefile->linno++;
10622         setprompt_if(doprompt, 2);
10623 }
10624 static void
10625 nlnoprompt(void)
10626 {
10627         g_parsefile->linno++;
10628         needprompt = doprompt;
10629 }
10630
10631 static int
10632 pgetc(void)
10633 {
10634         int c;
10635
10636         pgetc_debug("pgetc at %d:%p'%s'",
10637                         g_parsefile->left_in_line,
10638                         g_parsefile->next_to_pgetc,
10639                         g_parsefile->next_to_pgetc);
10640         if (g_parsefile->unget)
10641                 return g_parsefile->lastc[--g_parsefile->unget];
10642
10643         if (--g_parsefile->left_in_line >= 0)
10644                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10645         else
10646                 c = preadbuffer();
10647
10648         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10649         g_parsefile->lastc[0] = c;
10650
10651         return c;
10652 }
10653
10654 #if ENABLE_ASH_ALIAS
10655 static int
10656 pgetc_without_PEOA(void)
10657 {
10658         int c;
10659         do {
10660                 pgetc_debug("pgetc at %d:%p'%s'",
10661                                 g_parsefile->left_in_line,
10662                                 g_parsefile->next_to_pgetc,
10663                                 g_parsefile->next_to_pgetc);
10664                 c = pgetc();
10665         } while (c == PEOA);
10666         return c;
10667 }
10668 #else
10669 # define pgetc_without_PEOA() pgetc()
10670 #endif
10671
10672 /*
10673  * Undo a call to pgetc.  Only two characters may be pushed back.
10674  * PEOF may be pushed back.
10675  */
10676 static void
10677 pungetc(void)
10678 {
10679         g_parsefile->unget++;
10680 }
10681
10682 /* This one eats backslash+newline */
10683 static int
10684 pgetc_eatbnl(void)
10685 {
10686         int c;
10687
10688         while ((c = pgetc()) == '\\') {
10689                 if (pgetc() != '\n') {
10690                         pungetc();
10691                         break;
10692                 }
10693
10694                 nlprompt();
10695         }
10696
10697         return c;
10698 }
10699
10700 struct synstack {
10701         smalluint syntax;
10702         uint8_t innerdq   :1;
10703         uint8_t varpushed :1;
10704         uint8_t dblquote  :1;
10705         int varnest;            /* levels of variables expansion */
10706         int dqvarnest;          /* levels of variables expansion within double quotes */
10707         int parenlevel;         /* levels of parens in arithmetic */
10708         struct synstack *prev;
10709         struct synstack *next;
10710 };
10711
10712 static void
10713 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10714 {
10715         memset(next, 0, sizeof(*next));
10716         next->syntax = syntax;
10717         next->next = *stack;
10718         (*stack)->prev = next;
10719         *stack = next;
10720 }
10721
10722 static ALWAYS_INLINE void
10723 synstack_pop(struct synstack **stack)
10724 {
10725         *stack = (*stack)->next;
10726 }
10727
10728 /*
10729  * To handle the "." command, a stack of input files is used.  Pushfile
10730  * adds a new entry to the stack and popfile restores the previous level.
10731  */
10732 static void
10733 pushfile(void)
10734 {
10735         struct parsefile *pf;
10736
10737         pf = ckzalloc(sizeof(*pf));
10738         pf->prev = g_parsefile;
10739         pf->pf_fd = -1;
10740         /*pf->strpush = NULL; - ckzalloc did it */
10741         /*pf->basestrpush.prev = NULL;*/
10742         /*pf->unget = 0;*/
10743         g_parsefile = pf;
10744 }
10745
10746 static void
10747 popfile(void)
10748 {
10749         struct parsefile *pf = g_parsefile;
10750
10751         if (pf == &basepf)
10752                 return;
10753
10754         INT_OFF;
10755         if (pf->pf_fd >= 0)
10756                 close(pf->pf_fd);
10757         free(pf->buf);
10758         while (pf->strpush)
10759                 popstring();
10760         g_parsefile = pf->prev;
10761         free(pf);
10762         INT_ON;
10763 }
10764
10765 /*
10766  * Return to top level.
10767  */
10768 static void
10769 popallfiles(void)
10770 {
10771         while (g_parsefile != &basepf)
10772                 popfile();
10773 }
10774
10775 /*
10776  * Close the file(s) that the shell is reading commands from.  Called
10777  * after a fork is done.
10778  */
10779 static void
10780 closescript(void)
10781 {
10782         popallfiles();
10783         if (g_parsefile->pf_fd > 0) {
10784                 close(g_parsefile->pf_fd);
10785                 g_parsefile->pf_fd = 0;
10786         }
10787 }
10788
10789 /*
10790  * Like setinputfile, but takes an open file descriptor.  Call this with
10791  * interrupts off.
10792  */
10793 static void
10794 setinputfd(int fd, int push)
10795 {
10796         if (push) {
10797                 pushfile();
10798                 g_parsefile->buf = NULL;
10799         }
10800         g_parsefile->pf_fd = fd;
10801         if (g_parsefile->buf == NULL)
10802                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10803         g_parsefile->left_in_buffer = 0;
10804         g_parsefile->left_in_line = 0;
10805         g_parsefile->linno = 1;
10806 }
10807
10808 /*
10809  * Set the input to take input from a file.  If push is set, push the
10810  * old input onto the stack first.
10811  */
10812 static int
10813 setinputfile(const char *fname, int flags)
10814 {
10815         int fd;
10816
10817         INT_OFF;
10818         fd = open(fname, O_RDONLY | O_CLOEXEC);
10819         if (fd < 0) {
10820                 if (flags & INPUT_NOFILE_OK)
10821                         goto out;
10822                 exitstatus = 127;
10823                 ash_msg_and_raise_perror("can't open '%s'", fname);
10824         }
10825         if (fd < 10)
10826                 fd = savefd(fd);
10827         else if (O_CLOEXEC == 0) /* old libc */
10828                 close_on_exec_on(fd);
10829
10830         setinputfd(fd, flags & INPUT_PUSH_FILE);
10831  out:
10832         INT_ON;
10833         return fd;
10834 }
10835
10836 /*
10837  * Like setinputfile, but takes input from a string.
10838  */
10839 static void
10840 setinputstring(char *string)
10841 {
10842         INT_OFF;
10843         pushfile();
10844         g_parsefile->next_to_pgetc = string;
10845         g_parsefile->left_in_line = strlen(string);
10846         g_parsefile->buf = NULL;
10847         g_parsefile->linno = 1;
10848         INT_ON;
10849 }
10850
10851
10852 /*
10853  * Routines to check for mail.
10854  */
10855
10856 #if ENABLE_ASH_MAIL
10857
10858 /* Hash of mtimes of mailboxes */
10859 static unsigned mailtime_hash;
10860 /* Set if MAIL or MAILPATH is changed. */
10861 static smallint mail_var_path_changed;
10862
10863 /*
10864  * Print appropriate message(s) if mail has arrived.
10865  * If mail_var_path_changed is set,
10866  * then the value of MAIL has mail_var_path_changed,
10867  * so we just update the values.
10868  */
10869 static void
10870 chkmail(void)
10871 {
10872         const char *mpath;
10873         char *p;
10874         char *q;
10875         unsigned new_hash;
10876         struct stackmark smark;
10877         struct stat statb;
10878
10879         setstackmark(&smark);
10880         mpath = mpathset() ? mpathval() : mailval();
10881         new_hash = 0;
10882         for (;;) {
10883                 p = path_advance(&mpath, nullstr);
10884                 if (p == NULL)
10885                         break;
10886                 if (*p == '\0')
10887                         continue;
10888                 for (q = p; *q; q++)
10889                         continue;
10890 #if DEBUG
10891                 if (q[-1] != '/')
10892                         abort();
10893 #endif
10894                 q[-1] = '\0';                   /* delete trailing '/' */
10895                 if (stat(p, &statb) < 0) {
10896                         continue;
10897                 }
10898                 /* Very simplistic "hash": just a sum of all mtimes */
10899                 new_hash += (unsigned)statb.st_mtime;
10900         }
10901         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10902                 if (mailtime_hash != 0)
10903                         out2str("you have mail\n");
10904                 mailtime_hash = new_hash;
10905         }
10906         mail_var_path_changed = 0;
10907         popstackmark(&smark);
10908 }
10909
10910 static void FAST_FUNC
10911 changemail(const char *val UNUSED_PARAM)
10912 {
10913         mail_var_path_changed = 1;
10914 }
10915
10916 #endif /* ASH_MAIL */
10917
10918
10919 /* ============ ??? */
10920
10921 /*
10922  * Set the shell parameters.
10923  */
10924 static void
10925 setparam(char **argv)
10926 {
10927         char **newparam;
10928         char **ap;
10929         int nparam;
10930
10931         for (nparam = 0; argv[nparam]; nparam++)
10932                 continue;
10933         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10934         while (*argv) {
10935                 *ap++ = ckstrdup(*argv++);
10936         }
10937         *ap = NULL;
10938         freeparam(&shellparam);
10939         shellparam.malloced = 1;
10940         shellparam.nparam = nparam;
10941         shellparam.p = newparam;
10942 #if ENABLE_ASH_GETOPTS
10943         shellparam.optind = 1;
10944         shellparam.optoff = -1;
10945 #endif
10946 }
10947
10948 /*
10949  * Process shell options.  The global variable argptr contains a pointer
10950  * to the argument list; we advance it past the options.
10951  *
10952  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10953  * For a non-interactive shell, an error condition encountered
10954  * by a special built-in ... shall cause the shell to write a diagnostic message
10955  * to standard error and exit as shown in the following table:
10956  * Error                                           Special Built-In
10957  * ...
10958  * Utility syntax error (option or operand error)  Shall exit
10959  * ...
10960  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10961  * we see that bash does not do that (set "finishes" with error code 1 instead,
10962  * and shell continues), and people rely on this behavior!
10963  * Testcase:
10964  * set -o barfoo 2>/dev/null
10965  * echo $?
10966  *
10967  * Oh well. Let's mimic that.
10968  */
10969 static int
10970 plus_minus_o(char *name, int val)
10971 {
10972         int i;
10973
10974         if (name) {
10975                 for (i = 0; i < NOPTS; i++) {
10976                         if (strcmp(name, optnames(i)) == 0) {
10977                                 optlist[i] = val;
10978                                 return 0;
10979                         }
10980                 }
10981                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10982                 return 1;
10983         }
10984         for (i = 0; i < NOPTS; i++) {
10985                 if (val) {
10986                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10987                 } else {
10988                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10989                 }
10990         }
10991         return 0;
10992 }
10993 static void
10994 setoption(int flag, int val)
10995 {
10996         int i;
10997
10998         for (i = 0; i < NOPTS; i++) {
10999                 if (optletters(i) == flag) {
11000                         optlist[i] = val;
11001                         return;
11002                 }
11003         }
11004         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11005         /* NOTREACHED */
11006 }
11007 static int
11008 options(int cmdline, int *login_sh)
11009 {
11010         char *p;
11011         int val;
11012         int c;
11013
11014         if (cmdline)
11015                 minusc = NULL;
11016         while ((p = *argptr) != NULL) {
11017                 c = *p++;
11018                 if (c != '-' && c != '+')
11019                         break;
11020                 argptr++;
11021                 val = 0; /* val = 0 if c == '+' */
11022                 if (c == '-') {
11023                         val = 1;
11024                         if (p[0] == '\0' || LONE_DASH(p)) {
11025                                 if (!cmdline) {
11026                                         /* "-" means turn off -x and -v */
11027                                         if (p[0] == '\0')
11028                                                 xflag = vflag = 0;
11029                                         /* "--" means reset params */
11030                                         else if (*argptr == NULL)
11031                                                 setparam(argptr);
11032                                 }
11033                                 break;    /* "-" or "--" terminates options */
11034                         }
11035                 }
11036                 /* first char was + or - */
11037                 while ((c = *p++) != '\0') {
11038                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11039                         if (c == 'c' && cmdline) {
11040                                 minusc = p;     /* command is after shell args */
11041                         } else if (c == 'o') {
11042                                 if (plus_minus_o(*argptr, val)) {
11043                                         /* it already printed err message */
11044                                         return 1; /* error */
11045                                 }
11046                                 if (*argptr)
11047                                         argptr++;
11048                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11049                                 if (login_sh)
11050                                         *login_sh = 1;
11051                         /* bash does not accept +-login, we also won't */
11052                         } else if (cmdline && val && (c == '-')) { /* long options */
11053                                 if (strcmp(p, "login") == 0) {
11054                                         if (login_sh)
11055                                                 *login_sh = 1;
11056                                 }
11057                                 break;
11058                         } else {
11059                                 setoption(c, val);
11060                         }
11061                 }
11062         }
11063         return 0;
11064 }
11065
11066 /*
11067  * The shift builtin command.
11068  */
11069 static int FAST_FUNC
11070 shiftcmd(int argc UNUSED_PARAM, char **argv)
11071 {
11072         int n;
11073         char **ap1, **ap2;
11074
11075         n = 1;
11076         if (argv[1])
11077                 n = number(argv[1]);
11078         if (n > shellparam.nparam)
11079                 return 1;
11080         INT_OFF;
11081         shellparam.nparam -= n;
11082         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11083                 if (shellparam.malloced)
11084                         free(*ap1);
11085         }
11086         ap2 = shellparam.p;
11087         while ((*ap2++ = *ap1++) != NULL)
11088                 continue;
11089 #if ENABLE_ASH_GETOPTS
11090         shellparam.optind = 1;
11091         shellparam.optoff = -1;
11092 #endif
11093         INT_ON;
11094         return 0;
11095 }
11096
11097 /*
11098  * POSIX requires that 'set' (but not export or readonly) output the
11099  * variables in lexicographic order - by the locale's collating order (sigh).
11100  * Maybe we could keep them in an ordered balanced binary tree
11101  * instead of hashed lists.
11102  * For now just roll 'em through qsort for printing...
11103  */
11104 static int
11105 showvars(const char *sep_prefix, int on, int off)
11106 {
11107         const char *sep;
11108         char **ep, **epend;
11109
11110         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11111         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11112
11113         sep = *sep_prefix ? " " : sep_prefix;
11114
11115         for (; ep < epend; ep++) {
11116                 const char *p;
11117                 const char *q;
11118
11119                 p = endofname(*ep);
11120 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11121  * makes "export -p" to have output not suitable for "eval":
11122  * import os
11123  * os.environ["test-test"]="test"
11124  * if os.fork() == 0:
11125  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11126  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11127  */
11128                 q = nullstr;
11129                 if (*p == '=')
11130                         q = single_quote(++p);
11131                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11132         }
11133         return 0;
11134 }
11135
11136 /*
11137  * The set command builtin.
11138  */
11139 static int FAST_FUNC
11140 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11141 {
11142         int retval;
11143
11144         if (!argv[1])
11145                 return showvars(nullstr, 0, VUNSET);
11146
11147         INT_OFF;
11148         retval = options(/*cmdline:*/ 0, NULL);
11149         if (retval == 0) { /* if no parse error... */
11150                 optschanged();
11151                 if (*argptr != NULL) {
11152                         setparam(argptr);
11153                 }
11154         }
11155         INT_ON;
11156         return retval;
11157 }
11158
11159 #if ENABLE_ASH_RANDOM_SUPPORT
11160 static void FAST_FUNC
11161 change_random(const char *value)
11162 {
11163         uint32_t t;
11164
11165         if (value == NULL) {
11166                 /* "get", generate */
11167                 t = next_random(&random_gen);
11168                 /* set without recursion */
11169                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11170                 vrandom.flags &= ~VNOFUNC;
11171         } else {
11172                 /* set/reset */
11173                 t = strtoul(value, NULL, 10);
11174                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11175         }
11176 }
11177 #endif
11178
11179 #if ENABLE_ASH_GETOPTS
11180 static int
11181 getopts(char *optstr, char *optvar, char **optfirst)
11182 {
11183         char *p, *q;
11184         char c = '?';
11185         int done = 0;
11186         char sbuf[2];
11187         char **optnext;
11188         int ind = shellparam.optind;
11189         int off = shellparam.optoff;
11190
11191         sbuf[1] = '\0';
11192
11193         shellparam.optind = -1;
11194         optnext = optfirst + ind - 1;
11195
11196         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11197                 p = NULL;
11198         else
11199                 p = optnext[-1] + off;
11200         if (p == NULL || *p == '\0') {
11201                 /* Current word is done, advance */
11202                 p = *optnext;
11203                 if (p == NULL || *p != '-' || *++p == '\0') {
11204  atend:
11205                         unsetvar("OPTARG");
11206                         p = NULL;
11207                         done = 1;
11208                         goto out;
11209                 }
11210                 optnext++;
11211                 if (LONE_DASH(p))        /* check for "--" */
11212                         goto atend;
11213         }
11214
11215         c = *p++;
11216         for (q = optstr; *q != c;) {
11217                 if (*q == '\0') {
11218                         /* OPTERR is a bashism */
11219                         const char *cp = lookupvar("OPTERR");
11220                         if ((cp && LONE_CHAR(cp, '0'))
11221                          || (optstr[0] == ':')
11222                         ) {
11223                                 sbuf[0] = c;
11224                                 /*sbuf[1] = '\0'; - already is */
11225                                 setvar0("OPTARG", sbuf);
11226                         } else {
11227                                 fprintf(stderr, "Illegal option -%c\n", c);
11228                                 unsetvar("OPTARG");
11229                         }
11230                         c = '?';
11231                         goto out;
11232                 }
11233                 if (*++q == ':')
11234                         q++;
11235         }
11236
11237         if (*++q == ':') {
11238                 if (*p == '\0' && (p = *optnext) == NULL) {
11239                         /* OPTERR is a bashism */
11240                         const char *cp = lookupvar("OPTERR");
11241                         if ((cp && LONE_CHAR(cp, '0'))
11242                          || (optstr[0] == ':')
11243                         ) {
11244                                 sbuf[0] = c;
11245                                 /*sbuf[1] = '\0'; - already is */
11246                                 setvar0("OPTARG", sbuf);
11247                                 c = ':';
11248                         } else {
11249                                 fprintf(stderr, "No arg for -%c option\n", c);
11250                                 unsetvar("OPTARG");
11251                                 c = '?';
11252                         }
11253                         goto out;
11254                 }
11255
11256                 if (p == *optnext)
11257                         optnext++;
11258                 setvar0("OPTARG", p);
11259                 p = NULL;
11260         } else
11261                 setvar0("OPTARG", nullstr);
11262  out:
11263         ind = optnext - optfirst + 1;
11264         setvar("OPTIND", itoa(ind), VNOFUNC);
11265         sbuf[0] = c;
11266         /*sbuf[1] = '\0'; - already is */
11267         setvar0(optvar, sbuf);
11268
11269         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11270         shellparam.optind = ind;
11271
11272         return done;
11273 }
11274
11275 /*
11276  * The getopts builtin.  Shellparam.optnext points to the next argument
11277  * to be processed.  Shellparam.optptr points to the next character to
11278  * be processed in the current argument.  If shellparam.optnext is NULL,
11279  * then it's the first time getopts has been called.
11280  */
11281 static int FAST_FUNC
11282 getoptscmd(int argc, char **argv)
11283 {
11284         char **optbase;
11285
11286         if (argc < 3)
11287                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11288         if (argc == 3) {
11289                 optbase = shellparam.p;
11290                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11291                         shellparam.optind = 1;
11292                         shellparam.optoff = -1;
11293                 }
11294         } else {
11295                 optbase = &argv[3];
11296                 if ((unsigned)shellparam.optind > argc - 2) {
11297                         shellparam.optind = 1;
11298                         shellparam.optoff = -1;
11299                 }
11300         }
11301
11302         return getopts(argv[1], argv[2], optbase);
11303 }
11304 #endif /* ASH_GETOPTS */
11305
11306
11307 /* ============ Shell parser */
11308
11309 struct heredoc {
11310         struct heredoc *next;   /* next here document in list */
11311         union node *here;       /* redirection node */
11312         char *eofmark;          /* string indicating end of input */
11313         smallint striptabs;     /* if set, strip leading tabs */
11314 };
11315
11316 static smallint tokpushback;           /* last token pushed back */
11317 static smallint quoteflag;             /* set if (part of) last token was quoted */
11318 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11319 static struct heredoc *heredoclist;    /* list of here documents to read */
11320 static char *wordtext;                 /* text of last word returned by readtoken */
11321 static struct nodelist *backquotelist;
11322 static union node *redirnode;
11323 static struct heredoc *heredoc;
11324
11325 static const char *
11326 tokname(char *buf, int tok)
11327 {
11328         if (tok < TSEMI)
11329                 return tokname_array[tok];
11330         sprintf(buf, "\"%s\"", tokname_array[tok]);
11331         return buf;
11332 }
11333
11334 /* raise_error_unexpected_syntax:
11335  * Called when an unexpected token is read during the parse.  The argument
11336  * is the token that is expected, or -1 if more than one type of token can
11337  * occur at this point.
11338  */
11339 static void raise_error_unexpected_syntax(int) NORETURN;
11340 static void
11341 raise_error_unexpected_syntax(int token)
11342 {
11343         char msg[64];
11344         char buf[16];
11345         int l;
11346
11347         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11348         if (token >= 0)
11349                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11350         raise_error_syntax(msg);
11351         /* NOTREACHED */
11352 }
11353
11354 /* parsing is heavily cross-recursive, need these forward decls */
11355 static union node *andor(void);
11356 static union node *pipeline(void);
11357 static union node *parse_command(void);
11358 static void parseheredoc(void);
11359 static int peektoken(void);
11360 static int readtoken(void);
11361
11362 static union node *
11363 list(int nlflag)
11364 {
11365         union node *n1, *n2, *n3;
11366         int tok;
11367
11368         n1 = NULL;
11369         for (;;) {
11370                 switch (peektoken()) {
11371                 case TNL:
11372                         if (!(nlflag & 1))
11373                                 break;
11374                         parseheredoc();
11375                         return n1;
11376
11377                 case TEOF:
11378                         if (!n1 && (nlflag & 1))
11379                                 n1 = NODE_EOF;
11380                         parseheredoc();
11381                         return n1;
11382                 }
11383
11384                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11385                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11386                         return n1;
11387                 nlflag |= 2;
11388
11389                 n2 = andor();
11390                 tok = readtoken();
11391                 if (tok == TBACKGND) {
11392                         if (n2->type == NPIPE) {
11393                                 n2->npipe.pipe_backgnd = 1;
11394                         } else {
11395                                 if (n2->type != NREDIR) {
11396                                         n3 = stzalloc(sizeof(struct nredir));
11397                                         n3->nredir.n = n2;
11398                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11399                                         n2 = n3;
11400                                 }
11401                                 n2->type = NBACKGND;
11402                         }
11403                 }
11404                 if (n1 == NULL) {
11405                         n1 = n2;
11406                 } else {
11407                         n3 = stzalloc(sizeof(struct nbinary));
11408                         n3->type = NSEMI;
11409                         n3->nbinary.ch1 = n1;
11410                         n3->nbinary.ch2 = n2;
11411                         n1 = n3;
11412                 }
11413                 switch (tok) {
11414                 case TNL:
11415                 case TEOF:
11416                         tokpushback = 1;
11417                         /* fall through */
11418                 case TBACKGND:
11419                 case TSEMI:
11420                         break;
11421                 default:
11422                         if ((nlflag & 1))
11423                                 raise_error_unexpected_syntax(-1);
11424                         tokpushback = 1;
11425                         return n1;
11426                 }
11427         }
11428 }
11429
11430 static union node *
11431 andor(void)
11432 {
11433         union node *n1, *n2, *n3;
11434         int t;
11435
11436         n1 = pipeline();
11437         for (;;) {
11438                 t = readtoken();
11439                 if (t == TAND) {
11440                         t = NAND;
11441                 } else if (t == TOR) {
11442                         t = NOR;
11443                 } else {
11444                         tokpushback = 1;
11445                         return n1;
11446                 }
11447                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11448                 n2 = pipeline();
11449                 n3 = stzalloc(sizeof(struct nbinary));
11450                 n3->type = t;
11451                 n3->nbinary.ch1 = n1;
11452                 n3->nbinary.ch2 = n2;
11453                 n1 = n3;
11454         }
11455 }
11456
11457 static union node *
11458 pipeline(void)
11459 {
11460         union node *n1, *n2, *pipenode;
11461         struct nodelist *lp, *prev;
11462         int negate;
11463
11464         negate = 0;
11465         TRACE(("pipeline: entered\n"));
11466         if (readtoken() == TNOT) {
11467                 negate = !negate;
11468                 checkkwd = CHKKWD | CHKALIAS;
11469         } else
11470                 tokpushback = 1;
11471         n1 = parse_command();
11472         if (readtoken() == TPIPE) {
11473                 pipenode = stzalloc(sizeof(struct npipe));
11474                 pipenode->type = NPIPE;
11475                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11476                 lp = stzalloc(sizeof(struct nodelist));
11477                 pipenode->npipe.cmdlist = lp;
11478                 lp->n = n1;
11479                 do {
11480                         prev = lp;
11481                         lp = stzalloc(sizeof(struct nodelist));
11482                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11483                         lp->n = parse_command();
11484                         prev->next = lp;
11485                 } while (readtoken() == TPIPE);
11486                 lp->next = NULL;
11487                 n1 = pipenode;
11488         }
11489         tokpushback = 1;
11490         if (negate) {
11491                 n2 = stzalloc(sizeof(struct nnot));
11492                 n2->type = NNOT;
11493                 n2->nnot.com = n1;
11494                 return n2;
11495         }
11496         return n1;
11497 }
11498
11499 static union node *
11500 makename(void)
11501 {
11502         union node *n;
11503
11504         n = stzalloc(sizeof(struct narg));
11505         n->type = NARG;
11506         /*n->narg.next = NULL; - stzalloc did it */
11507         n->narg.text = wordtext;
11508         n->narg.backquote = backquotelist;
11509         return n;
11510 }
11511
11512 static void
11513 fixredir(union node *n, const char *text, int err)
11514 {
11515         int fd;
11516
11517         TRACE(("Fix redir %s %d\n", text, err));
11518         if (!err)
11519                 n->ndup.vname = NULL;
11520
11521         fd = bb_strtou(text, NULL, 10);
11522         if (!errno && fd >= 0)
11523                 n->ndup.dupfd = fd;
11524         else if (LONE_DASH(text))
11525                 n->ndup.dupfd = -1;
11526         else {
11527                 if (err)
11528                         raise_error_syntax("bad fd number");
11529                 n->ndup.vname = makename();
11530         }
11531 }
11532
11533 static void
11534 parsefname(void)
11535 {
11536         union node *n = redirnode;
11537
11538         if (n->type == NHERE)
11539                 checkkwd = CHKEOFMARK;
11540         if (readtoken() != TWORD)
11541                 raise_error_unexpected_syntax(-1);
11542         if (n->type == NHERE) {
11543                 struct heredoc *here = heredoc;
11544                 struct heredoc *p;
11545
11546                 if (quoteflag == 0)
11547                         n->type = NXHERE;
11548                 TRACE(("Here document %d\n", n->type));
11549                 rmescapes(wordtext, 0, NULL);
11550                 here->eofmark = wordtext;
11551                 here->next = NULL;
11552                 if (heredoclist == NULL)
11553                         heredoclist = here;
11554                 else {
11555                         for (p = heredoclist; p->next; p = p->next)
11556                                 continue;
11557                         p->next = here;
11558                 }
11559         } else if (n->type == NTOFD || n->type == NFROMFD) {
11560                 fixredir(n, wordtext, 0);
11561         } else {
11562                 n->nfile.fname = makename();
11563         }
11564 }
11565
11566 static union node *
11567 simplecmd(void)
11568 {
11569         union node *args, **app;
11570         union node *n = NULL;
11571         union node *vars, **vpp;
11572         union node **rpp, *redir;
11573         int savecheckkwd;
11574         int savelinno;
11575 #if BASH_TEST2
11576         smallint double_brackets_flag = 0;
11577 #endif
11578         IF_BASH_FUNCTION(smallint function_flag = 0;)
11579
11580         args = NULL;
11581         app = &args;
11582         vars = NULL;
11583         vpp = &vars;
11584         redir = NULL;
11585         rpp = &redir;
11586
11587         savecheckkwd = CHKALIAS;
11588         savelinno = g_parsefile->linno;
11589         for (;;) {
11590                 int t;
11591                 checkkwd = savecheckkwd;
11592                 t = readtoken();
11593                 switch (t) {
11594 #if BASH_FUNCTION
11595                 case TFUNCTION:
11596                         if (peektoken() != TWORD)
11597                                 raise_error_unexpected_syntax(TWORD);
11598                         function_flag = 1;
11599                         break;
11600 #endif
11601 #if BASH_TEST2
11602                 case TAND: /* "&&" */
11603                 case TOR: /* "||" */
11604                         if (!double_brackets_flag) {
11605                                 tokpushback = 1;
11606                                 goto out;
11607                         }
11608                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11609 #endif
11610                 case TWORD:
11611                         n = stzalloc(sizeof(struct narg));
11612                         n->type = NARG;
11613                         /*n->narg.next = NULL; - stzalloc did it */
11614                         n->narg.text = wordtext;
11615 #if BASH_TEST2
11616                         if (strcmp("[[", wordtext) == 0)
11617                                 double_brackets_flag = 1;
11618                         else if (strcmp("]]", wordtext) == 0)
11619                                 double_brackets_flag = 0;
11620 #endif
11621                         n->narg.backquote = backquotelist;
11622                         if (savecheckkwd && isassignment(wordtext)) {
11623                                 *vpp = n;
11624                                 vpp = &n->narg.next;
11625                         } else {
11626                                 *app = n;
11627                                 app = &n->narg.next;
11628                                 savecheckkwd = 0;
11629                         }
11630 #if BASH_FUNCTION
11631                         if (function_flag) {
11632                                 checkkwd = CHKNL | CHKKWD;
11633                                 switch (peektoken()) {
11634                                 case TBEGIN:
11635                                 case TIF:
11636                                 case TCASE:
11637                                 case TUNTIL:
11638                                 case TWHILE:
11639                                 case TFOR:
11640                                         goto do_func;
11641                                 case TLP:
11642                                         function_flag = 0;
11643                                         break;
11644 # if BASH_TEST2
11645                                 case TWORD:
11646                                         if (strcmp("[[", wordtext) == 0)
11647                                                 goto do_func;
11648                                         /* fall through */
11649 # endif
11650                                 default:
11651                                         raise_error_unexpected_syntax(-1);
11652                                 }
11653                         }
11654 #endif
11655                         break;
11656                 case TREDIR:
11657                         *rpp = n = redirnode;
11658                         rpp = &n->nfile.next;
11659                         parsefname();   /* read name of redirection file */
11660                         break;
11661                 case TLP:
11662  IF_BASH_FUNCTION(do_func:)
11663                         if (args && app == &args->narg.next
11664                          && !vars && !redir
11665                         ) {
11666                                 struct builtincmd *bcmd;
11667                                 const char *name;
11668
11669                                 /* We have a function */
11670                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11671                                         raise_error_unexpected_syntax(TRP);
11672                                 name = n->narg.text;
11673                                 if (!goodname(name)
11674                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11675                                 ) {
11676                                         raise_error_syntax("bad function name");
11677                                 }
11678                                 n->type = NDEFUN;
11679                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11680                                 n->ndefun.text = n->narg.text;
11681                                 n->ndefun.linno = g_parsefile->linno;
11682                                 n->ndefun.body = parse_command();
11683                                 return n;
11684                         }
11685                         IF_BASH_FUNCTION(function_flag = 0;)
11686                         /* fall through */
11687                 default:
11688                         tokpushback = 1;
11689                         goto out;
11690                 }
11691         }
11692  out:
11693         *app = NULL;
11694         *vpp = NULL;
11695         *rpp = NULL;
11696         n = stzalloc(sizeof(struct ncmd));
11697         if (NCMD != 0)
11698                 n->type = NCMD;
11699         n->ncmd.linno = savelinno;
11700         n->ncmd.args = args;
11701         n->ncmd.assign = vars;
11702         n->ncmd.redirect = redir;
11703         return n;
11704 }
11705
11706 static union node *
11707 parse_command(void)
11708 {
11709         union node *n1, *n2;
11710         union node *ap, **app;
11711         union node *cp, **cpp;
11712         union node *redir, **rpp;
11713         union node **rpp2;
11714         int t;
11715         int savelinno;
11716
11717         redir = NULL;
11718         rpp2 = &redir;
11719
11720         savelinno = g_parsefile->linno;
11721
11722         switch (readtoken()) {
11723         default:
11724                 raise_error_unexpected_syntax(-1);
11725                 /* NOTREACHED */
11726         case TIF:
11727                 n1 = stzalloc(sizeof(struct nif));
11728                 n1->type = NIF;
11729                 n1->nif.test = list(0);
11730                 if (readtoken() != TTHEN)
11731                         raise_error_unexpected_syntax(TTHEN);
11732                 n1->nif.ifpart = list(0);
11733                 n2 = n1;
11734                 while (readtoken() == TELIF) {
11735                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11736                         n2 = n2->nif.elsepart;
11737                         n2->type = NIF;
11738                         n2->nif.test = list(0);
11739                         if (readtoken() != TTHEN)
11740                                 raise_error_unexpected_syntax(TTHEN);
11741                         n2->nif.ifpart = list(0);
11742                 }
11743                 if (lasttoken == TELSE)
11744                         n2->nif.elsepart = list(0);
11745                 else {
11746                         n2->nif.elsepart = NULL;
11747                         tokpushback = 1;
11748                 }
11749                 t = TFI;
11750                 break;
11751         case TWHILE:
11752         case TUNTIL: {
11753                 int got;
11754                 n1 = stzalloc(sizeof(struct nbinary));
11755                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11756                 n1->nbinary.ch1 = list(0);
11757                 got = readtoken();
11758                 if (got != TDO) {
11759                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11760                                         got == TWORD ? wordtext : ""));
11761                         raise_error_unexpected_syntax(TDO);
11762                 }
11763                 n1->nbinary.ch2 = list(0);
11764                 t = TDONE;
11765                 break;
11766         }
11767         case TFOR:
11768                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11769                         raise_error_syntax("bad for loop variable");
11770                 n1 = stzalloc(sizeof(struct nfor));
11771                 n1->type = NFOR;
11772                 n1->nfor.linno = savelinno;
11773                 n1->nfor.var = wordtext;
11774                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11775                 if (readtoken() == TIN) {
11776                         app = &ap;
11777                         while (readtoken() == TWORD) {
11778                                 n2 = stzalloc(sizeof(struct narg));
11779                                 n2->type = NARG;
11780                                 /*n2->narg.next = NULL; - stzalloc did it */
11781                                 n2->narg.text = wordtext;
11782                                 n2->narg.backquote = backquotelist;
11783                                 *app = n2;
11784                                 app = &n2->narg.next;
11785                         }
11786                         *app = NULL;
11787                         n1->nfor.args = ap;
11788                         if (lasttoken != TNL && lasttoken != TSEMI)
11789                                 raise_error_unexpected_syntax(-1);
11790                 } else {
11791                         n2 = stzalloc(sizeof(struct narg));
11792                         n2->type = NARG;
11793                         /*n2->narg.next = NULL; - stzalloc did it */
11794                         n2->narg.text = (char *)dolatstr;
11795                         /*n2->narg.backquote = NULL;*/
11796                         n1->nfor.args = n2;
11797                         /*
11798                          * Newline or semicolon here is optional (but note
11799                          * that the original Bourne shell only allowed NL).
11800                          */
11801                         if (lasttoken != TSEMI)
11802                                 tokpushback = 1;
11803                 }
11804                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11805                 if (readtoken() != TDO)
11806                         raise_error_unexpected_syntax(TDO);
11807                 n1->nfor.body = list(0);
11808                 t = TDONE;
11809                 break;
11810         case TCASE:
11811                 n1 = stzalloc(sizeof(struct ncase));
11812                 n1->type = NCASE;
11813                 n1->ncase.linno = savelinno;
11814                 if (readtoken() != TWORD)
11815                         raise_error_unexpected_syntax(TWORD);
11816                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11817                 n2->type = NARG;
11818                 /*n2->narg.next = NULL; - stzalloc did it */
11819                 n2->narg.text = wordtext;
11820                 n2->narg.backquote = backquotelist;
11821                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11822                 if (readtoken() != TIN)
11823                         raise_error_unexpected_syntax(TIN);
11824                 cpp = &n1->ncase.cases;
11825  next_case:
11826                 checkkwd = CHKNL | CHKKWD;
11827                 t = readtoken();
11828                 while (t != TESAC) {
11829                         if (lasttoken == TLP)
11830                                 readtoken();
11831                         *cpp = cp = stzalloc(sizeof(struct nclist));
11832                         cp->type = NCLIST;
11833                         app = &cp->nclist.pattern;
11834                         for (;;) {
11835                                 *app = ap = stzalloc(sizeof(struct narg));
11836                                 ap->type = NARG;
11837                                 /*ap->narg.next = NULL; - stzalloc did it */
11838                                 ap->narg.text = wordtext;
11839                                 ap->narg.backquote = backquotelist;
11840                                 if (readtoken() != TPIPE)
11841                                         break;
11842                                 app = &ap->narg.next;
11843                                 readtoken();
11844                         }
11845                         //ap->narg.next = NULL;
11846                         if (lasttoken != TRP)
11847                                 raise_error_unexpected_syntax(TRP);
11848                         cp->nclist.body = list(2);
11849
11850                         cpp = &cp->nclist.next;
11851
11852                         checkkwd = CHKNL | CHKKWD;
11853                         t = readtoken();
11854                         if (t != TESAC) {
11855                                 if (t != TENDCASE)
11856                                         raise_error_unexpected_syntax(TENDCASE);
11857                                 goto next_case;
11858                         }
11859                 }
11860                 *cpp = NULL;
11861                 goto redir;
11862         case TLP:
11863                 n1 = stzalloc(sizeof(struct nredir));
11864                 n1->type = NSUBSHELL;
11865                 n1->nredir.linno = savelinno;
11866                 n1->nredir.n = list(0);
11867                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11868                 t = TRP;
11869                 break;
11870         case TBEGIN:
11871                 n1 = list(0);
11872                 t = TEND;
11873                 break;
11874         IF_BASH_FUNCTION(case TFUNCTION:)
11875         case TWORD:
11876         case TREDIR:
11877                 tokpushback = 1;
11878                 return simplecmd();
11879         }
11880
11881         if (readtoken() != t)
11882                 raise_error_unexpected_syntax(t);
11883
11884  redir:
11885         /* Now check for redirection which may follow command */
11886         checkkwd = CHKKWD | CHKALIAS;
11887         rpp = rpp2;
11888         while (readtoken() == TREDIR) {
11889                 *rpp = n2 = redirnode;
11890                 rpp = &n2->nfile.next;
11891                 parsefname();
11892         }
11893         tokpushback = 1;
11894         *rpp = NULL;
11895         if (redir) {
11896                 if (n1->type != NSUBSHELL) {
11897                         n2 = stzalloc(sizeof(struct nredir));
11898                         n2->type = NREDIR;
11899                         n2->nredir.linno = savelinno;
11900                         n2->nredir.n = n1;
11901                         n1 = n2;
11902                 }
11903                 n1->nredir.redirect = redir;
11904         }
11905         return n1;
11906 }
11907
11908 #if BASH_DOLLAR_SQUOTE
11909 static int
11910 decode_dollar_squote(void)
11911 {
11912         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11913         int c, cnt;
11914         char *p;
11915         char buf[4];
11916
11917         c = pgetc();
11918         p = strchr(C_escapes, c);
11919         if (p) {
11920                 buf[0] = c;
11921                 p = buf;
11922                 cnt = 3;
11923                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11924                         do {
11925                                 c = pgetc();
11926                                 *++p = c;
11927                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11928                         pungetc();
11929                 } else if (c == 'x') { /* \xHH */
11930                         do {
11931                                 c = pgetc();
11932                                 *++p = c;
11933                         } while (isxdigit(c) && --cnt);
11934                         pungetc();
11935                         if (cnt == 3) { /* \x but next char is "bad" */
11936                                 c = 'x';
11937                                 goto unrecognized;
11938                         }
11939                 } else { /* simple seq like \\ or \t */
11940                         p++;
11941                 }
11942                 *p = '\0';
11943                 p = buf;
11944                 c = bb_process_escape_sequence((void*)&p);
11945         } else { /* unrecognized "\z": print both chars unless ' or " */
11946                 if (c != '\'' && c != '"') {
11947  unrecognized:
11948                         c |= 0x100; /* "please encode \, then me" */
11949                 }
11950         }
11951         return c;
11952 }
11953 #endif
11954
11955 /* Used by expandstr to get here-doc like behaviour. */
11956 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11957
11958 static ALWAYS_INLINE int
11959 realeofmark(const char *eofmark)
11960 {
11961         return eofmark && eofmark != FAKEEOFMARK;
11962 }
11963
11964 /*
11965  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11966  * is not NULL, read a here document.  In the latter case, eofmark is the
11967  * word which marks the end of the document and striptabs is true if
11968  * leading tabs should be stripped from the document.  The argument c
11969  * is the first character of the input token or document.
11970  *
11971  * Because C does not have internal subroutines, I have simulated them
11972  * using goto's to implement the subroutine linkage.  The following macros
11973  * will run code that appears at the end of readtoken1.
11974  */
11975 #define CHECKEND()      {goto checkend; checkend_return:;}
11976 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11977 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11978 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11979 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11980 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11981 static int
11982 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11983 {
11984         /* NB: syntax parameter fits into smallint */
11985         /* c parameter is an unsigned char or PEOF or PEOA */
11986         char *out;
11987         size_t len;
11988         struct nodelist *bqlist;
11989         smallint quotef;
11990         smallint oldstyle;
11991         smallint pssyntax;   /* we are expanding a prompt string */
11992         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11993         /* syntax stack */
11994         struct synstack synbase = { };
11995         struct synstack *synstack = &synbase;
11996
11997 #if ENABLE_ASH_EXPAND_PRMT
11998         pssyntax = (syntax == PSSYNTAX);
11999         if (pssyntax)
12000                 syntax = DQSYNTAX;
12001 #else
12002         pssyntax = 0; /* constant */
12003 #endif
12004         synstack->syntax = syntax;
12005
12006         if (syntax == DQSYNTAX)
12007                 synstack->dblquote = 1;
12008         quotef = 0;
12009         bqlist = NULL;
12010
12011         STARTSTACKSTR(out);
12012  loop:
12013         /* For each line, until end of word */
12014         CHECKEND();     /* set c to PEOF if at end of here document */
12015         for (;;) {      /* until end of line or end of word */
12016                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12017                 switch (SIT(c, synstack->syntax)) {
12018                 case CNL:       /* '\n' */
12019                         if (synstack->syntax == BASESYNTAX
12020                          && !synstack->varnest
12021                         ) {
12022                                 goto endword;   /* exit outer loop */
12023                         }
12024                         USTPUTC(c, out);
12025                         nlprompt();
12026                         c = pgetc();
12027                         goto loop;              /* continue outer loop */
12028                 case CWORD:
12029                         USTPUTC(c, out);
12030                         break;
12031                 case CCTL:
12032 #if BASH_DOLLAR_SQUOTE
12033                         if (c == '\\' && bash_dollar_squote) {
12034                                 c = decode_dollar_squote();
12035                                 if (c == '\0') {
12036                                         /* skip $'\000', $'\x00' (like bash) */
12037                                         break;
12038                                 }
12039                                 if (c & 0x100) {
12040                                         /* Unknown escape. Encode as '\z' */
12041                                         c = (unsigned char)c;
12042                                         if (eofmark == NULL || synstack->dblquote)
12043                                                 USTPUTC(CTLESC, out);
12044                                         USTPUTC('\\', out);
12045                                 }
12046                         }
12047 #endif
12048                         if (!eofmark || synstack->dblquote || synstack->varnest)
12049                                 USTPUTC(CTLESC, out);
12050                         USTPUTC(c, out);
12051                         break;
12052                 case CBACK:     /* backslash */
12053                         c = pgetc_without_PEOA();
12054                         if (c == PEOF) {
12055                                 USTPUTC(CTLESC, out);
12056                                 USTPUTC('\\', out);
12057                                 pungetc();
12058                         } else if (c == '\n') {
12059                                 nlprompt();
12060                         } else {
12061                                 if (pssyntax && c == '$') {
12062                                         USTPUTC(CTLESC, out);
12063                                         USTPUTC('\\', out);
12064                                 }
12065                                 /* Backslash is retained if we are in "str"
12066                                  * and next char isn't dquote-special.
12067                                  */
12068                                 if (synstack->dblquote
12069                                  && c != '\\'
12070                                  && c != '`'
12071                                  && c != '$'
12072                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12073                                  && (c != '}' || !synstack->varnest)
12074                                 ) {
12075                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12076                                         USTPUTC('\\', out);
12077                                 }
12078                                 USTPUTC(CTLESC, out);
12079                                 USTPUTC(c, out);
12080                                 quotef = 1;
12081                         }
12082                         break;
12083                 case CSQUOTE:
12084                         synstack->syntax = SQSYNTAX;
12085  quotemark:
12086                         if (eofmark == NULL) {
12087                                 USTPUTC(CTLQUOTEMARK, out);
12088                         }
12089                         break;
12090                 case CDQUOTE:
12091                         synstack->syntax = DQSYNTAX;
12092                         synstack->dblquote = 1;
12093  toggledq:
12094                         if (synstack->varnest)
12095                                 synstack->innerdq ^= 1;
12096                         goto quotemark;
12097                 case CENDQUOTE:
12098                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12099                         if (eofmark != NULL && synstack->varnest == 0) {
12100                                 USTPUTC(c, out);
12101                                 break;
12102                         }
12103
12104                         if (synstack->dqvarnest == 0) {
12105                                 synstack->syntax = BASESYNTAX;
12106                                 synstack->dblquote = 0;
12107                         }
12108
12109                         quotef = 1;
12110
12111                         if (c == '"')
12112                                 goto toggledq;
12113
12114                         goto quotemark;
12115                 case CVAR:      /* '$' */
12116                         PARSESUB();             /* parse substitution */
12117                         break;
12118                 case CENDVAR:   /* '}' */
12119                         if (!synstack->innerdq && synstack->varnest > 0) {
12120                                 if (!--synstack->varnest && synstack->varpushed)
12121                                         synstack_pop(&synstack);
12122                                 else if (synstack->dqvarnest > 0)
12123                                         synstack->dqvarnest--;
12124                                 c = CTLENDVAR;
12125                         }
12126                         USTPUTC(c, out);
12127                         break;
12128 #if ENABLE_FEATURE_SH_MATH
12129                 case CLP:       /* '(' in arithmetic */
12130                         synstack->parenlevel++;
12131                         USTPUTC(c, out);
12132                         break;
12133                 case CRP:       /* ')' in arithmetic */
12134                         if (synstack->parenlevel > 0) {
12135                                 synstack->parenlevel--;
12136                         } else {
12137                                 if (pgetc_eatbnl() == ')') {
12138                                         c = CTLENDARI;
12139                                         synstack_pop(&synstack);
12140                                 } else {
12141                                         /*
12142                                          * unbalanced parens
12143                                          * (don't 2nd guess - no error)
12144                                          */
12145                                         pungetc();
12146                                 }
12147                         }
12148                         USTPUTC(c, out);
12149                         break;
12150 #endif
12151                 case CBQUOTE:   /* '`' */
12152                         if (checkkwd & CHKEOFMARK) {
12153                                 quotef = 1;
12154                                 USTPUTC('`', out);
12155                                 break;
12156                         }
12157
12158                         PARSEBACKQOLD();
12159                         break;
12160                 case CENDFILE:
12161                         goto endword;           /* exit outer loop */
12162                 case CIGN:
12163                         break;
12164                 default:
12165                         if (synstack->varnest == 0) {
12166 #if BASH_REDIR_OUTPUT
12167                                 if (c == '&') {
12168 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12169                                         if (pgetc() == '>')
12170                                                 c = 0x100 + '>'; /* flag &> */
12171                                         pungetc();
12172                                 }
12173 #endif
12174                                 goto endword;   /* exit outer loop */
12175                         }
12176                         IF_ASH_ALIAS(if (c != PEOA))
12177                                 USTPUTC(c, out);
12178                 }
12179                 c = pgetc();
12180         } /* for (;;) */
12181  endword:
12182
12183 #if ENABLE_FEATURE_SH_MATH
12184         if (synstack->syntax == ARISYNTAX)
12185                 raise_error_syntax("missing '))'");
12186 #endif
12187         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12188                 raise_error_syntax("unterminated quoted string");
12189         if (synstack->varnest != 0) {
12190                 /* { */
12191                 raise_error_syntax("missing '}'");
12192         }
12193         USTPUTC('\0', out);
12194         len = out - (char *)stackblock();
12195         out = stackblock();
12196         if (eofmark == NULL) {
12197                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12198                  && quotef == 0
12199                 ) {
12200                         if (isdigit_str9(out)) {
12201                                 PARSEREDIR(); /* passed as params: out, c */
12202                                 lasttoken = TREDIR;
12203                                 return lasttoken;
12204                         }
12205                         /* else: non-number X seen, interpret it
12206                          * as "NNNX>file" = "NNNX >file" */
12207                 }
12208                 pungetc();
12209         }
12210         quoteflag = quotef;
12211         backquotelist = bqlist;
12212         grabstackblock(len);
12213         wordtext = out;
12214         lasttoken = TWORD;
12215         return lasttoken;
12216 /* end of readtoken routine */
12217
12218 /*
12219  * Check to see whether we are at the end of the here document.  When this
12220  * is called, c is set to the first character of the next input line.  If
12221  * we are at the end of the here document, this routine sets the c to PEOF.
12222  */
12223 checkend: {
12224         if (realeofmark(eofmark)) {
12225                 int markloc;
12226                 char *p;
12227
12228 #if ENABLE_ASH_ALIAS
12229                 if (c == PEOA)
12230                         c = pgetc_without_PEOA();
12231 #endif
12232                 if (striptabs) {
12233                         while (c == '\t') {
12234                                 c = pgetc_without_PEOA();
12235                         }
12236                 }
12237
12238                 markloc = out - (char *)stackblock();
12239                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12240                         if (c != *p)
12241                                 goto more_heredoc;
12242
12243                         c = pgetc_without_PEOA();
12244                 }
12245
12246                 if (c == '\n' || c == PEOF) {
12247                         c = PEOF;
12248                         g_parsefile->linno++;
12249                         needprompt = doprompt;
12250                 } else {
12251                         int len_here;
12252
12253  more_heredoc:
12254                         p = (char *)stackblock() + markloc + 1;
12255                         len_here = out - p;
12256
12257                         if (len_here) {
12258                                 len_here -= (c >= PEOF);
12259                                 c = p[-1];
12260
12261                                 if (len_here) {
12262                                         char *str;
12263
12264                                         str = alloca(len_here + 1);
12265                                         *(char *)mempcpy(str, p, len_here) = '\0';
12266
12267                                         pushstring(str, NULL);
12268                                 }
12269                         }
12270                 }
12271
12272                 STADJUST((char *)stackblock() + markloc - out, out);
12273         }
12274         goto checkend_return;
12275 }
12276
12277 /*
12278  * Parse a redirection operator.  The variable "out" points to a string
12279  * specifying the fd to be redirected.  The variable "c" contains the
12280  * first character of the redirection operator.
12281  */
12282 parseredir: {
12283         /* out is already checked to be a valid number or "" */
12284         int fd = (*out == '\0' ? -1 : atoi(out));
12285         union node *np;
12286
12287         np = stzalloc(sizeof(struct nfile));
12288         if (c == '>') {
12289                 np->nfile.fd = 1;
12290                 c = pgetc_eatbnl();
12291                 if (c == '>')
12292                         np->type = NAPPEND;
12293                 else if (c == '|')
12294                         np->type = NCLOBBER;
12295                 else if (c == '&')
12296                         np->type = NTOFD;
12297                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12298                 else {
12299                         np->type = NTO;
12300                         pungetc();
12301                 }
12302         }
12303 #if BASH_REDIR_OUTPUT
12304         else if (c == 0x100 + '>') { /* this flags &> redirection */
12305                 np->nfile.fd = 1;
12306                 pgetc(); /* this is '>', no need to check */
12307                 np->type = NTO2;
12308         }
12309 #endif
12310         else { /* c == '<' */
12311                 /*np->nfile.fd = 0; - stzalloc did it */
12312                 c = pgetc_eatbnl();
12313                 switch (c) {
12314                 case '<':
12315                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12316                                 np = stzalloc(sizeof(struct nhere));
12317                                 /*np->nfile.fd = 0; - stzalloc did it */
12318                         }
12319                         np->type = NHERE;
12320                         heredoc = stzalloc(sizeof(struct heredoc));
12321                         heredoc->here = np;
12322                         c = pgetc_eatbnl();
12323                         if (c == '-') {
12324                                 heredoc->striptabs = 1;
12325                         } else {
12326                                 /*heredoc->striptabs = 0; - stzalloc did it */
12327                                 pungetc();
12328                         }
12329                         break;
12330
12331                 case '&':
12332                         np->type = NFROMFD;
12333                         break;
12334
12335                 case '>':
12336                         np->type = NFROMTO;
12337                         break;
12338
12339                 default:
12340                         np->type = NFROM;
12341                         pungetc();
12342                         break;
12343                 }
12344         }
12345         if (fd >= 0)
12346                 np->nfile.fd = fd;
12347         redirnode = np;
12348         goto parseredir_return;
12349 }
12350
12351 /*
12352  * Parse a substitution.  At this point, we have read the dollar sign
12353  * and nothing else.
12354  */
12355
12356 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12357  * (assuming ascii char codes, as the original implementation did) */
12358 #define is_special(c) \
12359         (((unsigned)(c) - 33 < 32) \
12360                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12361 parsesub: {
12362         unsigned char subtype;
12363         int typeloc;
12364
12365         c = pgetc_eatbnl();
12366         if ((checkkwd & CHKEOFMARK)
12367          || c > 255 /* PEOA or PEOF */
12368          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12369         ) {
12370 #if BASH_DOLLAR_SQUOTE
12371                 if (synstack->syntax != DQSYNTAX && c == '\'')
12372                         bash_dollar_squote = 1;
12373                 else
12374 #endif
12375                         USTPUTC('$', out);
12376                 pungetc();
12377         } else if (c == '(') {
12378                 /* $(command) or $((arith)) */
12379                 if (pgetc_eatbnl() == '(') {
12380 #if ENABLE_FEATURE_SH_MATH
12381                         PARSEARITH();
12382 #else
12383                         raise_error_syntax("support for $((arith)) is disabled");
12384 #endif
12385                 } else {
12386                         pungetc();
12387                         PARSEBACKQNEW();
12388                 }
12389         } else {
12390                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12391                 smalluint newsyn = synstack->syntax;
12392
12393                 USTPUTC(CTLVAR, out);
12394                 typeloc = out - (char *)stackblock();
12395                 STADJUST(1, out);
12396                 subtype = VSNORMAL;
12397                 if (c == '{') {
12398                         c = pgetc_eatbnl();
12399                         subtype = 0;
12400                 }
12401  varname:
12402                 if (is_name(c)) {
12403                         /* $[{[#]]NAME[}] */
12404                         do {
12405                                 STPUTC(c, out);
12406                                 c = pgetc_eatbnl();
12407                         } while (is_in_name(c));
12408                 } else if (isdigit(c)) {
12409                         /* $[{[#]]NUM[}] */
12410                         do {
12411                                 STPUTC(c, out);
12412                                 c = pgetc_eatbnl();
12413                         } while (isdigit(c));
12414                 } else {
12415                         /* $[{[#]]<specialchar>[}] */
12416                         int cc = c;
12417
12418                         c = pgetc_eatbnl();
12419                         if (!subtype && cc == '#') {
12420                                 subtype = VSLENGTH;
12421                                 if (c == '_' || isalnum(c))
12422                                         goto varname;
12423                                 cc = c;
12424                                 c = pgetc_eatbnl();
12425                                 if (cc == '}' || c != '}') {
12426                                         pungetc();
12427                                         subtype = 0;
12428                                         c = cc;
12429                                         cc = '#';
12430                                 }
12431                         }
12432
12433                         if (!is_special(cc)) {
12434                                 if (subtype == VSLENGTH)
12435                                         subtype = 0;
12436                                 goto badsub;
12437                         }
12438
12439                         USTPUTC(cc, out);
12440                 }
12441
12442                 if (c != '}' && subtype == VSLENGTH) {
12443                         /* ${#VAR didn't end with } */
12444                         goto badsub;
12445                 }
12446
12447                 if (subtype == 0) {
12448                         static const char types[] ALIGN1 = "}-+?=";
12449                         /* ${VAR...} but not $VAR or ${#VAR} */
12450                         /* c == first char after VAR */
12451                         int cc = c;
12452
12453                         switch (c) {
12454                         case ':':
12455                                 c = pgetc_eatbnl();
12456 #if BASH_SUBSTR
12457                                 /* This check is only needed to not misinterpret
12458                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12459                                  * constructs.
12460                                  */
12461                                 if (!strchr(types, c)) {
12462                                         subtype = VSSUBSTR;
12463                                         pungetc();
12464                                         break; /* "goto badsub" is bigger (!) */
12465                                 }
12466 #endif
12467                                 subtype = VSNUL;
12468                                 /*FALLTHROUGH*/
12469                         default: {
12470                                 const char *p = strchr(types, c);
12471                                 if (p == NULL)
12472                                         break;
12473                                 subtype |= p - types + VSNORMAL;
12474                                 break;
12475                         }
12476                         case '%':
12477                         case '#':
12478                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12479                                 c = pgetc_eatbnl();
12480                                 if (c == cc)
12481                                         subtype++;
12482                                 else
12483                                         pungetc();
12484
12485                                 newsyn = BASESYNTAX;
12486                                 break;
12487 #if BASH_PATTERN_SUBST
12488                         case '/':
12489                                 /* ${v/[/]pattern/repl} */
12490 //TODO: encode pattern and repl separately.
12491 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12492 // are broken (should print "ONE")
12493                                 subtype = VSREPLACE;
12494                                 newsyn = BASESYNTAX;
12495                                 c = pgetc_eatbnl();
12496                                 if (c != '/')
12497                                         goto badsub;
12498                                 subtype++; /* VSREPLACEALL */
12499                                 break;
12500 #endif
12501                         }
12502                 } else {
12503  badsub:
12504                         pungetc();
12505                 }
12506
12507                 if (newsyn == ARISYNTAX)
12508                         newsyn = DQSYNTAX;
12509
12510                 if ((newsyn != synstack->syntax || synstack->innerdq)
12511                  && subtype != VSNORMAL
12512                 ) {
12513                         synstack_push(&synstack,
12514                                 synstack->prev ?: alloca(sizeof(*synstack)),
12515                                 newsyn);
12516
12517                         synstack->varpushed = 1;
12518                         synstack->dblquote = newsyn != BASESYNTAX;
12519                 }
12520
12521                 ((unsigned char *)stackblock())[typeloc] = subtype;
12522                 if (subtype != VSNORMAL) {
12523                         synstack->varnest++;
12524                         if (synstack->dblquote)
12525                                 synstack->dqvarnest++;
12526                 }
12527                 STPUTC('=', out);
12528         }
12529         goto parsesub_return;
12530 }
12531
12532 /*
12533  * Called to parse command substitutions.  Newstyle is set if the command
12534  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12535  * list of commands (passed by reference), and savelen is the number of
12536  * characters on the top of the stack which must be preserved.
12537  */
12538 parsebackq: {
12539         struct nodelist **nlpp;
12540         union node *n;
12541         char *str;
12542         size_t savelen;
12543         smallint saveprompt = 0;
12544
12545         str = NULL;
12546         savelen = out - (char *)stackblock();
12547         if (savelen > 0) {
12548                 /*
12549                  * FIXME: this can allocate very large block on stack and SEGV.
12550                  * Example:
12551                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12552                  * allocates 100kb for every command subst. With about
12553                  * a hundred command substitutions stack overflows.
12554                  * With larger prepended string, SEGV happens sooner.
12555                  */
12556                 str = alloca(savelen);
12557                 memcpy(str, stackblock(), savelen);
12558         }
12559
12560         if (oldstyle) {
12561                 /* We must read until the closing backquote, giving special
12562                  * treatment to some slashes, and then push the string and
12563                  * reread it as input, interpreting it normally.
12564                  */
12565                 char *pout;
12566                 size_t psavelen;
12567                 char *pstr;
12568
12569                 STARTSTACKSTR(pout);
12570                 for (;;) {
12571                         int pc;
12572
12573                         setprompt_if(needprompt, 2);
12574                         pc = pgetc_eatbnl();
12575                         switch (pc) {
12576                         case '`':
12577                                 goto done;
12578
12579                         case '\\':
12580                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12581                                 if (pc != '\\' && pc != '`' && pc != '$'
12582                                  && (!synstack->dblquote || pc != '"')
12583                                 ) {
12584                                         STPUTC('\\', pout);
12585                                 }
12586                                 if (pc <= 255 /* not PEOA or PEOF */) {
12587                                         break;
12588                                 }
12589                                 /* fall through */
12590
12591                         case PEOF:
12592                         IF_ASH_ALIAS(case PEOA:)
12593                                 raise_error_syntax("EOF in backquote substitution");
12594
12595                         case '\n':
12596                                 nlnoprompt();
12597                                 break;
12598
12599                         default:
12600                                 break;
12601                         }
12602                         STPUTC(pc, pout);
12603                 }
12604  done:
12605                 STPUTC('\0', pout);
12606                 psavelen = pout - (char *)stackblock();
12607                 if (psavelen > 0) {
12608                         pstr = grabstackstr(pout);
12609                         setinputstring(pstr);
12610                 }
12611         }
12612         nlpp = &bqlist;
12613         while (*nlpp)
12614                 nlpp = &(*nlpp)->next;
12615         *nlpp = stzalloc(sizeof(**nlpp));
12616         /* (*nlpp)->next = NULL; - stzalloc did it */
12617
12618         if (oldstyle) {
12619                 saveprompt = doprompt;
12620                 doprompt = 0;
12621         }
12622
12623         n = list(2);
12624
12625         if (oldstyle)
12626                 doprompt = saveprompt;
12627         else if (readtoken() != TRP)
12628                 raise_error_unexpected_syntax(TRP);
12629
12630         (*nlpp)->n = n;
12631         if (oldstyle) {
12632                 /*
12633                  * Start reading from old file again, ignoring any pushed back
12634                  * tokens left from the backquote parsing
12635                  */
12636                 popfile();
12637                 tokpushback = 0;
12638         }
12639         while (stackblocksize() <= savelen)
12640                 growstackblock();
12641         STARTSTACKSTR(out);
12642         if (str) {
12643                 memcpy(out, str, savelen);
12644                 STADJUST(savelen, out);
12645         }
12646         USTPUTC(CTLBACKQ, out);
12647         if (oldstyle)
12648                 goto parsebackq_oldreturn;
12649         goto parsebackq_newreturn;
12650 }
12651
12652 #if ENABLE_FEATURE_SH_MATH
12653 /*
12654  * Parse an arithmetic expansion (indicate start of one and set state)
12655  */
12656 parsearith: {
12657
12658         synstack_push(&synstack,
12659                         synstack->prev ?: alloca(sizeof(*synstack)),
12660                         ARISYNTAX);
12661         synstack->dblquote = 1;
12662         USTPUTC(CTLARI, out);
12663         goto parsearith_return;
12664 }
12665 #endif
12666 } /* end of readtoken */
12667
12668 /*
12669  * Read the next input token.
12670  * If the token is a word, we set backquotelist to the list of cmds in
12671  *      backquotes.  We set quoteflag to true if any part of the word was
12672  *      quoted.
12673  * If the token is TREDIR, then we set redirnode to a structure containing
12674  *      the redirection.
12675  *
12676  * [Change comment:  here documents and internal procedures]
12677  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12678  *  word parsing code into a separate routine.  In this case, readtoken
12679  *  doesn't need to have any internal procedures, but parseword does.
12680  *  We could also make parseoperator in essence the main routine, and
12681  *  have parseword (readtoken1?) handle both words and redirection.]
12682  */
12683 #define NEW_xxreadtoken
12684 #ifdef NEW_xxreadtoken
12685 /* singles must be first! */
12686 static const char xxreadtoken_chars[7] ALIGN1 = {
12687         '\n', '(', ')', /* singles */
12688         '&', '|', ';',  /* doubles */
12689         0
12690 };
12691
12692 #define xxreadtoken_singles 3
12693 #define xxreadtoken_doubles 3
12694
12695 static const char xxreadtoken_tokens[] ALIGN1 = {
12696         TNL, TLP, TRP,          /* only single occurrence allowed */
12697         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12698         TEOF,                   /* corresponds to trailing nul */
12699         TAND, TOR, TENDCASE     /* if double occurrence */
12700 };
12701
12702 static int
12703 xxreadtoken(void)
12704 {
12705         int c;
12706
12707         if (tokpushback) {
12708                 tokpushback = 0;
12709                 return lasttoken;
12710         }
12711         setprompt_if(needprompt, 2);
12712         for (;;) {                      /* until token or start of word found */
12713                 c = pgetc_eatbnl();
12714                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12715                         continue;
12716
12717                 if (c == '#') {
12718                         while ((c = pgetc()) != '\n' && c != PEOF)
12719                                 continue;
12720                         pungetc();
12721                 } else if (c == '\\') {
12722                         break; /* return readtoken1(...) */
12723                 } else {
12724                         const char *p;
12725
12726                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12727                         if (c != PEOF) {
12728                                 if (c == '\n') {
12729                                         nlnoprompt();
12730                                 }
12731
12732                                 p = strchr(xxreadtoken_chars, c);
12733                                 if (p == NULL)
12734                                         break; /* return readtoken1(...) */
12735
12736                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12737                                         int cc = pgetc_eatbnl();
12738                                         if (cc == c) {    /* double occurrence? */
12739                                                 p += xxreadtoken_doubles + 1;
12740                                         } else {
12741                                                 pungetc();
12742 #if BASH_REDIR_OUTPUT
12743                                                 if (c == '&' && cc == '>') /* &> */
12744                                                         break; /* return readtoken1(...) */
12745 #endif
12746                                         }
12747                                 }
12748                         }
12749                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12750                         return lasttoken;
12751                 }
12752         } /* for (;;) */
12753
12754         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12755 }
12756 #else /* old xxreadtoken */
12757 #define RETURN(token)   return lasttoken = token
12758 static int
12759 xxreadtoken(void)
12760 {
12761         int c;
12762
12763         if (tokpushback) {
12764                 tokpushback = 0;
12765                 return lasttoken;
12766         }
12767         setprompt_if(needprompt, 2);
12768         for (;;) {      /* until token or start of word found */
12769                 c = pgetc_eatbnl();
12770                 switch (c) {
12771                 case ' ': case '\t':
12772                 IF_ASH_ALIAS(case PEOA:)
12773                         continue;
12774                 case '#':
12775                         while ((c = pgetc()) != '\n' && c != PEOF)
12776                                 continue;
12777                         pungetc();
12778                         continue;
12779                 case '\n':
12780                         nlnoprompt();
12781                         RETURN(TNL);
12782                 case PEOF:
12783                         RETURN(TEOF);
12784                 case '&':
12785                         if (pgetc_eatbnl() == '&')
12786                                 RETURN(TAND);
12787                         pungetc();
12788                         RETURN(TBACKGND);
12789                 case '|':
12790                         if (pgetc_eatbnl() == '|')
12791                                 RETURN(TOR);
12792                         pungetc();
12793                         RETURN(TPIPE);
12794                 case ';':
12795                         if (pgetc_eatbnl() == ';')
12796                                 RETURN(TENDCASE);
12797                         pungetc();
12798                         RETURN(TSEMI);
12799                 case '(':
12800                         RETURN(TLP);
12801                 case ')':
12802                         RETURN(TRP);
12803                 }
12804                 break;
12805         }
12806         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12807 #undef RETURN
12808 }
12809 #endif /* old xxreadtoken */
12810
12811 static int
12812 readtoken(void)
12813 {
12814         int t;
12815         int kwd = checkkwd;
12816 #if DEBUG
12817         smallint alreadyseen = tokpushback;
12818 #endif
12819
12820 #if ENABLE_ASH_ALIAS
12821  top:
12822 #endif
12823
12824         t = xxreadtoken();
12825
12826         /*
12827          * eat newlines
12828          */
12829         if (kwd & CHKNL) {
12830                 while (t == TNL) {
12831                         parseheredoc();
12832                         t = xxreadtoken();
12833                 }
12834         }
12835
12836         if (t != TWORD || quoteflag) {
12837                 goto out;
12838         }
12839
12840         /*
12841          * check for keywords
12842          */
12843         if (kwd & CHKKWD) {
12844                 const char *const *pp;
12845
12846                 pp = findkwd(wordtext);
12847                 if (pp) {
12848                         lasttoken = t = pp - tokname_array;
12849                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12850                         goto out;
12851                 }
12852         }
12853
12854         if (checkkwd & CHKALIAS) {
12855 #if ENABLE_ASH_ALIAS
12856                 struct alias *ap;
12857                 ap = lookupalias(wordtext, 1);
12858                 if (ap != NULL) {
12859                         if (*ap->val) {
12860                                 pushstring(ap->val, ap);
12861                         }
12862                         goto top;
12863                 }
12864 #endif
12865         }
12866  out:
12867         checkkwd = 0;
12868 #if DEBUG
12869         if (!alreadyseen)
12870                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12871         else
12872                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12873 #endif
12874         return t;
12875 }
12876
12877 static int
12878 peektoken(void)
12879 {
12880         int t;
12881
12882         t = readtoken();
12883         tokpushback = 1;
12884         return t;
12885 }
12886
12887 /*
12888  * Read and parse a command.  Returns NODE_EOF on end of file.
12889  * (NULL is a valid parse tree indicating a blank line.)
12890  */
12891 static union node *
12892 parsecmd(int interact)
12893 {
12894         tokpushback = 0;
12895         checkkwd = 0;
12896         heredoclist = 0;
12897         doprompt = interact;
12898         setprompt_if(doprompt, doprompt);
12899         needprompt = 0;
12900         return list(1);
12901 }
12902
12903 /*
12904  * Input any here documents.
12905  */
12906 static void
12907 parseheredoc(void)
12908 {
12909         struct heredoc *here;
12910         union node *n;
12911
12912         here = heredoclist;
12913         heredoclist = NULL;
12914
12915         while (here) {
12916                 setprompt_if(needprompt, 2);
12917                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12918                                 here->eofmark, here->striptabs);
12919                 n = stzalloc(sizeof(struct narg));
12920                 n->narg.type = NARG;
12921                 /*n->narg.next = NULL; - stzalloc did it */
12922                 n->narg.text = wordtext;
12923                 n->narg.backquote = backquotelist;
12924                 here->here->nhere.doc = n;
12925                 here = here->next;
12926         }
12927 }
12928
12929
12930 static const char *
12931 expandstr(const char *ps, int syntax_type)
12932 {
12933         union node n;
12934         int saveprompt;
12935
12936         /* XXX Fix (char *) cast. */
12937         setinputstring((char *)ps);
12938
12939         saveprompt = doprompt;
12940         doprompt = 0;
12941
12942         /* readtoken1() might die horribly.
12943          * Try a prompt with syntactically wrong command:
12944          * PS1='$(date "+%H:%M:%S) > '
12945          */
12946         {
12947                 volatile int saveint;
12948                 struct jmploc *volatile savehandler = exception_handler;
12949                 struct jmploc jmploc;
12950                 SAVE_INT(saveint);
12951                 if (setjmp(jmploc.loc) == 0) {
12952                         exception_handler = &jmploc;
12953                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12954                 }
12955                 exception_handler = savehandler;
12956                 RESTORE_INT(saveint);
12957         }
12958
12959         doprompt = saveprompt;
12960
12961         popfile();
12962
12963         n.narg.type = NARG;
12964         n.narg.next = NULL;
12965         n.narg.text = wordtext;
12966         n.narg.backquote = backquotelist;
12967
12968         expandarg(&n, NULL, EXP_QUOTED);
12969         return stackblock();
12970 }
12971
12972 static inline int
12973 parser_eof(void)
12974 {
12975         return tokpushback && lasttoken == TEOF;
12976 }
12977
12978 /*
12979  * Execute a command or commands contained in a string.
12980  */
12981 static int
12982 evalstring(char *s, int flags)
12983 {
12984         struct jmploc *volatile savehandler;
12985         struct jmploc jmploc;
12986         int ex;
12987
12988         union node *n;
12989         struct stackmark smark;
12990         int status;
12991
12992         s = sstrdup(s);
12993         setinputstring(s);
12994         setstackmark(&smark);
12995
12996         status = 0;
12997         /* On exception inside execution loop, we must popfile().
12998          * Try interactively:
12999          *      readonly a=a
13000          *      command eval "a=b"  # throws "is read only" error
13001          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13002          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13003          */
13004         savehandler = exception_handler;
13005         ex = setjmp(jmploc.loc);
13006         if (ex)
13007                 goto out;
13008         exception_handler = &jmploc;
13009
13010         while ((n = parsecmd(0)) != NODE_EOF) {
13011                 int i;
13012
13013                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13014                 if (n)
13015                         status = i;
13016                 popstackmark(&smark);
13017                 if (evalskip)
13018                         break;
13019         }
13020  out:
13021         popstackmark(&smark);
13022         popfile();
13023         stunalloc(s);
13024
13025         exception_handler = savehandler;
13026         if (ex)
13027                 longjmp(exception_handler->loc, ex);
13028
13029         return status;
13030 }
13031
13032 /*
13033  * The eval command.
13034  */
13035 static int FAST_FUNC
13036 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13037 {
13038         char *p;
13039         char *concat;
13040
13041         if (argv[1]) {
13042                 p = argv[1];
13043                 argv += 2;
13044                 if (argv[0]) {
13045                         STARTSTACKSTR(concat);
13046                         for (;;) {
13047                                 concat = stack_putstr(p, concat);
13048                                 p = *argv++;
13049                                 if (p == NULL)
13050                                         break;
13051                                 STPUTC(' ', concat);
13052                         }
13053                         STPUTC('\0', concat);
13054                         p = grabstackstr(concat);
13055                 }
13056                 return evalstring(p, flags & EV_TESTED);
13057         }
13058         return 0;
13059 }
13060
13061 /*
13062  * Read and execute commands.
13063  * "Top" is nonzero for the top level command loop;
13064  * it turns on prompting if the shell is interactive.
13065  */
13066 static int
13067 cmdloop(int top)
13068 {
13069         union node *n;
13070         struct stackmark smark;
13071         int inter;
13072         int status = 0;
13073         int numeof = 0;
13074
13075         TRACE(("cmdloop(%d) called\n", top));
13076         for (;;) {
13077                 int skip;
13078
13079                 setstackmark(&smark);
13080 #if JOBS
13081                 if (doing_jobctl)
13082                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13083 #endif
13084                 inter = 0;
13085                 if (iflag && top) {
13086                         inter++;
13087                         chkmail();
13088                 }
13089                 n = parsecmd(inter);
13090 #if DEBUG
13091                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13092                         showtree(n);
13093 #endif
13094                 if (n == NODE_EOF) {
13095                         if (!top || numeof >= 50)
13096                                 break;
13097                         if (!stoppedjobs()) {
13098                                 if (!Iflag)
13099                                         break;
13100                                 out2str("\nUse \"exit\" to leave shell.\n");
13101                         }
13102                         numeof++;
13103                 } else if (nflag == 0) {
13104                         int i;
13105
13106                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13107                         job_warning >>= 1;
13108                         numeof = 0;
13109                         i = evaltree(n, 0);
13110                         if (n)
13111                                 status = i;
13112                 }
13113                 popstackmark(&smark);
13114                 skip = evalskip;
13115
13116                 if (skip) {
13117                         evalskip &= ~SKIPFUNC;
13118                         break;
13119                 }
13120         }
13121         return status;
13122 }
13123
13124 /*
13125  * Take commands from a file.  To be compatible we should do a path
13126  * search for the file, which is necessary to find sub-commands.
13127  */
13128 static char *
13129 find_dot_file(char *name)
13130 {
13131         char *fullname;
13132         const char *path = pathval();
13133         struct stat statb;
13134
13135         /* don't try this for absolute or relative paths */
13136         if (strchr(name, '/'))
13137                 return name;
13138
13139         while ((fullname = path_advance(&path, name)) != NULL) {
13140                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13141                         /*
13142                          * Don't bother freeing here, since it will
13143                          * be freed by the caller.
13144                          */
13145                         return fullname;
13146                 }
13147                 if (fullname != name)
13148                         stunalloc(fullname);
13149         }
13150         /* not found in PATH */
13151
13152 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13153         return name;
13154 #else
13155         ash_msg_and_raise_error("%s: not found", name);
13156         /* NOTREACHED */
13157 #endif
13158 }
13159
13160 static int FAST_FUNC
13161 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13162 {
13163         /* "false; . empty_file; echo $?" should print 0, not 1: */
13164         int status = 0;
13165         char *fullname;
13166         char **argv;
13167         char *args_need_save;
13168         volatile struct shparam saveparam;
13169
13170 //???
13171 //      struct strlist *sp;
13172 //      for (sp = cmdenviron; sp; sp = sp->next)
13173 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13174
13175         nextopt(nullstr); /* handle possible "--" */
13176         argv = argptr;
13177
13178         if (!argv[0]) {
13179                 /* bash says: "bash: .: filename argument required" */
13180                 return 2; /* bash compat */
13181         }
13182
13183         /* This aborts if file isn't found, which is POSIXly correct.
13184          * bash returns exitcode 1 instead.
13185          */
13186         fullname = find_dot_file(argv[0]);
13187         argv++;
13188         args_need_save = argv[0];
13189         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13190                 int argc;
13191                 saveparam = shellparam;
13192                 shellparam.malloced = 0;
13193                 argc = 1;
13194                 while (argv[argc])
13195                         argc++;
13196                 shellparam.nparam = argc;
13197                 shellparam.p = argv;
13198         };
13199
13200         /* This aborts if file can't be opened, which is POSIXly correct.
13201          * bash returns exitcode 1 instead.
13202          */
13203         setinputfile(fullname, INPUT_PUSH_FILE);
13204         commandname = fullname;
13205         status = cmdloop(0);
13206         popfile();
13207
13208         if (args_need_save) {
13209                 freeparam(&shellparam);
13210                 shellparam = saveparam;
13211         };
13212
13213         return status;
13214 }
13215
13216 static int FAST_FUNC
13217 exitcmd(int argc UNUSED_PARAM, char **argv)
13218 {
13219         if (stoppedjobs())
13220                 return 0;
13221         if (argv[1])
13222                 exitstatus = number(argv[1]);
13223         raise_exception(EXEXIT);
13224         /* NOTREACHED */
13225 }
13226
13227 /*
13228  * Read a file containing shell functions.
13229  */
13230 static void
13231 readcmdfile(char *name)
13232 {
13233         setinputfile(name, INPUT_PUSH_FILE);
13234         cmdloop(0);
13235         popfile();
13236 }
13237
13238
13239 /* ============ find_command inplementation */
13240
13241 /*
13242  * Resolve a command name.  If you change this routine, you may have to
13243  * change the shellexec routine as well.
13244  */
13245 static void
13246 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13247 {
13248         struct tblentry *cmdp;
13249         int idx;
13250         int prev;
13251         char *fullname;
13252         struct stat statb;
13253         int e;
13254         int updatetbl;
13255         struct builtincmd *bcmd;
13256
13257         /* If name contains a slash, don't use PATH or hash table */
13258         if (strchr(name, '/') != NULL) {
13259                 entry->u.index = -1;
13260                 if (act & DO_ABS) {
13261                         while (stat(name, &statb) < 0) {
13262 #ifdef SYSV
13263                                 if (errno == EINTR)
13264                                         continue;
13265 #endif
13266                                 entry->cmdtype = CMDUNKNOWN;
13267                                 return;
13268                         }
13269                 }
13270                 entry->cmdtype = CMDNORMAL;
13271                 return;
13272         }
13273
13274 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13275
13276         updatetbl = (path == pathval());
13277         if (!updatetbl) {
13278                 act |= DO_ALTPATH;
13279                 if (strstr(path, "%builtin") != NULL)
13280                         act |= DO_ALTBLTIN;
13281         }
13282
13283         /* If name is in the table, check answer will be ok */
13284         cmdp = cmdlookup(name, 0);
13285         if (cmdp != NULL) {
13286                 int bit;
13287
13288                 switch (cmdp->cmdtype) {
13289                 default:
13290 #if DEBUG
13291                         abort();
13292 #endif
13293                 case CMDNORMAL:
13294                         bit = DO_ALTPATH;
13295                         break;
13296                 case CMDFUNCTION:
13297                         bit = DO_NOFUNC;
13298                         break;
13299                 case CMDBUILTIN:
13300                         bit = DO_ALTBLTIN;
13301                         break;
13302                 }
13303                 if (act & bit) {
13304                         updatetbl = 0;
13305                         cmdp = NULL;
13306                 } else if (cmdp->rehash == 0)
13307                         /* if not invalidated by cd, we're done */
13308                         goto success;
13309         }
13310
13311         /* If %builtin not in path, check for builtin next */
13312         bcmd = find_builtin(name);
13313         if (bcmd) {
13314                 if (IS_BUILTIN_REGULAR(bcmd))
13315                         goto builtin_success;
13316                 if (act & DO_ALTPATH) {
13317                         if (!(act & DO_ALTBLTIN))
13318                                 goto builtin_success;
13319                 } else if (builtinloc <= 0) {
13320                         goto builtin_success;
13321                 }
13322         }
13323
13324 #if ENABLE_FEATURE_SH_STANDALONE
13325         {
13326                 int applet_no = find_applet_by_name(name);
13327                 if (applet_no >= 0) {
13328                         entry->cmdtype = CMDNORMAL;
13329                         entry->u.index = -2 - applet_no;
13330                         return;
13331                 }
13332         }
13333 #endif
13334
13335         /* We have to search path. */
13336         prev = -1;              /* where to start */
13337         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13338                 if (cmdp->cmdtype == CMDBUILTIN)
13339                         prev = builtinloc;
13340                 else
13341                         prev = cmdp->param.index;
13342         }
13343
13344         e = ENOENT;
13345         idx = -1;
13346  loop:
13347         while ((fullname = path_advance(&path, name)) != NULL) {
13348                 stunalloc(fullname);
13349                 /* NB: code below will still use fullname
13350                  * despite it being "unallocated" */
13351                 idx++;
13352                 if (pathopt) {
13353                         if (prefix(pathopt, "builtin")) {
13354                                 if (bcmd)
13355                                         goto builtin_success;
13356                                 continue;
13357                         }
13358                         if ((act & DO_NOFUNC)
13359                          || !prefix(pathopt, "func")
13360                         ) {     /* ignore unimplemented options */
13361                                 continue;
13362                         }
13363                 }
13364                 /* if rehash, don't redo absolute path names */
13365                 if (fullname[0] == '/' && idx <= prev) {
13366                         if (idx < prev)
13367                                 continue;
13368                         TRACE(("searchexec \"%s\": no change\n", name));
13369                         goto success;
13370                 }
13371                 while (stat(fullname, &statb) < 0) {
13372 #ifdef SYSV
13373                         if (errno == EINTR)
13374                                 continue;
13375 #endif
13376                         if (errno != ENOENT && errno != ENOTDIR)
13377                                 e = errno;
13378                         goto loop;
13379                 }
13380                 e = EACCES;     /* if we fail, this will be the error */
13381                 if (!S_ISREG(statb.st_mode))
13382                         continue;
13383                 if (pathopt) {          /* this is a %func directory */
13384                         stalloc(strlen(fullname) + 1);
13385                         /* NB: stalloc will return space pointed by fullname
13386                          * (because we don't have any intervening allocations
13387                          * between stunalloc above and this stalloc) */
13388                         readcmdfile(fullname);
13389                         cmdp = cmdlookup(name, 0);
13390                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13391                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13392                         stunalloc(fullname);
13393                         goto success;
13394                 }
13395                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13396                 if (!updatetbl) {
13397                         entry->cmdtype = CMDNORMAL;
13398                         entry->u.index = idx;
13399                         return;
13400                 }
13401                 INT_OFF;
13402                 cmdp = cmdlookup(name, 1);
13403                 cmdp->cmdtype = CMDNORMAL;
13404                 cmdp->param.index = idx;
13405                 INT_ON;
13406                 goto success;
13407         }
13408
13409         /* We failed.  If there was an entry for this command, delete it */
13410         if (cmdp && updatetbl)
13411                 delete_cmd_entry();
13412         if (act & DO_ERR) {
13413 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13414                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13415                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13416                         char *argv[3];
13417                         argv[0] = (char*) "command_not_found_handle";
13418                         argv[1] = name;
13419                         argv[2] = NULL;
13420                         evalfun(hookp->param.func, 2, argv, 0);
13421                         entry->cmdtype = CMDUNKNOWN;
13422                         return;
13423                 }
13424 #endif
13425                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13426         }
13427         entry->cmdtype = CMDUNKNOWN;
13428         return;
13429
13430  builtin_success:
13431         if (!updatetbl) {
13432                 entry->cmdtype = CMDBUILTIN;
13433                 entry->u.cmd = bcmd;
13434                 return;
13435         }
13436         INT_OFF;
13437         cmdp = cmdlookup(name, 1);
13438         cmdp->cmdtype = CMDBUILTIN;
13439         cmdp->param.cmd = bcmd;
13440         INT_ON;
13441  success:
13442         cmdp->rehash = 0;
13443         entry->cmdtype = cmdp->cmdtype;
13444         entry->u = cmdp->param;
13445 }
13446
13447
13448 /*
13449  * The trap builtin.
13450  */
13451 static int FAST_FUNC
13452 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13453 {
13454         char *action;
13455         char **ap;
13456         int signo, exitcode;
13457
13458         nextopt(nullstr);
13459         ap = argptr;
13460         if (!*ap) {
13461                 for (signo = 0; signo < NSIG; signo++) {
13462                         char *tr = trap_ptr[signo];
13463                         if (tr) {
13464                                 /* note: bash adds "SIG", but only if invoked
13465                                  * as "bash". If called as "sh", or if set -o posix,
13466                                  * then it prints short signal names.
13467                                  * We are printing short names: */
13468                                 out1fmt("trap -- %s %s\n",
13469                                                 single_quote(tr),
13470                                                 get_signame(signo));
13471                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13472                  * In this case, we will exit very soon, no need to free(). */
13473                                 /* if (trap_ptr != trap && tp[0]) */
13474                                 /*      free(tr); */
13475                         }
13476                 }
13477                 /*
13478                 if (trap_ptr != trap) {
13479                         free(trap_ptr);
13480                         trap_ptr = trap;
13481                 }
13482                 */
13483                 return 0;
13484         }
13485
13486         /* Why the second check?
13487          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13488          * In this case, NUM is signal no, not an action.
13489          */
13490         action = NULL;
13491         if (ap[1] && !is_number(ap[0]))
13492                 action = *ap++;
13493
13494         exitcode = 0;
13495         while (*ap) {
13496                 signo = get_signum(*ap);
13497                 if (signo < 0) {
13498                         /* Mimic bash message exactly */
13499                         ash_msg("%s: invalid signal specification", *ap);
13500                         exitcode = 1;
13501                         goto next;
13502                 }
13503                 INT_OFF;
13504                 if (action) {
13505                         if (LONE_DASH(action))
13506                                 action = NULL;
13507                         else {
13508                                 if (action[0]) /* not NULL and not "" and not "-" */
13509                                         may_have_traps = 1;
13510                                 action = ckstrdup(action);
13511                         }
13512                 }
13513                 free(trap[signo]);
13514                 trap[signo] = action;
13515                 if (signo != 0)
13516                         setsignal(signo);
13517                 INT_ON;
13518  next:
13519                 ap++;
13520         }
13521         return exitcode;
13522 }
13523
13524
13525 /* ============ Builtins */
13526
13527 #if ENABLE_ASH_HELP
13528 static int FAST_FUNC
13529 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13530 {
13531         unsigned col;
13532         unsigned i;
13533
13534         out1fmt(
13535                 "Built-in commands:\n"
13536                 "------------------\n");
13537         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13538                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13539                                         builtintab[i].name + 1);
13540                 if (col > 60) {
13541                         out1fmt("\n");
13542                         col = 0;
13543                 }
13544         }
13545 # if ENABLE_FEATURE_SH_STANDALONE
13546         {
13547                 const char *a = applet_names;
13548                 while (*a) {
13549                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13550                         if (col > 60) {
13551                                 out1fmt("\n");
13552                                 col = 0;
13553                         }
13554                         while (*a++ != '\0')
13555                                 continue;
13556                 }
13557         }
13558 # endif
13559         newline_and_flush(stdout);
13560         return EXIT_SUCCESS;
13561 }
13562 #endif
13563
13564 #if MAX_HISTORY
13565 static int FAST_FUNC
13566 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13567 {
13568         show_history(line_input_state);
13569         return EXIT_SUCCESS;
13570 }
13571 #endif
13572
13573 /*
13574  * The export and readonly commands.
13575  */
13576 static int FAST_FUNC
13577 exportcmd(int argc UNUSED_PARAM, char **argv)
13578 {
13579         struct var *vp;
13580         char *name;
13581         const char *p;
13582         char **aptr;
13583         char opt;
13584         int flag;
13585         int flag_off;
13586
13587         /* "readonly" in bash accepts, but ignores -n.
13588          * We do the same: it saves a conditional in nextopt's param.
13589          */
13590         flag_off = 0;
13591         while ((opt = nextopt("np")) != '\0') {
13592                 if (opt == 'n')
13593                         flag_off = VEXPORT;
13594         }
13595         flag = VEXPORT;
13596         if (argv[0][0] == 'r') {
13597                 flag = VREADONLY;
13598                 flag_off = 0; /* readonly ignores -n */
13599         }
13600         flag_off = ~flag_off;
13601
13602         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13603         {
13604                 aptr = argptr;
13605                 name = *aptr;
13606                 if (name) {
13607                         do {
13608                                 p = strchr(name, '=');
13609                                 if (p != NULL) {
13610                                         p++;
13611                                 } else {
13612                                         vp = *findvar(hashvar(name), name);
13613                                         if (vp) {
13614                                                 vp->flags = ((vp->flags | flag) & flag_off);
13615                                                 continue;
13616                                         }
13617                                 }
13618                                 setvar(name, p, (flag & flag_off));
13619                         } while ((name = *++aptr) != NULL);
13620                         return 0;
13621                 }
13622         }
13623
13624         /* No arguments. Show the list of exported or readonly vars.
13625          * -n is ignored.
13626          */
13627         showvars(argv[0], flag, 0);
13628         return 0;
13629 }
13630
13631 /*
13632  * Delete a function if it exists.
13633  */
13634 static void
13635 unsetfunc(const char *name)
13636 {
13637         struct tblentry *cmdp;
13638
13639         cmdp = cmdlookup(name, 0);
13640         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13641                 delete_cmd_entry();
13642 }
13643
13644 /*
13645  * The unset builtin command.  We unset the function before we unset the
13646  * variable to allow a function to be unset when there is a readonly variable
13647  * with the same name.
13648  */
13649 static int FAST_FUNC
13650 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13651 {
13652         char **ap;
13653         int i;
13654         int flag = 0;
13655
13656         while ((i = nextopt("vf")) != 0) {
13657                 flag = i;
13658         }
13659
13660         for (ap = argptr; *ap; ap++) {
13661                 if (flag != 'f') {
13662                         unsetvar(*ap);
13663                         continue;
13664                 }
13665                 if (flag != 'v')
13666                         unsetfunc(*ap);
13667         }
13668         return 0;
13669 }
13670
13671 static const unsigned char timescmd_str[] ALIGN1 = {
13672         ' ',  offsetof(struct tms, tms_utime),
13673         '\n', offsetof(struct tms, tms_stime),
13674         ' ',  offsetof(struct tms, tms_cutime),
13675         '\n', offsetof(struct tms, tms_cstime),
13676         0
13677 };
13678 static int FAST_FUNC
13679 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13680 {
13681         unsigned clk_tck;
13682         const unsigned char *p;
13683         struct tms buf;
13684
13685         clk_tck = bb_clk_tck();
13686
13687         times(&buf);
13688         p = timescmd_str;
13689         do {
13690                 unsigned sec, frac;
13691                 unsigned long t;
13692                 t = *(clock_t *)(((char *) &buf) + p[1]);
13693                 sec = t / clk_tck;
13694                 frac = t % clk_tck;
13695                 out1fmt("%um%u.%03us%c",
13696                         sec / 60, sec % 60,
13697                         (frac * 1000) / clk_tck,
13698                         p[0]);
13699                 p += 2;
13700         } while (*p);
13701
13702         return 0;
13703 }
13704
13705 #if ENABLE_FEATURE_SH_MATH
13706 /*
13707  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13708  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13709  *
13710  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13711  */
13712 static int FAST_FUNC
13713 letcmd(int argc UNUSED_PARAM, char **argv)
13714 {
13715         arith_t i;
13716
13717         argv++;
13718         if (!*argv)
13719                 ash_msg_and_raise_error("expression expected");
13720         do {
13721                 i = ash_arith(*argv);
13722         } while (*++argv);
13723
13724         return !i;
13725 }
13726 #endif
13727
13728 /*
13729  * The read builtin. Options:
13730  *      -r              Do not interpret '\' specially
13731  *      -s              Turn off echo (tty only)
13732  *      -n NCHARS       Read NCHARS max
13733  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13734  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13735  *      -u FD           Read from given FD instead of fd 0
13736  *      -d DELIM        End on DELIM char, not newline
13737  * This uses unbuffered input, which may be avoidable in some cases.
13738  * TODO: bash also has:
13739  *      -a ARRAY        Read into array[0],[1],etc
13740  *      -e              Use line editing (tty only)
13741  */
13742 static int FAST_FUNC
13743 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13744 {
13745         char *opt_n = NULL;
13746         char *opt_p = NULL;
13747         char *opt_t = NULL;
13748         char *opt_u = NULL;
13749         char *opt_d = NULL; /* optimized out if !BASH */
13750         int read_flags = 0;
13751         const char *r;
13752         int i;
13753
13754         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13755                 switch (i) {
13756                 case 'p':
13757                         opt_p = optionarg;
13758                         break;
13759                 case 'n':
13760                         opt_n = optionarg;
13761                         break;
13762                 case 's':
13763                         read_flags |= BUILTIN_READ_SILENT;
13764                         break;
13765                 case 't':
13766                         opt_t = optionarg;
13767                         break;
13768                 case 'r':
13769                         read_flags |= BUILTIN_READ_RAW;
13770                         break;
13771                 case 'u':
13772                         opt_u = optionarg;
13773                         break;
13774 #if BASH_READ_D
13775                 case 'd':
13776                         opt_d = optionarg;
13777                         break;
13778 #endif
13779                 default:
13780                         break;
13781                 }
13782         }
13783
13784         /* "read -s" needs to save/restore termios, can't allow ^C
13785          * to jump out of it.
13786          */
13787  again:
13788         INT_OFF;
13789         r = shell_builtin_read(setvar0,
13790                 argptr,
13791                 bltinlookup("IFS"), /* can be NULL */
13792                 read_flags,
13793                 opt_n,
13794                 opt_p,
13795                 opt_t,
13796                 opt_u,
13797                 opt_d
13798         );
13799         INT_ON;
13800
13801         if ((uintptr_t)r == 1 && errno == EINTR) {
13802                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13803                  * Correct behavior is to not exit "read"
13804                  */
13805                 if (pending_sig == 0)
13806                         goto again;
13807         }
13808
13809         if ((uintptr_t)r > 1)
13810                 ash_msg_and_raise_error(r);
13811
13812         return (uintptr_t)r;
13813 }
13814
13815 static int FAST_FUNC
13816 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13817 {
13818         static const char permuser[3] ALIGN1 = "ogu";
13819
13820         mode_t mask;
13821         int symbolic_mode = 0;
13822
13823         while (nextopt("S") != '\0') {
13824                 symbolic_mode = 1;
13825         }
13826
13827         INT_OFF;
13828         mask = umask(0);
13829         umask(mask);
13830         INT_ON;
13831
13832         if (*argptr == NULL) {
13833                 if (symbolic_mode) {
13834                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13835                         char *p = buf;
13836                         int i;
13837
13838                         i = 2;
13839                         for (;;) {
13840                                 *p++ = ',';
13841                                 *p++ = permuser[i];
13842                                 *p++ = '=';
13843                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13844                                 if (!(mask & 0400)) *p++ = 'r';
13845                                 if (!(mask & 0200)) *p++ = 'w';
13846                                 if (!(mask & 0100)) *p++ = 'x';
13847                                 mask <<= 3;
13848                                 if (--i < 0)
13849                                         break;
13850                         }
13851                         *p = '\0';
13852                         puts(buf + 1);
13853                 } else {
13854                         out1fmt("%04o\n", mask);
13855                 }
13856         } else {
13857                 char *modestr = *argptr;
13858                 /* numeric umasks are taken as-is */
13859                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13860                 if (!isdigit(modestr[0]))
13861                         mask ^= 0777;
13862                 mask = bb_parse_mode(modestr, mask);
13863                 if ((unsigned)mask > 0777) {
13864                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13865                 }
13866                 if (!isdigit(modestr[0]))
13867                         mask ^= 0777;
13868                 umask(mask);
13869         }
13870         return 0;
13871 }
13872
13873 static int FAST_FUNC
13874 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13875 {
13876         return shell_builtin_ulimit(argv);
13877 }
13878
13879 /* ============ main() and helpers */
13880
13881 /*
13882  * Called to exit the shell.
13883  */
13884 static void
13885 exitshell(void)
13886 {
13887         struct jmploc loc;
13888         char *p;
13889         int status;
13890
13891 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13892         save_history(line_input_state);
13893 #endif
13894         status = exitstatus;
13895         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13896         if (setjmp(loc.loc)) {
13897                 if (exception_type == EXEXIT)
13898                         status = exitstatus;
13899                 goto out;
13900         }
13901         exception_handler = &loc;
13902         p = trap[0];
13903         if (p) {
13904                 trap[0] = NULL;
13905                 evalskip = 0;
13906                 evalstring(p, 0);
13907                 /*free(p); - we'll exit soon */
13908         }
13909  out:
13910         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13911          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13912          */
13913         setjobctl(0);
13914         flush_stdout_stderr();
13915         _exit(status);
13916         /* NOTREACHED */
13917 }
13918
13919 /* Don't inline: conserve stack of caller from having our locals too */
13920 static NOINLINE void
13921 init(void)
13922 {
13923         /* we will never free this */
13924         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13925         basepf.linno = 1;
13926
13927         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13928         setsignal(SIGCHLD);
13929
13930         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13931          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13932          */
13933         signal(SIGHUP, SIG_DFL);
13934
13935         {
13936                 char **envp;
13937                 const char *p;
13938
13939                 initvar();
13940                 for (envp = environ; envp && *envp; envp++) {
13941 /* Used to have
13942  *                      p = endofname(*envp);
13943  *                      if (p != *envp && *p == '=') {
13944  * here to weed out badly-named variables, but this breaks
13945  * scenarios where people do want them passed to children:
13946  * import os
13947  * os.environ["test-test"]="test"
13948  * if os.fork() == 0:
13949  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13950  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13951  */
13952                         if (strchr(*envp, '=')) {
13953                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13954                         }
13955                 }
13956
13957                 setvareq((char*)defoptindvar, VTEXTFIXED);
13958
13959                 setvar0("PPID", utoa(getppid()));
13960 #if BASH_SHLVL_VAR
13961                 p = lookupvar("SHLVL");
13962                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13963 #endif
13964 #if BASH_HOSTNAME_VAR
13965                 if (!lookupvar("HOSTNAME")) {
13966                         struct utsname uts;
13967                         uname(&uts);
13968                         setvar0("HOSTNAME", uts.nodename);
13969                 }
13970 #endif
13971                 p = lookupvar("PWD");
13972                 if (p) {
13973                         struct stat st1, st2;
13974                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13975                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13976                         ) {
13977                                 p = NULL;
13978                         }
13979                 }
13980                 setpwd(p, 0);
13981         }
13982 }
13983
13984
13985 //usage:#define ash_trivial_usage
13986 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
13987 //usage:#define ash_full_usage "\n\n"
13988 //usage:        "Unix shell interpreter"
13989
13990 /*
13991  * Process the shell command line arguments.
13992  */
13993 static int
13994 procargs(char **argv)
13995 {
13996         int i;
13997         const char *xminusc;
13998         char **xargv;
13999         int login_sh;
14000
14001         xargv = argv;
14002         login_sh = xargv[0] && xargv[0][0] == '-';
14003         arg0 = xargv[0];
14004         /* if (xargv[0]) - mmm, this is always true! */
14005                 xargv++;
14006         for (i = 0; i < NOPTS; i++)
14007                 optlist[i] = 2;
14008         argptr = xargv;
14009         if (options(/*cmdline:*/ 1, &login_sh)) {
14010                 /* it already printed err message */
14011                 raise_exception(EXERROR);
14012         }
14013         xargv = argptr;
14014         xminusc = minusc;
14015         if (*xargv == NULL) {
14016                 if (xminusc)
14017                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14018                 sflag = 1;
14019         }
14020         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
14021                 iflag = 1;
14022         if (mflag == 2)
14023                 mflag = iflag;
14024         for (i = 0; i < NOPTS; i++)
14025                 if (optlist[i] == 2)
14026                         optlist[i] = 0;
14027 #if DEBUG == 2
14028         debug = 1;
14029 #endif
14030         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14031         if (xminusc) {
14032                 minusc = *xargv++;
14033                 if (*xargv)
14034                         goto setarg0;
14035         } else if (!sflag) {
14036                 setinputfile(*xargv, 0);
14037  setarg0:
14038                 arg0 = *xargv++;
14039                 commandname = arg0;
14040         }
14041
14042         shellparam.p = xargv;
14043 #if ENABLE_ASH_GETOPTS
14044         shellparam.optind = 1;
14045         shellparam.optoff = -1;
14046 #endif
14047         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14048         while (*xargv) {
14049                 shellparam.nparam++;
14050                 xargv++;
14051         }
14052         optschanged();
14053
14054         return login_sh;
14055 }
14056
14057 /*
14058  * Read /etc/profile, ~/.profile, $ENV.
14059  */
14060 static void
14061 read_profile(const char *name)
14062 {
14063         name = expandstr(name, DQSYNTAX);
14064         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14065                 return;
14066         cmdloop(0);
14067         popfile();
14068 }
14069
14070 /*
14071  * This routine is called when an error or an interrupt occurs in an
14072  * interactive shell and control is returned to the main command loop.
14073  * (In dash, this function is auto-generated by build machinery).
14074  */
14075 static void
14076 reset(void)
14077 {
14078         /* from eval.c: */
14079         evalskip = 0;
14080         loopnest = 0;
14081
14082         /* from expand.c: */
14083         ifsfree();
14084
14085         /* from input.c: */
14086         g_parsefile->left_in_buffer = 0;
14087         g_parsefile->left_in_line = 0;      /* clear input buffer */
14088         popallfiles();
14089
14090         /* from redir.c: */
14091         unwindredir(NULL);
14092
14093         /* from var.c: */
14094         unwindlocalvars(NULL);
14095 }
14096
14097 #if PROFILE
14098 static short profile_buf[16384];
14099 extern int etext();
14100 #endif
14101
14102 /*
14103  * Main routine.  We initialize things, parse the arguments, execute
14104  * profiles if we're a login shell, and then call cmdloop to execute
14105  * commands.  The setjmp call sets up the location to jump to when an
14106  * exception occurs.  When an exception occurs the variable "state"
14107  * is used to figure out how far we had gotten.
14108  */
14109 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14110 int ash_main(int argc UNUSED_PARAM, char **argv)
14111 {
14112         volatile smallint state;
14113         struct jmploc jmploc;
14114         struct stackmark smark;
14115         int login_sh;
14116
14117         /* Initialize global data */
14118         INIT_G_misc();
14119         INIT_G_memstack();
14120         INIT_G_var();
14121 #if ENABLE_ASH_ALIAS
14122         INIT_G_alias();
14123 #endif
14124         INIT_G_cmdtable();
14125
14126 #if PROFILE
14127         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14128 #endif
14129
14130 #if ENABLE_FEATURE_EDITING
14131         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14132 #endif
14133         state = 0;
14134         if (setjmp(jmploc.loc)) {
14135                 smallint e;
14136                 smallint s;
14137
14138                 reset();
14139
14140                 e = exception_type;
14141                 s = state;
14142                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14143                         exitshell();
14144                 }
14145                 if (e == EXINT) {
14146                         newline_and_flush(stderr);
14147                 }
14148
14149                 popstackmark(&smark);
14150                 FORCE_INT_ON; /* enable interrupts */
14151                 if (s == 1)
14152                         goto state1;
14153                 if (s == 2)
14154                         goto state2;
14155                 if (s == 3)
14156                         goto state3;
14157                 goto state4;
14158         }
14159         exception_handler = &jmploc;
14160         rootpid = getpid();
14161
14162         init();
14163         setstackmark(&smark);
14164         login_sh = procargs(argv);
14165 #if DEBUG
14166         TRACE(("Shell args: "));
14167         trace_puts_args(argv);
14168 #endif
14169
14170         if (login_sh) {
14171                 const char *hp;
14172
14173                 state = 1;
14174                 read_profile("/etc/profile");
14175  state1:
14176                 state = 2;
14177                 hp = lookupvar("HOME");
14178                 if (hp)
14179                         read_profile("$HOME/.profile");
14180         }
14181  state2:
14182         state = 3;
14183         if (
14184 #ifndef linux
14185          getuid() == geteuid() && getgid() == getegid() &&
14186 #endif
14187          iflag
14188         ) {
14189                 const char *shinit = lookupvar("ENV");
14190                 if (shinit != NULL && *shinit != '\0')
14191                         read_profile(shinit);
14192         }
14193         popstackmark(&smark);
14194  state3:
14195         state = 4;
14196         if (minusc) {
14197                 /* evalstring pushes parsefile stack.
14198                  * Ensure we don't falsely claim that 0 (stdin)
14199                  * is one of stacked source fds.
14200                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14201                 // if (!sflag) g_parsefile->pf_fd = -1;
14202                 // ^^ not necessary since now we special-case fd 0
14203                 // in save_fd_on_redirect()
14204                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14205         }
14206
14207         if (sflag || minusc == NULL) {
14208 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14209                 if (iflag) {
14210                         const char *hp = lookupvar("HISTFILE");
14211                         if (!hp) {
14212                                 hp = lookupvar("HOME");
14213                                 if (hp) {
14214                                         INT_OFF;
14215                                         hp = concat_path_file(hp, ".ash_history");
14216                                         setvar0("HISTFILE", hp);
14217                                         free((char*)hp);
14218                                         INT_ON;
14219                                         hp = lookupvar("HISTFILE");
14220                                 }
14221                         }
14222                         if (hp)
14223                                 line_input_state->hist_file = hp;
14224 # if ENABLE_FEATURE_SH_HISTFILESIZE
14225                         hp = lookupvar("HISTFILESIZE");
14226                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14227 # endif
14228                 }
14229 #endif
14230  state4: /* XXX ??? - why isn't this before the "if" statement */
14231                 cmdloop(1);
14232         }
14233 #if PROFILE
14234         monitor(0);
14235 #endif
14236 #ifdef GPROF
14237         {
14238                 extern void _mcleanup(void);
14239                 _mcleanup();
14240         }
14241 #endif
14242         TRACE(("End of main reached\n"));
14243         exitshell();
14244         /* NOTREACHED */
14245 }
14246
14247
14248 /*-
14249  * Copyright (c) 1989, 1991, 1993, 1994
14250  *      The Regents of the University of California.  All rights reserved.
14251  *
14252  * This code is derived from software contributed to Berkeley by
14253  * Kenneth Almquist.
14254  *
14255  * Redistribution and use in source and binary forms, with or without
14256  * modification, are permitted provided that the following conditions
14257  * are met:
14258  * 1. Redistributions of source code must retain the above copyright
14259  *    notice, this list of conditions and the following disclaimer.
14260  * 2. Redistributions in binary form must reproduce the above copyright
14261  *    notice, this list of conditions and the following disclaimer in the
14262  *    documentation and/or other materials provided with the distribution.
14263  * 3. Neither the name of the University nor the names of its contributors
14264  *    may be used to endorse or promote products derived from this software
14265  *    without specific prior written permission.
14266  *
14267  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14268  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14269  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14270  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14271  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14272  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14273  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14274  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14275  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14276  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14277  * SUCH DAMAGE.
14278  */