e89cecf0b05608dda57288f717e58806b7a5f563
[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 (78 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 #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
185 # include "embedded_scripts.h"
186 #else
187 # define NUM_SCRIPTS 0
188 #endif
189
190 /* So far, all bash compat is controlled by one config option */
191 /* Separate defines document which part of code implements what */
192 /* function keyword */
193 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
194 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
195 /* &>file */
196 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
198 /* $'...' */
199 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
201 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
202 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
203 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
204 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
205 /* BASH_TEST2: [[ EXPR ]]
206  * Status of [[ support:
207  * We replace && and || with -a and -o
208  * TODO:
209  * singleword+noglob expansion:
210  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
211  *   [[ /bin/n* ]]; echo 0:$?
212  * -a/-o are not AND/OR ops! (they are just strings)
213  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
214  * = is glob match operator, not equality operator: STR = GLOB
215  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
216  * == same as =
217  * add =~ regex match operator: STR =~ REGEX
218  */
219 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
220 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
221 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
222 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
223 #define    BASH_EPOCH_VARS      ENABLE_ASH_BASH_COMPAT
224 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
225 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
226 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
227 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
228 #define    BASH_WAIT_N          ENABLE_ASH_BASH_COMPAT
229
230 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
231 /* Bionic at least up to version 24 has no glob() */
232 # undef  ENABLE_ASH_INTERNAL_GLOB
233 # define ENABLE_ASH_INTERNAL_GLOB 1
234 #endif
235
236 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
237 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
238 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
239 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
240 # error glob() should unbackslash them and match. uClibc does not unbackslash,
241 # error fails to match dirname, subsequently not expanding <pattern> in it.
242 // Testcase:
243 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
244 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
245 #endif
246
247 #if !ENABLE_ASH_INTERNAL_GLOB
248 # include <glob.h>
249 #endif
250
251 #include "unicode.h"
252 #include "shell_common.h"
253 #if ENABLE_FEATURE_SH_MATH
254 # include "math.h"
255 #else
256 typedef long arith_t;
257 # define ARITH_FMT "%ld"
258 #endif
259 #if ENABLE_ASH_RANDOM_SUPPORT
260 # include "random.h"
261 #else
262 # define CLEAR_RANDOM_T(rnd) ((void)0)
263 #endif
264
265 #include "NUM_APPLETS.h"
266 #if NUM_APPLETS == 1
267 /* STANDALONE does not make sense, and won't compile */
268 # undef CONFIG_FEATURE_SH_STANDALONE
269 # undef ENABLE_FEATURE_SH_STANDALONE
270 # undef IF_FEATURE_SH_STANDALONE
271 # undef IF_NOT_FEATURE_SH_STANDALONE
272 # define ENABLE_FEATURE_SH_STANDALONE 0
273 # define IF_FEATURE_SH_STANDALONE(...)
274 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
275 #endif
276
277 #ifndef F_DUPFD_CLOEXEC
278 # define F_DUPFD_CLOEXEC F_DUPFD
279 #endif
280 #ifndef O_CLOEXEC
281 # define O_CLOEXEC 0
282 #endif
283 #ifndef PIPE_BUF
284 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
285 #endif
286
287 #if !BB_MMU
288 # error "Do not even bother, ash will not run on NOMMU machine"
289 #endif
290
291 /* We use a trick to have more optimized code (fewer pointer reloads):
292  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
293  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
294  * This way, compiler in ash.c knows the pointer can not change.
295  *
296  * However, this may break on weird arches or toolchains. In this case,
297  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
298  * this optimization.
299  */
300 #ifndef BB_GLOBAL_CONST
301 # define BB_GLOBAL_CONST const
302 #endif
303
304
305 /* ============ Hash table sizes. Configurable. */
306
307 #define VTABSIZE 39
308 #define ATABSIZE 39
309 #define CMDTABLESIZE 31         /* should be prime */
310
311
312 /* ============ Shell options */
313
314 static const char *const optletters_optnames[] = {
315         "e"   "errexit",
316         "f"   "noglob",
317         "I"   "ignoreeof",
318 /* The below allowed this invocation:
319  * ash -c 'set -i; echo $-; sleep 5; echo $-'
320  * to be ^C-ed and get to interactive ash prompt.
321  * bash does not support such "set -i".
322  * In our code, this is denoted by empty long name:
323  */
324         "i"   "",
325         "m"   "monitor",
326         "n"   "noexec",
327 /* Ditto: bash has no "set -s" */
328         "s"   "",
329         "c"   "",
330         "x"   "xtrace",
331         "v"   "verbose",
332         "C"   "noclobber",
333         "a"   "allexport",
334         "b"   "notify",
335         "u"   "nounset",
336         "\0"  "vi"
337 #if BASH_PIPEFAIL
338         ,"\0"  "pipefail"
339 #endif
340 #if DEBUG
341         ,"\0"  "nolog"
342         ,"\0"  "debug"
343 #endif
344 };
345 //bash 4.4.23 also has these opts (with these defaults):
346 //braceexpand           on
347 //emacs                 on
348 //errtrace              off
349 //functrace             off
350 //hashall               on
351 //histexpand            off
352 //history               on
353 //interactive-comments  on
354 //keyword               off
355 //onecmd                off
356 //physical              off
357 //posix                 off
358 //privileged            off
359
360 #define optletters(n)  optletters_optnames[n][0]
361 #define optnames(n)   (optletters_optnames[n] + 1)
362
363 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
364
365
366 /* ============ Misc data */
367
368 #define msg_illnum "Illegal number: %s"
369
370 /*
371  * We enclose jmp_buf in a structure so that we can declare pointers to
372  * jump locations.  The global variable handler contains the location to
373  * jump to when an exception occurs, and the global variable exception_type
374  * contains a code identifying the exception.  To implement nested
375  * exception handlers, the user should save the value of handler on entry
376  * to an inner scope, set handler to point to a jmploc structure for the
377  * inner scope, and restore handler on exit from the scope.
378  */
379 struct jmploc {
380         jmp_buf loc;
381 };
382
383 struct globals_misc {
384         uint8_t exitstatus;     /* exit status of last command */
385         uint8_t back_exitstatus;/* exit status of backquoted command */
386         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
387         int savestatus;         /* exit status of last command outside traps */
388         int rootpid;            /* pid of main shell */
389         /* shell level: 0 for the main shell, 1 for its children, and so on */
390         int shlvl;
391 #define rootshell (!shlvl)
392         int errlinno;
393
394         char *minusc;  /* argument to -c option */
395
396         char *curdir; // = nullstr;     /* current working directory */
397         char *physdir; // = nullstr;    /* physical working directory */
398
399         char *arg0; /* value of $0 */
400
401         struct jmploc *exception_handler;
402
403         volatile int suppress_int; /* counter */
404         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
405         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
406         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
407         smallint exception_type; /* kind of exception (0..5) */
408         /* exceptions */
409 #define EXINT 0         /* SIGINT received */
410 #define EXERROR 1       /* a generic error */
411 #define EXEXIT 4        /* exit the shell */
412
413         char nullstr[1];        /* zero length string */
414
415         char optlist[NOPTS];
416 #define eflag optlist[0]
417 #define fflag optlist[1]
418 #define Iflag optlist[2]
419 #define iflag optlist[3]
420 #define mflag optlist[4]
421 #define nflag optlist[5]
422 #define sflag optlist[6]
423 #define cflag optlist[7]
424 #define xflag optlist[8]
425 #define vflag optlist[9]
426 #define Cflag optlist[10]
427 #define aflag optlist[11]
428 #define bflag optlist[12]
429 #define uflag optlist[13]
430 #define viflag optlist[14]
431 #if BASH_PIPEFAIL
432 # define pipefail optlist[15]
433 #else
434 # define pipefail 0
435 #endif
436 #if DEBUG
437 # define nolog optlist[15 + BASH_PIPEFAIL]
438 # define debug optlist[16 + BASH_PIPEFAIL]
439 #endif
440
441         /* trap handler commands */
442         /*
443          * Sigmode records the current value of the signal handlers for the various
444          * modes.  A value of zero means that the current handler is not known.
445          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
446          */
447         char sigmode[NSIG - 1];
448 #define S_DFL      1            /* default signal handling (SIG_DFL) */
449 #define S_CATCH    2            /* signal is caught */
450 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
451 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
452
453         /* indicates specified signal received */
454         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
455         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
456         char *trap[NSIG];
457         char **trap_ptr;        /* used only by "trap hack" */
458
459         /* Rarely referenced stuff */
460 #if ENABLE_ASH_RANDOM_SUPPORT
461         random_t random_gen;
462 #endif
463         pid_t backgndpid;        /* pid of last background process */
464 };
465 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
466 #define G_misc (*ash_ptr_to_globals_misc)
467 #define exitstatus        (G_misc.exitstatus )
468 #define back_exitstatus   (G_misc.back_exitstatus )
469 #define job_warning       (G_misc.job_warning)
470 #define savestatus  (G_misc.savestatus )
471 #define rootpid     (G_misc.rootpid    )
472 #define shlvl       (G_misc.shlvl      )
473 #define errlinno    (G_misc.errlinno   )
474 #define minusc      (G_misc.minusc     )
475 #define curdir      (G_misc.curdir     )
476 #define physdir     (G_misc.physdir    )
477 #define arg0        (G_misc.arg0       )
478 #define exception_handler (G_misc.exception_handler)
479 #define exception_type    (G_misc.exception_type   )
480 #define suppress_int      (G_misc.suppress_int     )
481 #define pending_int       (G_misc.pending_int      )
482 #define got_sigchld       (G_misc.got_sigchld      )
483 #define pending_sig       (G_misc.pending_sig      )
484 #define nullstr     (G_misc.nullstr    )
485 #define optlist     (G_misc.optlist    )
486 #define sigmode     (G_misc.sigmode    )
487 #define gotsig      (G_misc.gotsig     )
488 #define may_have_traps    (G_misc.may_have_traps   )
489 #define trap        (G_misc.trap       )
490 #define trap_ptr    (G_misc.trap_ptr   )
491 #define random_gen  (G_misc.random_gen )
492 #define backgndpid  (G_misc.backgndpid )
493 #define INIT_G_misc() do { \
494         (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \
495         barrier(); \
496         savestatus = -1; \
497         curdir = nullstr; \
498         physdir = nullstr; \
499         trap_ptr = trap; \
500 } while (0)
501
502
503 /* ============ DEBUG */
504 #if DEBUG
505 static void trace_printf(const char *fmt, ...);
506 static void trace_vprintf(const char *fmt, va_list va);
507 # define TRACE(param)    trace_printf param
508 # define TRACEV(param)   trace_vprintf param
509 # define close(fd) do { \
510         int dfd = (fd); \
511         if (close(dfd) < 0) \
512                 bb_error_msg("bug on %d: closing %d(0x%x)", \
513                         __LINE__, dfd, dfd); \
514 } while (0)
515 #else
516 # define TRACE(param)
517 # define TRACEV(param)
518 #endif
519
520
521 /* ============ Utility functions */
522 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
523 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
524
525 static int
526 isdigit_str9(const char *str)
527 {
528         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
529         while (--maxlen && isdigit(*str))
530                 str++;
531         return (*str == '\0');
532 }
533
534 static const char *
535 var_end(const char *var)
536 {
537         while (*var)
538                 if (*var++ == '=')
539                         break;
540         return var;
541 }
542
543
544 /* ============ Interrupts / exceptions */
545
546 static void exitshell(void) NORETURN;
547
548 /*
549  * These macros allow the user to suspend the handling of interrupt signals
550  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
551  * much more efficient and portable.  (But hacking the kernel is so much
552  * more fun than worrying about efficiency and portability. :-))
553  */
554 #if DEBUG_INTONOFF
555 # define INT_OFF do { \
556         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
557         suppress_int++; \
558         barrier(); \
559 } while (0)
560 #else
561 # define INT_OFF do { \
562         suppress_int++; \
563         barrier(); \
564 } while (0)
565 #endif
566
567 /*
568  * Called to raise an exception.  Since C doesn't include exceptions, we
569  * just do a longjmp to the exception handler.  The type of exception is
570  * stored in the global variable "exception_type".
571  */
572 static void raise_exception(int) NORETURN;
573 static void
574 raise_exception(int e)
575 {
576 #if DEBUG
577         if (exception_handler == NULL)
578                 abort();
579 #endif
580         INT_OFF;
581         exception_type = e;
582         longjmp(exception_handler->loc, 1);
583 }
584 #if DEBUG
585 #define raise_exception(e) do { \
586         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
587         raise_exception(e); \
588 } while (0)
589 #endif
590
591 /*
592  * Called when a SIGINT is received.  (If the user specifies
593  * that SIGINT is to be trapped or ignored using the trap builtin, then
594  * this routine is not called.)  Suppressint is nonzero when interrupts
595  * are held using the INT_OFF macro.  (The test for iflag is just
596  * defensive programming.)
597  */
598 static void raise_interrupt(void) NORETURN;
599 static void
600 raise_interrupt(void)
601 {
602         pending_int = 0;
603         /* Signal is not automatically unmasked after it is raised,
604          * do it ourself - unmask all signals */
605         sigprocmask_allsigs(SIG_UNBLOCK);
606         /* pending_sig = 0; - now done in signal_handler() */
607
608         if (!(rootshell && iflag)) {
609                 /* Kill ourself with SIGINT */
610                 signal(SIGINT, SIG_DFL);
611                 raise(SIGINT);
612         }
613         /* bash: ^C even on empty command line sets $? */
614         exitstatus = SIGINT + 128;
615         raise_exception(EXINT);
616         /* NOTREACHED */
617 }
618 #if DEBUG
619 #define raise_interrupt() do { \
620         TRACE(("raising interrupt on line %d\n", __LINE__)); \
621         raise_interrupt(); \
622 } while (0)
623 #endif
624
625 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
626 int_on(void)
627 {
628         barrier();
629         if (--suppress_int == 0 && pending_int) {
630                 raise_interrupt();
631         }
632 }
633 #if DEBUG_INTONOFF
634 # define INT_ON do { \
635         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
636         int_on(); \
637 } while (0)
638 #else
639 # define INT_ON int_on()
640 #endif
641 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
642 force_int_on(void)
643 {
644         barrier();
645         suppress_int = 0;
646         if (pending_int)
647                 raise_interrupt();
648 }
649 #define FORCE_INT_ON force_int_on()
650
651 #define SAVE_INT(v) ((v) = suppress_int)
652
653 #define RESTORE_INT(v) do { \
654         barrier(); \
655         suppress_int = (v); \
656         if (suppress_int == 0 && pending_int) \
657                 raise_interrupt(); \
658 } while (0)
659
660
661 /* ============ Stdout/stderr output */
662
663 static void
664 outstr(const char *p, FILE *file)
665 {
666         INT_OFF;
667         fputs(p, file);
668         INT_ON;
669 }
670
671 static void
672 flush_stdout_stderr(void)
673 {
674         INT_OFF;
675         fflush_all();
676         INT_ON;
677 }
678
679 /* Was called outcslow(c,FILE*), but c was always '\n' */
680 static void
681 newline_and_flush(FILE *dest)
682 {
683         INT_OFF;
684         putc('\n', dest);
685         fflush(dest);
686         INT_ON;
687 }
688
689 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
690 static int
691 out1fmt(const char *fmt, ...)
692 {
693         va_list ap;
694         int r;
695
696         INT_OFF;
697         va_start(ap, fmt);
698         r = vprintf(fmt, ap);
699         va_end(ap);
700         INT_ON;
701         return r;
702 }
703
704 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
705 static int
706 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
707 {
708         va_list ap;
709         int ret;
710
711         INT_OFF;
712         va_start(ap, fmt);
713         ret = vsnprintf(outbuf, length, fmt, ap);
714         va_end(ap);
715         INT_ON;
716         return ret > (int)length ? length : ret;
717 }
718
719 static void
720 out1str(const char *p)
721 {
722         outstr(p, stdout);
723 }
724
725 static void
726 out2str(const char *p)
727 {
728         outstr(p, stderr);
729         flush_stdout_stderr();
730 }
731
732
733 /* ============ Parser structures */
734
735 /* control characters in argument strings */
736 #define CTL_FIRST CTLESC
737 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
738 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
739 #define CTLENDVAR    ((unsigned char)'\203')
740 #define CTLBACKQ     ((unsigned char)'\204')
741 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
742 #define CTLENDARI    ((unsigned char)'\207')
743 #define CTLQUOTEMARK ((unsigned char)'\210')
744 #define CTL_LAST CTLQUOTEMARK
745
746 /* variable substitution byte (follows CTLVAR) */
747 #define VSTYPE  0x0f            /* type of variable substitution */
748 #define VSNUL   0x10            /* colon--treat the empty string as unset */
749
750 /* values of VSTYPE field */
751 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
752 #define VSMINUS         0x2     /* ${var-text} */
753 #define VSPLUS          0x3     /* ${var+text} */
754 #define VSQUESTION      0x4     /* ${var?message} */
755 #define VSASSIGN        0x5     /* ${var=text} */
756 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
757 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
758 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
759 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
760 #define VSLENGTH        0xa     /* ${#var} */
761 #if BASH_SUBSTR
762 #define VSSUBSTR        0xc     /* ${var:position:length} */
763 #endif
764 #if BASH_PATTERN_SUBST
765 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
766 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
767 #endif
768
769 static const char dolatstr[] ALIGN1 = {
770         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
771 };
772 #define DOLATSTRLEN 6
773
774 #define NCMD      0
775 #define NPIPE     1
776 #define NREDIR    2
777 #define NBACKGND  3
778 #define NSUBSHELL 4
779 #define NAND      5
780 #define NOR       6
781 #define NSEMI     7
782 #define NIF       8
783 #define NWHILE    9
784 #define NUNTIL   10
785 #define NFOR     11
786 #define NCASE    12
787 #define NCLIST   13
788 #define NDEFUN   14
789 #define NARG     15
790 #define NTO      16
791 #if BASH_REDIR_OUTPUT
792 #define NTO2     17
793 #endif
794 #define NCLOBBER 18
795 #define NFROM    19
796 #define NFROMTO  20
797 #define NAPPEND  21
798 #define NTOFD    22
799 #define NFROMFD  23
800 #define NHERE    24
801 #define NXHERE   25
802 #define NNOT     26
803 #define N_NUMBER 27
804
805 union node;
806
807 struct ncmd {
808         smallint type; /* Nxxxx */
809         int linno;
810         union node *assign;
811         union node *args;
812         union node *redirect;
813 };
814
815 struct npipe {
816         smallint type;
817         smallint pipe_backgnd;
818         struct nodelist *cmdlist;
819 };
820
821 struct nredir {
822         smallint type;
823         int linno;
824         union node *n;
825         union node *redirect;
826 };
827
828 struct nbinary {
829         smallint type;
830         union node *ch1;
831         union node *ch2;
832 };
833
834 struct nif {
835         smallint type;
836         union node *test;
837         union node *ifpart;
838         union node *elsepart;
839 };
840
841 struct nfor {
842         smallint type;
843         int linno;
844         union node *args;
845         union node *body;
846         char *var;
847 };
848
849 struct ncase {
850         smallint type;
851         int linno;
852         union node *expr;
853         union node *cases;
854 };
855
856 struct nclist {
857         smallint type;
858         union node *next;
859         union node *pattern;
860         union node *body;
861 };
862
863 struct ndefun {
864         smallint type;
865         int linno;
866         char *text;
867         union node *body;
868 };
869
870 struct narg {
871         smallint type;
872         union node *next;
873         char *text;
874         struct nodelist *backquote;
875 };
876
877 /* nfile and ndup layout must match!
878  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
879  * that it is actually NTO2 (>&file), and change its type.
880  */
881 struct nfile {
882         smallint type;
883         union node *next;
884         int fd;
885         int _unused_dupfd;
886         union node *fname;
887         char *expfname;
888 };
889
890 struct ndup {
891         smallint type;
892         union node *next;
893         int fd;
894         int dupfd;
895         union node *vname;
896         char *_unused_expfname;
897 };
898
899 struct nhere {
900         smallint type;
901         union node *next;
902         int fd;
903         union node *doc;
904 };
905
906 struct nnot {
907         smallint type;
908         union node *com;
909 };
910
911 union node {
912         smallint type;
913         struct ncmd ncmd;
914         struct npipe npipe;
915         struct nredir nredir;
916         struct nbinary nbinary;
917         struct nif nif;
918         struct nfor nfor;
919         struct ncase ncase;
920         struct nclist nclist;
921         struct ndefun ndefun;
922         struct narg narg;
923         struct nfile nfile;
924         struct ndup ndup;
925         struct nhere nhere;
926         struct nnot nnot;
927 };
928
929 /*
930  * NODE_EOF is returned by parsecmd when it encounters an end of file.
931  * It must be distinct from NULL.
932  */
933 #define NODE_EOF ((union node *) -1L)
934
935 struct nodelist {
936         struct nodelist *next;
937         union node *n;
938 };
939
940 struct funcnode {
941         int count;
942         union node n;
943 };
944
945 /*
946  * Free a parse tree.
947  */
948 static void
949 freefunc(struct funcnode *f)
950 {
951         if (f && --f->count < 0)
952                 free(f);
953 }
954
955
956 /* ============ Debugging output */
957
958 #if DEBUG
959
960 static FILE *tracefile;
961
962 static void
963 trace_printf(const char *fmt, ...)
964 {
965         va_list va;
966
967         if (debug != 1)
968                 return;
969         if (DEBUG_TIME)
970                 fprintf(tracefile, "%u ", (int) time(NULL));
971         if (DEBUG_PID)
972                 fprintf(tracefile, "[%u] ", (int) getpid());
973         if (DEBUG_SIG)
974                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
975         va_start(va, fmt);
976         vfprintf(tracefile, fmt, va);
977         va_end(va);
978 }
979
980 static void
981 trace_vprintf(const char *fmt, va_list va)
982 {
983         if (debug != 1)
984                 return;
985         vfprintf(tracefile, fmt, va);
986         fprintf(tracefile, "\n");
987 }
988
989 static void
990 trace_puts(const char *s)
991 {
992         if (debug != 1)
993                 return;
994         fputs(s, tracefile);
995 }
996
997 static void
998 trace_puts_quoted(char *s)
999 {
1000         char *p;
1001         char c;
1002
1003         if (debug != 1)
1004                 return;
1005         putc('"', tracefile);
1006         for (p = s; *p; p++) {
1007                 switch ((unsigned char)*p) {
1008                 case '\n': c = 'n'; goto backslash;
1009                 case '\t': c = 't'; goto backslash;
1010                 case '\r': c = 'r'; goto backslash;
1011                 case '\"': c = '\"'; goto backslash;
1012                 case '\\': c = '\\'; goto backslash;
1013                 case CTLESC: c = 'e'; goto backslash;
1014                 case CTLVAR: c = 'v'; goto backslash;
1015                 case CTLBACKQ: c = 'q'; goto backslash;
1016  backslash:
1017                         putc('\\', tracefile);
1018                         putc(c, tracefile);
1019                         break;
1020                 default:
1021                         if (*p >= ' ' && *p <= '~')
1022                                 putc(*p, tracefile);
1023                         else {
1024                                 putc('\\', tracefile);
1025                                 putc((*p >> 6) & 03, tracefile);
1026                                 putc((*p >> 3) & 07, tracefile);
1027                                 putc(*p & 07, tracefile);
1028                         }
1029                         break;
1030                 }
1031         }
1032         putc('"', tracefile);
1033 }
1034
1035 static void
1036 trace_puts_args(char **ap)
1037 {
1038         if (debug != 1)
1039                 return;
1040         if (!*ap)
1041                 return;
1042         while (1) {
1043                 trace_puts_quoted(*ap);
1044                 if (!*++ap) {
1045                         putc('\n', tracefile);
1046                         break;
1047                 }
1048                 putc(' ', tracefile);
1049         }
1050 }
1051
1052 static void
1053 opentrace(void)
1054 {
1055         char s[100];
1056 #ifdef O_APPEND
1057         int flags;
1058 #endif
1059
1060         if (debug != 1) {
1061                 if (tracefile)
1062                         fflush(tracefile);
1063                 /* leave open because libedit might be using it */
1064                 return;
1065         }
1066         strcpy(s, "./trace");
1067         if (tracefile) {
1068                 if (!freopen(s, "a", tracefile)) {
1069                         fprintf(stderr, "Can't re-open %s\n", s);
1070                         debug = 0;
1071                         return;
1072                 }
1073         } else {
1074                 tracefile = fopen(s, "a");
1075                 if (tracefile == NULL) {
1076                         fprintf(stderr, "Can't open %s\n", s);
1077                         debug = 0;
1078                         return;
1079                 }
1080         }
1081 #ifdef O_APPEND
1082         flags = fcntl(fileno(tracefile), F_GETFL);
1083         if (flags >= 0)
1084                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1085 #endif
1086         setlinebuf(tracefile);
1087         fputs("\nTracing started.\n", tracefile);
1088 }
1089
1090 static void
1091 indent(int amount, char *pfx, FILE *fp)
1092 {
1093         int i;
1094
1095         for (i = 0; i < amount; i++) {
1096                 if (pfx && i == amount - 1)
1097                         fputs(pfx, fp);
1098                 putc('\t', fp);
1099         }
1100 }
1101
1102 /* little circular references here... */
1103 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1104
1105 static void
1106 sharg(union node *arg, FILE *fp)
1107 {
1108         char *p;
1109         struct nodelist *bqlist;
1110         unsigned char subtype;
1111
1112         if (arg->type != NARG) {
1113                 out1fmt("<node type %d>\n", arg->type);
1114                 abort();
1115         }
1116         bqlist = arg->narg.backquote;
1117         for (p = arg->narg.text; *p; p++) {
1118                 switch ((unsigned char)*p) {
1119                 case CTLESC:
1120                         p++;
1121                         putc(*p, fp);
1122                         break;
1123                 case CTLVAR:
1124                         putc('$', fp);
1125                         putc('{', fp);
1126                         subtype = *++p;
1127                         if (subtype == VSLENGTH)
1128                                 putc('#', fp);
1129
1130                         while (*p != '=') {
1131                                 putc(*p, fp);
1132                                 p++;
1133                         }
1134
1135                         if (subtype & VSNUL)
1136                                 putc(':', fp);
1137
1138                         switch (subtype & VSTYPE) {
1139                         case VSNORMAL:
1140                                 putc('}', fp);
1141                                 break;
1142                         case VSMINUS:
1143                                 putc('-', fp);
1144                                 break;
1145                         case VSPLUS:
1146                                 putc('+', fp);
1147                                 break;
1148                         case VSQUESTION:
1149                                 putc('?', fp);
1150                                 break;
1151                         case VSASSIGN:
1152                                 putc('=', fp);
1153                                 break;
1154                         case VSTRIMLEFT:
1155                                 putc('#', fp);
1156                                 break;
1157                         case VSTRIMLEFTMAX:
1158                                 putc('#', fp);
1159                                 putc('#', fp);
1160                                 break;
1161                         case VSTRIMRIGHT:
1162                                 putc('%', fp);
1163                                 break;
1164                         case VSTRIMRIGHTMAX:
1165                                 putc('%', fp);
1166                                 putc('%', fp);
1167                                 break;
1168                         case VSLENGTH:
1169                                 break;
1170                         default:
1171                                 out1fmt("<subtype %d>", subtype);
1172                         }
1173                         break;
1174                 case CTLENDVAR:
1175                         putc('}', fp);
1176                         break;
1177                 case CTLBACKQ:
1178                         putc('$', fp);
1179                         putc('(', fp);
1180                         shtree(bqlist->n, -1, NULL, fp);
1181                         putc(')', fp);
1182                         break;
1183                 default:
1184                         putc(*p, fp);
1185                         break;
1186                 }
1187         }
1188 }
1189
1190 static void
1191 shcmd(union node *cmd, FILE *fp)
1192 {
1193         union node *np;
1194         int first;
1195         const char *s;
1196         int dftfd;
1197
1198         first = 1;
1199         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1200                 if (!first)
1201                         putc(' ', fp);
1202                 sharg(np, fp);
1203                 first = 0;
1204         }
1205         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1206                 if (!first)
1207                         putc(' ', fp);
1208                 dftfd = 0;
1209                 switch (np->nfile.type) {
1210                 case NTO:      s = ">>"+1; dftfd = 1; break;
1211                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1212                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1213 #if BASH_REDIR_OUTPUT
1214                 case NTO2:
1215 #endif
1216                 case NTOFD:    s = ">&"; dftfd = 1; break;
1217                 case NFROM:    s = "<"; break;
1218                 case NFROMFD:  s = "<&"; break;
1219                 case NFROMTO:  s = "<>"; break;
1220                 default:       s = "*error*"; break;
1221                 }
1222                 if (np->nfile.fd != dftfd)
1223                         fprintf(fp, "%d", np->nfile.fd);
1224                 fputs(s, fp);
1225                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1226                         fprintf(fp, "%d", np->ndup.dupfd);
1227                 } else {
1228                         sharg(np->nfile.fname, fp);
1229                 }
1230                 first = 0;
1231         }
1232 }
1233
1234 static void
1235 shtree(union node *n, int ind, char *pfx, FILE *fp)
1236 {
1237         struct nodelist *lp;
1238         const char *s;
1239
1240         if (n == NULL)
1241                 return;
1242
1243         indent(ind, pfx, fp);
1244
1245         if (n == NODE_EOF) {
1246                 fputs("<EOF>", fp);
1247                 return;
1248         }
1249
1250         switch (n->type) {
1251         case NSEMI:
1252                 s = "; ";
1253                 goto binop;
1254         case NAND:
1255                 s = " && ";
1256                 goto binop;
1257         case NOR:
1258                 s = " || ";
1259  binop:
1260                 shtree(n->nbinary.ch1, ind, NULL, fp);
1261                 /* if (ind < 0) */
1262                         fputs(s, fp);
1263                 shtree(n->nbinary.ch2, ind, NULL, fp);
1264                 break;
1265         case NCMD:
1266                 shcmd(n, fp);
1267                 if (ind >= 0)
1268                         putc('\n', fp);
1269                 break;
1270         case NPIPE:
1271                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1272                         shtree(lp->n, 0, NULL, fp);
1273                         if (lp->next)
1274                                 fputs(" | ", fp);
1275                 }
1276                 if (n->npipe.pipe_backgnd)
1277                         fputs(" &", fp);
1278                 if (ind >= 0)
1279                         putc('\n', fp);
1280                 break;
1281         default:
1282                 fprintf(fp, "<node type %d>", n->type);
1283                 if (ind >= 0)
1284                         putc('\n', fp);
1285                 break;
1286         }
1287 }
1288
1289 static void
1290 showtree(union node *n)
1291 {
1292         trace_puts("showtree called\n");
1293         shtree(n, 1, NULL, stderr);
1294 }
1295
1296 #endif /* DEBUG */
1297
1298
1299 /* ============ Parser data */
1300
1301 /*
1302  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1303  */
1304 struct strlist {
1305         struct strlist *next;
1306         char *text;
1307 };
1308
1309 struct alias;
1310
1311 struct strpush {
1312         struct strpush *prev;   /* preceding string on stack */
1313         char *prev_string;
1314         int prev_left_in_line;
1315 #if ENABLE_ASH_ALIAS
1316         struct alias *ap;       /* if push was associated with an alias */
1317 #endif
1318         char *string;           /* remember the string since it may change */
1319
1320         /* Remember last two characters for pungetc. */
1321         int lastc[2];
1322
1323         /* Number of outstanding calls to pungetc. */
1324         int unget;
1325 };
1326
1327 /*
1328  * The parsefile structure pointed to by the global variable parsefile
1329  * contains information about the current file being read.
1330  */
1331 struct parsefile {
1332         struct parsefile *prev; /* preceding file on stack */
1333         int linno;              /* current line */
1334         int pf_fd;              /* file descriptor (or -1 if string) */
1335         int left_in_line;       /* number of chars left in this line */
1336         int left_in_buffer;     /* number of chars left in this buffer past the line */
1337         char *next_to_pgetc;    /* next char in buffer */
1338         char *buf;              /* input buffer */
1339         struct strpush *strpush; /* for pushing strings at this level */
1340         struct strpush basestrpush; /* so pushing one is fast */
1341
1342         /* Remember last two characters for pungetc. */
1343         int lastc[2];
1344
1345         /* Number of outstanding calls to pungetc. */
1346         int unget;
1347 };
1348
1349 static struct parsefile basepf;        /* top level input file */
1350 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1351 static char *commandname;              /* currently executing command */
1352
1353
1354 /* ============ Message printing */
1355
1356 static void
1357 ash_vmsg(const char *msg, va_list ap)
1358 {
1359         fprintf(stderr, "%s: ", arg0);
1360         if (commandname) {
1361                 if (strcmp(arg0, commandname))
1362                         fprintf(stderr, "%s: ", commandname);
1363                 if (!iflag || g_parsefile->pf_fd > 0)
1364                         fprintf(stderr, "line %d: ", errlinno);
1365         }
1366         vfprintf(stderr, msg, ap);
1367         newline_and_flush(stderr);
1368 }
1369
1370 /*
1371  * Exverror is called to raise the error exception.  If the second argument
1372  * is not NULL then error prints an error message using printf style
1373  * formatting.  It then raises the error exception.
1374  */
1375 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1376 static void
1377 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1378 {
1379 #if DEBUG
1380         if (msg) {
1381                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1382                 TRACEV((msg, ap));
1383         } else
1384                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1385         if (msg)
1386 #endif
1387                 ash_vmsg(msg, ap);
1388
1389         flush_stdout_stderr();
1390         raise_exception(cond);
1391         /* NOTREACHED */
1392 }
1393
1394 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1395 static void
1396 ash_msg_and_raise_error(const char *msg, ...)
1397 {
1398         va_list ap;
1399
1400         exitstatus = 2;
1401
1402         va_start(ap, msg);
1403         ash_vmsg_and_raise(EXERROR, msg, ap);
1404         /* NOTREACHED */
1405         va_end(ap);
1406 }
1407
1408 /*
1409  * 'fmt' must be a string literal.
1410  */
1411 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1412
1413 static void raise_error_syntax(const char *) NORETURN;
1414 static void
1415 raise_error_syntax(const char *msg)
1416 {
1417         errlinno = g_parsefile->linno;
1418         ash_msg_and_raise_error("syntax error: %s", msg);
1419         /* NOTREACHED */
1420 }
1421
1422 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1423 static void
1424 ash_msg_and_raise(int cond, const char *msg, ...)
1425 {
1426         va_list ap;
1427
1428         va_start(ap, msg);
1429         ash_vmsg_and_raise(cond, msg, ap);
1430         /* NOTREACHED */
1431         va_end(ap);
1432 }
1433
1434 /*
1435  * error/warning routines for external builtins
1436  */
1437 static void
1438 ash_msg(const char *fmt, ...)
1439 {
1440         va_list ap;
1441
1442         va_start(ap, fmt);
1443         ash_vmsg(fmt, ap);
1444         va_end(ap);
1445 }
1446
1447 /*
1448  * Return a string describing an error.  The returned string may be a
1449  * pointer to a static buffer that will be overwritten on the next call.
1450  * Action describes the operation that got the error.
1451  */
1452 static const char *
1453 errmsg(int e, const char *em)
1454 {
1455         if (e == ENOENT || e == ENOTDIR) {
1456                 return em;
1457         }
1458         return strerror(e);
1459 }
1460
1461
1462 /* ============ Memory allocation */
1463
1464 #if 0
1465 /* I consider these wrappers nearly useless:
1466  * ok, they return you to nearest exception handler, but
1467  * how much memory do you leak in the process, making
1468  * memory starvation worse?
1469  */
1470 static void *
1471 ckrealloc(void * p, size_t nbytes)
1472 {
1473         p = realloc(p, nbytes);
1474         if (!p)
1475                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1476         return p;
1477 }
1478
1479 static void *
1480 ckmalloc(size_t nbytes)
1481 {
1482         return ckrealloc(NULL, nbytes);
1483 }
1484
1485 static void *
1486 ckzalloc(size_t nbytes)
1487 {
1488         return memset(ckmalloc(nbytes), 0, nbytes);
1489 }
1490
1491 static char *
1492 ckstrdup(const char *s)
1493 {
1494         char *p = strdup(s);
1495         if (!p)
1496                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1497         return p;
1498 }
1499 #else
1500 /* Using bbox equivalents. They exit if out of memory */
1501 # define ckrealloc xrealloc
1502 # define ckmalloc  xmalloc
1503 # define ckzalloc  xzalloc
1504 # define ckstrdup  xstrdup
1505 #endif
1506
1507 /*
1508  * It appears that grabstackstr() will barf with such alignments
1509  * because stalloc() will return a string allocated in a new stackblock.
1510  */
1511 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1512 enum {
1513         /* Most machines require the value returned from malloc to be aligned
1514          * in some way.  The following macro will get this right
1515          * on many machines.  */
1516         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1517         /* Minimum size of a block */
1518         MINSIZE = SHELL_ALIGN(504),
1519 };
1520
1521 struct stack_block {
1522         struct stack_block *prev;
1523         char space[MINSIZE];
1524 };
1525
1526 struct stackmark {
1527         struct stack_block *stackp;
1528         char *stacknxt;
1529         size_t stacknleft;
1530 };
1531
1532
1533 struct globals_memstack {
1534         struct stack_block *g_stackp; // = &stackbase;
1535         char *g_stacknxt; // = stackbase.space;
1536         char *sstrend; // = stackbase.space + MINSIZE;
1537         size_t g_stacknleft; // = MINSIZE;
1538         struct stack_block stackbase;
1539 };
1540 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1541 #define G_memstack (*ash_ptr_to_globals_memstack)
1542 #define g_stackp     (G_memstack.g_stackp    )
1543 #define g_stacknxt   (G_memstack.g_stacknxt  )
1544 #define sstrend      (G_memstack.sstrend     )
1545 #define g_stacknleft (G_memstack.g_stacknleft)
1546 #define stackbase    (G_memstack.stackbase   )
1547 #define INIT_G_memstack() do { \
1548         (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \
1549         barrier(); \
1550         g_stackp = &stackbase; \
1551         g_stacknxt = stackbase.space; \
1552         g_stacknleft = MINSIZE; \
1553         sstrend = stackbase.space + MINSIZE; \
1554 } while (0)
1555
1556
1557 #define stackblock()     ((void *)g_stacknxt)
1558 #define stackblocksize() g_stacknleft
1559
1560 /*
1561  * Parse trees for commands are allocated in lifo order, so we use a stack
1562  * to make this more efficient, and also to avoid all sorts of exception
1563  * handling code to handle interrupts in the middle of a parse.
1564  *
1565  * The size 504 was chosen because the Ultrix malloc handles that size
1566  * well.
1567  */
1568 static void *
1569 stalloc(size_t nbytes)
1570 {
1571         char *p;
1572         size_t aligned;
1573
1574         aligned = SHELL_ALIGN(nbytes);
1575         if (aligned > g_stacknleft) {
1576                 size_t len;
1577                 size_t blocksize;
1578                 struct stack_block *sp;
1579
1580                 blocksize = aligned;
1581                 if (blocksize < MINSIZE)
1582                         blocksize = MINSIZE;
1583                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1584                 if (len < blocksize)
1585                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1586                 INT_OFF;
1587                 sp = ckmalloc(len);
1588                 sp->prev = g_stackp;
1589                 g_stacknxt = sp->space;
1590                 g_stacknleft = blocksize;
1591                 sstrend = g_stacknxt + blocksize;
1592                 g_stackp = sp;
1593                 INT_ON;
1594         }
1595         p = g_stacknxt;
1596         g_stacknxt += aligned;
1597         g_stacknleft -= aligned;
1598         return p;
1599 }
1600
1601 static void *
1602 stzalloc(size_t nbytes)
1603 {
1604         return memset(stalloc(nbytes), 0, nbytes);
1605 }
1606
1607 static void
1608 stunalloc(void *p)
1609 {
1610 #if DEBUG
1611         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1612                 write(STDERR_FILENO, "stunalloc\n", 10);
1613                 abort();
1614         }
1615 #endif
1616         g_stacknleft += g_stacknxt - (char *)p;
1617         g_stacknxt = p;
1618 }
1619
1620 /*
1621  * Like strdup but works with the ash stack.
1622  */
1623 static char *
1624 sstrdup(const char *p)
1625 {
1626         size_t len = strlen(p) + 1;
1627         return memcpy(stalloc(len), p, len);
1628 }
1629
1630 static ALWAYS_INLINE void
1631 grabstackblock(size_t len)
1632 {
1633         stalloc(len);
1634 }
1635
1636 static void
1637 pushstackmark(struct stackmark *mark, size_t len)
1638 {
1639         mark->stackp = g_stackp;
1640         mark->stacknxt = g_stacknxt;
1641         mark->stacknleft = g_stacknleft;
1642         grabstackblock(len);
1643 }
1644
1645 static void
1646 setstackmark(struct stackmark *mark)
1647 {
1648         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1649 }
1650
1651 static void
1652 popstackmark(struct stackmark *mark)
1653 {
1654         struct stack_block *sp;
1655
1656         if (!mark->stackp)
1657                 return;
1658
1659         INT_OFF;
1660         while (g_stackp != mark->stackp) {
1661                 sp = g_stackp;
1662                 g_stackp = sp->prev;
1663                 free(sp);
1664         }
1665         g_stacknxt = mark->stacknxt;
1666         g_stacknleft = mark->stacknleft;
1667         sstrend = mark->stacknxt + mark->stacknleft;
1668         INT_ON;
1669 }
1670
1671 /*
1672  * When the parser reads in a string, it wants to stick the string on the
1673  * stack and only adjust the stack pointer when it knows how big the
1674  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1675  * of space on top of the stack and stackblocklen returns the length of
1676  * this block.  Growstackblock will grow this space by at least one byte,
1677  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1678  * part of the block that has been used.
1679  */
1680 static void
1681 growstackblock(void)
1682 {
1683         size_t newlen;
1684
1685         newlen = g_stacknleft * 2;
1686         if (newlen < g_stacknleft)
1687                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1688         if (newlen < 128)
1689                 newlen += 128;
1690
1691         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1692                 struct stack_block *sp;
1693                 struct stack_block *prevstackp;
1694                 size_t grosslen;
1695
1696                 INT_OFF;
1697                 sp = g_stackp;
1698                 prevstackp = sp->prev;
1699                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1700                 sp = ckrealloc(sp, grosslen);
1701                 sp->prev = prevstackp;
1702                 g_stackp = sp;
1703                 g_stacknxt = sp->space;
1704                 g_stacknleft = newlen;
1705                 sstrend = sp->space + newlen;
1706                 INT_ON;
1707         } else {
1708                 char *oldspace = g_stacknxt;
1709                 size_t oldlen = g_stacknleft;
1710                 char *p = stalloc(newlen);
1711
1712                 /* free the space we just allocated */
1713                 g_stacknxt = memcpy(p, oldspace, oldlen);
1714                 g_stacknleft += newlen;
1715         }
1716 }
1717
1718 /*
1719  * The following routines are somewhat easier to use than the above.
1720  * The user declares a variable of type STACKSTR, which may be declared
1721  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1722  * the user uses the macro STPUTC to add characters to the string.  In
1723  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1724  * grown as necessary.  When the user is done, she can just leave the
1725  * string there and refer to it using stackblock().  Or she can allocate
1726  * the space for it using grabstackstr().  If it is necessary to allow
1727  * someone else to use the stack temporarily and then continue to grow
1728  * the string, the user should use grabstack to allocate the space, and
1729  * then call ungrabstr(p) to return to the previous mode of operation.
1730  *
1731  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1732  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1733  * is space for at least one character.
1734  */
1735 static void *
1736 growstackstr(void)
1737 {
1738         size_t len = stackblocksize();
1739         growstackblock();
1740         return (char *)stackblock() + len;
1741 }
1742
1743 static char *
1744 growstackto(size_t len)
1745 {
1746         while (stackblocksize() < len)
1747                 growstackblock();
1748
1749         return stackblock();
1750 }
1751
1752 /*
1753  * Called from CHECKSTRSPACE.
1754  */
1755 static char *
1756 makestrspace(size_t newlen, char *p)
1757 {
1758         size_t len = p - g_stacknxt;
1759
1760         return growstackto(len + newlen) + len;
1761 }
1762
1763 static char *
1764 stack_nputstr(const char *s, size_t n, char *p)
1765 {
1766         p = makestrspace(n, p);
1767         p = (char *)mempcpy(p, s, n);
1768         return p;
1769 }
1770
1771 static char *
1772 stack_putstr(const char *s, char *p)
1773 {
1774         return stack_nputstr(s, strlen(s), p);
1775 }
1776
1777 static char *
1778 _STPUTC(int c, char *p)
1779 {
1780         if (p == sstrend)
1781                 p = growstackstr();
1782         *p++ = c;
1783         return p;
1784 }
1785
1786 #define STARTSTACKSTR(p)        ((p) = stackblock())
1787 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1788 #define CHECKSTRSPACE(n, p) do { \
1789         char *q = (p); \
1790         size_t l = (n); \
1791         size_t m = sstrend - q; \
1792         if (l > m) \
1793                 (p) = makestrspace(l, q); \
1794 } while (0)
1795 #define USTPUTC(c, p)           (*(p)++ = (c))
1796 #define STACKSTRNUL(p) do { \
1797         if ((p) == sstrend) \
1798                 (p) = growstackstr(); \
1799         *(p) = '\0'; \
1800 } while (0)
1801 #define STUNPUTC(p)             (--(p))
1802 #define STTOPC(p)               ((p)[-1])
1803 #define STADJUST(amount, p)     ((p) += (amount))
1804
1805 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1806 #define ungrabstackstr(s, p)    stunalloc(s)
1807 #define stackstrend()           ((void *)sstrend)
1808
1809
1810 /* ============ String helpers */
1811
1812 /*
1813  * prefix -- see if pfx is a prefix of string.
1814  */
1815 static char *
1816 prefix(const char *string, const char *pfx)
1817 {
1818         while (*pfx) {
1819                 if (*pfx++ != *string++)
1820                         return NULL;
1821         }
1822         return (char *) string;
1823 }
1824
1825 /*
1826  * Check for a valid number.  This should be elsewhere.
1827  */
1828 static int
1829 is_number(const char *p)
1830 {
1831         do {
1832                 if (!isdigit(*p))
1833                         return 0;
1834         } while (*++p != '\0');
1835         return 1;
1836 }
1837
1838 /*
1839  * Convert a string of digits to an integer, printing an error message on
1840  * failure.
1841  */
1842 static int
1843 number(const char *s)
1844 {
1845         if (!is_number(s))
1846                 ash_msg_and_raise_error(msg_illnum, s);
1847         return atoi(s);
1848 }
1849
1850 /*
1851  * Produce a single quoted string suitable as input to the shell.
1852  * The return string is allocated on the stack.
1853  */
1854 static char *
1855 single_quote(const char *s)
1856 {
1857         char *p;
1858
1859         STARTSTACKSTR(p);
1860
1861         do {
1862                 char *q;
1863                 size_t len;
1864
1865                 len = strchrnul(s, '\'') - s;
1866
1867                 q = p = makestrspace(len + 3, p);
1868
1869                 *q++ = '\'';
1870                 q = (char *)mempcpy(q, s, len);
1871                 *q++ = '\'';
1872                 s += len;
1873
1874                 STADJUST(q - p, p);
1875
1876                 if (*s != '\'')
1877                         break;
1878                 len = 0;
1879                 do len++; while (*++s == '\'');
1880
1881                 q = p = makestrspace(len + 3, p);
1882
1883                 *q++ = '"';
1884                 q = (char *)mempcpy(q, s - len, len);
1885                 *q++ = '"';
1886
1887                 STADJUST(q - p, p);
1888         } while (*s);
1889
1890         USTPUTC('\0', p);
1891
1892         return stackblock();
1893 }
1894
1895 /*
1896  * Produce a possibly single quoted string suitable as input to the shell.
1897  * If quoting was done, the return string is allocated on the stack,
1898  * otherwise a pointer to the original string is returned.
1899  */
1900 static const char *
1901 maybe_single_quote(const char *s)
1902 {
1903         const char *p = s;
1904
1905         while (*p) {
1906                 /* Assuming ACSII */
1907                 /* quote ctrl_chars space !"#$%&'()* */
1908                 if (*p < '+')
1909                         goto need_quoting;
1910                 /* quote ;<=>? */
1911                 if (*p >= ';' && *p <= '?')
1912                         goto need_quoting;
1913                 /* quote `[\ */
1914                 if (*p == '`')
1915                         goto need_quoting;
1916                 if (*p == '[')
1917                         goto need_quoting;
1918                 if (*p == '\\')
1919                         goto need_quoting;
1920                 /* quote {|}~ DEL and high bytes */
1921                 if (*p > 'z')
1922                         goto need_quoting;
1923                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1924                 /* TODO: maybe avoid quoting % */
1925                 p++;
1926         }
1927         return s;
1928
1929  need_quoting:
1930         return single_quote(s);
1931 }
1932
1933
1934 /* ============ nextopt */
1935
1936 static char **argptr;                  /* argument list for builtin commands */
1937 static char *optionarg;                /* set by nextopt (like getopt) */
1938 static char *optptr;                   /* used by nextopt */
1939
1940 /*
1941  * XXX - should get rid of. Have all builtins use getopt(3).
1942  * The library getopt must have the BSD extension static variable
1943  * "optreset", otherwise it can't be used within the shell safely.
1944  *
1945  * Standard option processing (a la getopt) for builtin routines.
1946  * The only argument that is passed to nextopt is the option string;
1947  * the other arguments are unnecessary. It returns the character,
1948  * or '\0' on end of input.
1949  */
1950 static int
1951 nextopt(const char *optstring)
1952 {
1953         char *p;
1954         const char *q;
1955         char c;
1956
1957         p = optptr;
1958         if (p == NULL || *p == '\0') {
1959                 /* We ate entire "-param", take next one */
1960                 p = *argptr;
1961                 if (p == NULL)
1962                         return '\0';
1963                 if (*p != '-')
1964                         return '\0';
1965                 if (*++p == '\0') /* just "-" ? */
1966                         return '\0';
1967                 argptr++;
1968                 if (LONE_DASH(p)) /* "--" ? */
1969                         return '\0';
1970                 /* p => next "-param" */
1971         }
1972         /* p => some option char in the middle of a "-param" */
1973         c = *p++;
1974         for (q = optstring; *q != c;) {
1975                 if (*q == '\0')
1976                         ash_msg_and_raise_error("illegal option -%c", c);
1977                 if (*++q == ':')
1978                         q++;
1979         }
1980         if (*++q == ':') {
1981                 if (*p == '\0') {
1982                         p = *argptr++;
1983                         if (p == NULL)
1984                                 ash_msg_and_raise_error("no arg for -%c option", c);
1985                 }
1986                 optionarg = p;
1987                 p = NULL;
1988         }
1989         optptr = p;
1990         return c;
1991 }
1992
1993
1994 /* ============ Shell variables */
1995
1996 struct shparam {
1997         int nparam;             /* # of positional parameters (without $0) */
1998 #if ENABLE_ASH_GETOPTS
1999         int optind;             /* next parameter to be processed by getopts */
2000         int optoff;             /* used by getopts */
2001 #endif
2002         unsigned char malloced; /* if parameter list dynamically allocated */
2003         char **p;               /* parameter list */
2004 };
2005
2006 /*
2007  * Free the list of positional parameters.
2008  */
2009 static void
2010 freeparam(volatile struct shparam *param)
2011 {
2012         if (param->malloced) {
2013                 char **ap, **ap1;
2014                 ap = ap1 = param->p;
2015                 while (*ap)
2016                         free(*ap++);
2017                 free(ap1);
2018         }
2019 }
2020
2021 #if ENABLE_ASH_GETOPTS
2022 static void FAST_FUNC getoptsreset(const char *value);
2023 #endif
2024
2025 struct var {
2026         struct var *next;               /* next entry in hash list */
2027         int flags;                      /* flags are defined above */
2028         const char *var_text;           /* name=value */
2029         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2030                                         /* the variable gets set/unset */
2031 };
2032
2033 struct localvar {
2034         struct localvar *next;          /* next local variable in list */
2035         struct var *vp;                 /* the variable that was made local */
2036         int flags;                      /* saved flags */
2037         const char *text;               /* saved text */
2038 };
2039
2040 /* flags */
2041 #define VEXPORT         0x01    /* variable is exported */
2042 #define VREADONLY       0x02    /* variable cannot be modified */
2043 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2044 #define VTEXTFIXED      0x08    /* text is statically allocated */
2045 #define VSTACK          0x10    /* text is allocated on the stack */
2046 #define VUNSET          0x20    /* the variable is not set */
2047 #define VNOFUNC         0x40    /* don't call the callback function */
2048 #define VNOSET          0x80    /* do not set variable - just readonly test */
2049 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2050 #if ENABLE_ASH_RANDOM_SUPPORT
2051 # define VDYNAMIC       0x200   /* dynamic variable */
2052 #else
2053 # define VDYNAMIC       0
2054 #endif
2055
2056
2057 /* Need to be before varinit_data[] */
2058 #if ENABLE_LOCALE_SUPPORT
2059 static void FAST_FUNC
2060 change_lc_all(const char *value)
2061 {
2062         if (value && *value != '\0')
2063                 setlocale(LC_ALL, value);
2064 }
2065 static void FAST_FUNC
2066 change_lc_ctype(const char *value)
2067 {
2068         if (value && *value != '\0')
2069                 setlocale(LC_CTYPE, value);
2070 }
2071 #endif
2072 #if ENABLE_ASH_MAIL
2073 static void chkmail(void);
2074 static void changemail(const char *var_value) FAST_FUNC;
2075 #else
2076 # define chkmail()  ((void)0)
2077 #endif
2078 static void changepath(const char *) FAST_FUNC;
2079 #if ENABLE_ASH_RANDOM_SUPPORT
2080 static void change_random(const char *) FAST_FUNC;
2081 #endif
2082 #if BASH_EPOCH_VARS
2083 static void change_seconds(const char *) FAST_FUNC;
2084 static void change_realtime(const char *) FAST_FUNC;
2085 #endif
2086
2087 static const struct {
2088         int flags;
2089         const char *var_text;
2090         void (*var_func)(const char *) FAST_FUNC;
2091 } varinit_data[] = {
2092         /*
2093          * Note: VEXPORT would not work correctly here for NOFORK applets:
2094          * some environment strings may be constant.
2095          */
2096         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2097 #if ENABLE_ASH_MAIL
2098         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2099         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2100 #endif
2101         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2102         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2103         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2104         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2105 #if ENABLE_ASH_GETOPTS
2106         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2107 #endif
2108         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2109 #if ENABLE_ASH_RANDOM_SUPPORT
2110         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2111 #endif
2112 #if BASH_EPOCH_VARS
2113         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2114         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2115 #endif
2116 #if ENABLE_LOCALE_SUPPORT
2117         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2118         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2119 #endif
2120 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2121         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2122 #endif
2123 };
2124
2125 struct redirtab;
2126
2127 struct globals_var {
2128         struct shparam shellparam;      /* $@ current positional parameters */
2129         struct redirtab *redirlist;
2130         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2131         struct var *vartab[VTABSIZE];
2132         struct var varinit[ARRAY_SIZE(varinit_data)];
2133         int lineno;
2134         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2135 };
2136 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2137 #define G_var (*ash_ptr_to_globals_var)
2138 #define shellparam    (G_var.shellparam   )
2139 //#define redirlist     (G_var.redirlist    )
2140 #define preverrout_fd (G_var.preverrout_fd)
2141 #define vartab        (G_var.vartab       )
2142 #define varinit       (G_var.varinit      )
2143 #define lineno        (G_var.lineno       )
2144 #define linenovar     (G_var.linenovar    )
2145 #define vifs      varinit[0]
2146 #if ENABLE_ASH_MAIL
2147 # define vmail    varinit[1]
2148 # define vmpath   varinit[2]
2149 #endif
2150 #define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2151 #define vpath     varinit[VAR_OFFSET1 + 1]
2152 #define vps1      varinit[VAR_OFFSET1 + 2]
2153 #define vps2      varinit[VAR_OFFSET1 + 3]
2154 #define vps4      varinit[VAR_OFFSET1 + 4]
2155 #if ENABLE_ASH_GETOPTS
2156 # define voptind  varinit[VAR_OFFSET1 + 5]
2157 #endif
2158 #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2159 #define vlineno   varinit[VAR_OFFSET2 + 5]
2160 #if ENABLE_ASH_RANDOM_SUPPORT
2161 # define vrandom  varinit[VAR_OFFSET2 + 6]
2162 #endif
2163 #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2164 #if BASH_EPOCH_VARS
2165 # define vepochs  varinit[VAR_OFFSET3 + 6]
2166 # define vepochr  varinit[VAR_OFFSET3 + 7]
2167 #endif
2168 #define INIT_G_var() do { \
2169         unsigned i; \
2170         (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \
2171         barrier(); \
2172         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2173                 varinit[i].flags    = varinit_data[i].flags; \
2174                 varinit[i].var_text = varinit_data[i].var_text; \
2175                 varinit[i].var_func = varinit_data[i].var_func; \
2176         } \
2177         strcpy(linenovar, "LINENO="); \
2178         vlineno.var_text = linenovar; \
2179 } while (0)
2180
2181 /*
2182  * The following macros access the values of the above variables.
2183  * They have to skip over the name.  They return the null string
2184  * for unset variables.
2185  */
2186 #define ifsval()        (vifs.var_text + 4)
2187 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2188 #if ENABLE_ASH_MAIL
2189 # define mailval()      (vmail.var_text + 5)
2190 # define mpathval()     (vmpath.var_text + 9)
2191 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2192 #endif
2193 #define pathval()       (vpath.var_text + 5)
2194 #define ps1val()        (vps1.var_text + 4)
2195 #define ps2val()        (vps2.var_text + 4)
2196 #define ps4val()        (vps4.var_text + 4)
2197 #if ENABLE_ASH_GETOPTS
2198 # define optindval()    (voptind.var_text + 7)
2199 #endif
2200
2201 #if ENABLE_ASH_GETOPTS
2202 static void FAST_FUNC
2203 getoptsreset(const char *value)
2204 {
2205         shellparam.optind = 1;
2206         if (is_number(value))
2207                 shellparam.optind = number(value) ?: 1;
2208         shellparam.optoff = -1;
2209 }
2210 #endif
2211
2212 /*
2213  * Compares two strings up to the first = or '\0'.  The first
2214  * string must be terminated by '='; the second may be terminated by
2215  * either '=' or '\0'.
2216  */
2217 static int
2218 varcmp(const char *p, const char *q)
2219 {
2220         int c, d;
2221
2222         while ((c = *p) == (d = *q)) {
2223                 if (c == '\0' || c == '=')
2224                         goto out;
2225                 p++;
2226                 q++;
2227         }
2228         if (c == '=')
2229                 c = '\0';
2230         if (d == '=')
2231                 d = '\0';
2232  out:
2233         return c - d;
2234 }
2235
2236 /*
2237  * Find the appropriate entry in the hash table from the name.
2238  */
2239 static struct var **
2240 hashvar(const char *p)
2241 {
2242         unsigned hashval;
2243
2244         hashval = ((unsigned char) *p) << 4;
2245         while (*p && *p != '=')
2246                 hashval += (unsigned char) *p++;
2247         return &vartab[hashval % VTABSIZE];
2248 }
2249
2250 static int
2251 vpcmp(const void *a, const void *b)
2252 {
2253         return varcmp(*(const char **)a, *(const char **)b);
2254 }
2255
2256 /*
2257  * This routine initializes the builtin variables.
2258  */
2259 static void
2260 initvar(void)
2261 {
2262         struct var *vp;
2263         struct var *end;
2264         struct var **vpp;
2265
2266         /*
2267          * PS1 depends on uid
2268          */
2269 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2270         vps1.var_text = "PS1=\\w \\$ ";
2271 #else
2272         if (!geteuid())
2273                 vps1.var_text = "PS1=# ";
2274 #endif
2275         vp = varinit;
2276         end = vp + ARRAY_SIZE(varinit);
2277         do {
2278                 vpp = hashvar(vp->var_text);
2279                 vp->next = *vpp;
2280                 *vpp = vp;
2281         } while (++vp < end);
2282 }
2283
2284 static struct var **
2285 findvar(struct var **vpp, const char *name)
2286 {
2287         for (; *vpp; vpp = &(*vpp)->next) {
2288                 if (varcmp((*vpp)->var_text, name) == 0) {
2289                         break;
2290                 }
2291         }
2292         return vpp;
2293 }
2294
2295 /*
2296  * Find the value of a variable.  Returns NULL if not set.
2297  */
2298 static const char* FAST_FUNC
2299 lookupvar(const char *name)
2300 {
2301         struct var *v;
2302
2303         v = *findvar(hashvar(name), name);
2304         if (v) {
2305 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2306         /*
2307          * Dynamic variables are implemented roughly the same way they are
2308          * in bash. Namely, they're "special" so long as they aren't unset.
2309          * As soon as they're unset, they're no longer dynamic, and dynamic
2310          * lookup will no longer happen at that point. -- PFM.
2311          */
2312                 if (v->flags & VDYNAMIC)
2313                         v->var_func(NULL);
2314 #endif
2315                 if (!(v->flags & VUNSET)) {
2316                         if (v == &vlineno && v->var_text == linenovar) {
2317                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2318                         }
2319                         return var_end(v->var_text);
2320                 }
2321         }
2322         return NULL;
2323 }
2324
2325 #if ENABLE_UNICODE_SUPPORT
2326 static void
2327 reinit_unicode_for_ash(void)
2328 {
2329         /* Unicode support should be activated even if LANG is set
2330          * _during_ shell execution, not only if it was set when
2331          * shell was started. Therefore, re-check LANG every time:
2332          */
2333         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2334          || ENABLE_UNICODE_USING_LOCALE
2335         ) {
2336                 const char *s = lookupvar("LC_ALL");
2337                 if (!s) s = lookupvar("LC_CTYPE");
2338                 if (!s) s = lookupvar("LANG");
2339                 reinit_unicode(s);
2340         }
2341 }
2342 #else
2343 # define reinit_unicode_for_ash() ((void)0)
2344 #endif
2345
2346 /*
2347  * Search the environment of a builtin command.
2348  */
2349 static ALWAYS_INLINE const char *
2350 bltinlookup(const char *name)
2351 {
2352         return lookupvar(name);
2353 }
2354
2355 /*
2356  * Same as setvar except that the variable and value are passed in
2357  * the first argument as name=value.  Since the first argument will
2358  * be actually stored in the table, it should not be a string that
2359  * will go away.
2360  * Called with interrupts off.
2361  */
2362 static struct var *
2363 setvareq(char *s, int flags)
2364 {
2365         struct var *vp, **vpp;
2366
2367         vpp = hashvar(s);
2368         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2369         vpp = findvar(vpp, s);
2370         vp = *vpp;
2371         if (vp) {
2372                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2373                         const char *n;
2374
2375                         if (flags & VNOSAVE)
2376                                 free(s);
2377                         n = vp->var_text;
2378                         exitstatus = 1;
2379                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2380                 }
2381
2382                 if (flags & VNOSET)
2383                         goto out;
2384
2385                 if (vp->var_func && !(flags & VNOFUNC))
2386                         vp->var_func(var_end(s));
2387
2388                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2389                         free((char*)vp->var_text);
2390
2391                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2392                         *vpp = vp->next;
2393                         free(vp);
2394  out_free:
2395                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2396                                 free(s);
2397                         goto out;
2398                 }
2399
2400                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2401 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2402                 if (flags & VUNSET)
2403                         flags &= ~VDYNAMIC;
2404 #endif
2405         } else {
2406                 /* variable s is not found */
2407                 if (flags & VNOSET)
2408                         goto out;
2409                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2410                         goto out_free;
2411                 vp = ckzalloc(sizeof(*vp));
2412                 vp->next = *vpp;
2413                 /*vp->func = NULL; - ckzalloc did it */
2414                 *vpp = vp;
2415         }
2416         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2417                 s = ckstrdup(s);
2418         vp->var_text = s;
2419         vp->flags = flags;
2420
2421  out:
2422         return vp;
2423 }
2424
2425 /*
2426  * Set the value of a variable.  The flags argument is ored with the
2427  * flags of the variable.  If val is NULL, the variable is unset.
2428  */
2429 static struct var *
2430 setvar(const char *name, const char *val, int flags)
2431 {
2432         const char *q;
2433         char *p;
2434         char *nameeq;
2435         size_t namelen;
2436         size_t vallen;
2437         struct var *vp;
2438
2439         q = endofname(name);
2440         p = strchrnul(q, '=');
2441         namelen = p - name;
2442         if (!namelen || p != q)
2443                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2444         vallen = 0;
2445         if (val == NULL) {
2446                 flags |= VUNSET;
2447         } else {
2448                 vallen = strlen(val);
2449         }
2450
2451         INT_OFF;
2452         nameeq = ckzalloc(namelen + vallen + 2);
2453         p = mempcpy(nameeq, name, namelen);
2454         if (val) {
2455                 *p++ = '=';
2456                 memcpy(p, val, vallen);
2457         }
2458         vp = setvareq(nameeq, flags | VNOSAVE);
2459         INT_ON;
2460
2461         return vp;
2462 }
2463
2464 static void FAST_FUNC
2465 setvar0(const char *name, const char *val)
2466 {
2467         setvar(name, val, 0);
2468 }
2469
2470 /*
2471  * Unset the specified variable.
2472  */
2473 static void
2474 unsetvar(const char *s)
2475 {
2476         setvar(s, NULL, 0);
2477 }
2478
2479 /*
2480  * Process a linked list of variable assignments.
2481  */
2482 static void
2483 listsetvar(struct strlist *list_set_var, int flags)
2484 {
2485         struct strlist *lp = list_set_var;
2486
2487         if (!lp)
2488                 return;
2489         INT_OFF;
2490         do {
2491                 setvareq(lp->text, flags);
2492                 lp = lp->next;
2493         } while (lp);
2494         INT_ON;
2495 }
2496
2497 /*
2498  * Generate a list of variables satisfying the given conditions.
2499  */
2500 #if !ENABLE_FEATURE_SH_NOFORK
2501 # define listvars(on, off, lp, end) listvars(on, off, end)
2502 #endif
2503 static char **
2504 listvars(int on, int off, struct strlist *lp, char ***end)
2505 {
2506         struct var **vpp;
2507         struct var *vp;
2508         char **ep;
2509         int mask;
2510
2511         STARTSTACKSTR(ep);
2512         vpp = vartab;
2513         mask = on | off;
2514         do {
2515                 for (vp = *vpp; vp; vp = vp->next) {
2516                         if ((vp->flags & mask) == on) {
2517 #if ENABLE_FEATURE_SH_NOFORK
2518                                 /* If variable with the same name is both
2519                                  * exported and temporarily set for a command:
2520                                  *  export ZVAR=5
2521                                  *  ZVAR=6 printenv
2522                                  * then "ZVAR=6" will be both in vartab and
2523                                  * lp lists. Do not pass it twice to printenv.
2524                                  */
2525                                 struct strlist *lp1 = lp;
2526                                 while (lp1) {
2527                                         if (strcmp(lp1->text, vp->var_text) == 0)
2528                                                 goto skip;
2529                                         lp1 = lp1->next;
2530                                 }
2531 #endif
2532                                 if (ep == stackstrend())
2533                                         ep = growstackstr();
2534                                 *ep++ = (char*)vp->var_text;
2535 #if ENABLE_FEATURE_SH_NOFORK
2536  skip: ;
2537 #endif
2538                         }
2539                 }
2540         } while (++vpp < vartab + VTABSIZE);
2541
2542 #if ENABLE_FEATURE_SH_NOFORK
2543         while (lp) {
2544                 if (ep == stackstrend())
2545                         ep = growstackstr();
2546                 *ep++ = lp->text;
2547                 lp = lp->next;
2548         }
2549 #endif
2550
2551         if (ep == stackstrend())
2552                 ep = growstackstr();
2553         if (end)
2554                 *end = ep;
2555         *ep++ = NULL;
2556         return grabstackstr(ep);
2557 }
2558
2559
2560 /* ============ Path search helper
2561  *
2562  * The variable path (passed by reference) should be set to the start
2563  * of the path before the first call; padvance will update
2564  * this value as it proceeds.  Successive calls to padvance will return
2565  * the possible path expansions in sequence.  If an option (indicated by
2566  * a percent sign) appears in the path entry then the global variable
2567  * pathopt will be set to point to it; otherwise pathopt will be set to
2568  * NULL.
2569  */
2570 static const char *pathopt;     /* set by padvance */
2571
2572 static int
2573 padvance(const char **path, const char *name)
2574 {
2575         const char *p;
2576         char *q;
2577         const char *start;
2578         size_t len;
2579
2580         if (*path == NULL)
2581                 return -1;
2582         start = *path;
2583         for (p = start; *p && *p != ':' && *p != '%'; p++)
2584                 continue;
2585         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2586         q = growstackto(len);
2587         if (p != start) {
2588                 q = mempcpy(q, start, p - start);
2589                 *q++ = '/';
2590         }
2591         strcpy(q, name);
2592         pathopt = NULL;
2593         if (*p == '%') {
2594                 pathopt = ++p;
2595                 while (*p && *p != ':')
2596                         p++;
2597         }
2598         if (*p == ':')
2599                 *path = p + 1;
2600         else
2601                 *path = NULL;
2602         return len;
2603 }
2604
2605
2606 /* ============ Prompt */
2607
2608 static smallint doprompt;                   /* if set, prompt the user */
2609 static smallint needprompt;                 /* true if interactive and at start of line */
2610
2611 #if ENABLE_FEATURE_EDITING
2612 static line_input_t *line_input_state;
2613 static const char *cmdedit_prompt;
2614 static void
2615 putprompt(const char *s)
2616 {
2617         if (ENABLE_ASH_EXPAND_PRMT) {
2618                 free((char*)cmdedit_prompt);
2619                 cmdedit_prompt = ckstrdup(s);
2620                 return;
2621         }
2622         cmdedit_prompt = s;
2623 }
2624 #else
2625 static void
2626 putprompt(const char *s)
2627 {
2628         out2str(s);
2629 }
2630 #endif
2631
2632 /* expandstr() needs parsing machinery, so it is far away ahead... */
2633 static const char *expandstr(const char *ps, int syntax_type);
2634 /* Values for syntax param */
2635 #define BASESYNTAX 0    /* not in quotes */
2636 #define DQSYNTAX   1    /* in double quotes */
2637 #define SQSYNTAX   2    /* in single quotes */
2638 #define ARISYNTAX  3    /* in arithmetic */
2639 #if ENABLE_ASH_EXPAND_PRMT
2640 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2641 #endif
2642 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2643
2644 /*
2645  * called by editline -- any expansions to the prompt should be added here.
2646  */
2647 static void
2648 setprompt_if(smallint do_set, int whichprompt)
2649 {
2650         const char *prompt;
2651         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2652
2653         if (!do_set)
2654                 return;
2655
2656         needprompt = 0;
2657
2658         switch (whichprompt) {
2659         case 1:
2660                 prompt = ps1val();
2661                 break;
2662         case 2:
2663                 prompt = ps2val();
2664                 break;
2665         default:                        /* 0 */
2666                 prompt = nullstr;
2667         }
2668 #if ENABLE_ASH_EXPAND_PRMT
2669         pushstackmark(&smark, stackblocksize());
2670         putprompt(expandstr(prompt, PSSYNTAX));
2671         popstackmark(&smark);
2672 #else
2673         putprompt(prompt);
2674 #endif
2675 }
2676
2677
2678 /* ============ The cd and pwd commands */
2679
2680 #define CD_PHYSICAL 1
2681 #define CD_PRINT 2
2682
2683 static int
2684 cdopt(void)
2685 {
2686         int flags = 0;
2687         int i, j;
2688
2689         j = 'L';
2690         while ((i = nextopt("LP")) != '\0') {
2691                 if (i != j) {
2692                         flags ^= CD_PHYSICAL;
2693                         j = i;
2694                 }
2695         }
2696
2697         return flags;
2698 }
2699
2700 /*
2701  * Update curdir (the name of the current directory) in response to a
2702  * cd command.
2703  */
2704 static const char *
2705 updatepwd(const char *dir)
2706 {
2707         char *new;
2708         char *p;
2709         char *cdcomppath;
2710         const char *lim;
2711
2712         cdcomppath = sstrdup(dir);
2713         STARTSTACKSTR(new);
2714         if (*dir != '/') {
2715                 if (curdir == nullstr)
2716                         return 0;
2717                 new = stack_putstr(curdir, new);
2718         }
2719         new = makestrspace(strlen(dir) + 2, new);
2720         lim = (char *)stackblock() + 1;
2721         if (*dir != '/') {
2722                 if (new[-1] != '/')
2723                         USTPUTC('/', new);
2724                 if (new > lim && *lim == '/')
2725                         lim++;
2726         } else {
2727                 USTPUTC('/', new);
2728                 cdcomppath++;
2729                 if (dir[1] == '/' && dir[2] != '/') {
2730                         USTPUTC('/', new);
2731                         cdcomppath++;
2732                         lim++;
2733                 }
2734         }
2735         p = strtok(cdcomppath, "/");
2736         while (p) {
2737                 switch (*p) {
2738                 case '.':
2739                         if (p[1] == '.' && p[2] == '\0') {
2740                                 while (new > lim) {
2741                                         STUNPUTC(new);
2742                                         if (new[-1] == '/')
2743                                                 break;
2744                                 }
2745                                 break;
2746                         }
2747                         if (p[1] == '\0')
2748                                 break;
2749                         /* fall through */
2750                 default:
2751                         new = stack_putstr(p, new);
2752                         USTPUTC('/', new);
2753                 }
2754                 p = strtok(NULL, "/");
2755         }
2756         if (new > lim)
2757                 STUNPUTC(new);
2758         *new = 0;
2759         return stackblock();
2760 }
2761
2762 /*
2763  * Find out what the current directory is. If we already know the current
2764  * directory, this routine returns immediately.
2765  */
2766 static char *
2767 getpwd(void)
2768 {
2769         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2770         return dir ? dir : nullstr;
2771 }
2772
2773 static void
2774 setpwd(const char *val, int setold)
2775 {
2776         char *oldcur, *dir;
2777
2778         oldcur = dir = curdir;
2779
2780         if (setold) {
2781                 setvar("OLDPWD", oldcur, VEXPORT);
2782         }
2783         INT_OFF;
2784         if (physdir != nullstr) {
2785                 if (physdir != oldcur)
2786                         free(physdir);
2787                 physdir = nullstr;
2788         }
2789         if (oldcur == val || !val) {
2790                 char *s = getpwd();
2791                 physdir = s;
2792                 if (!val)
2793                         dir = s;
2794         } else
2795                 dir = ckstrdup(val);
2796         if (oldcur != dir && oldcur != nullstr) {
2797                 free(oldcur);
2798         }
2799         curdir = dir;
2800         INT_ON;
2801         setvar("PWD", dir, VEXPORT);
2802 }
2803
2804 static void hashcd(void);
2805
2806 /*
2807  * Actually do the chdir.  We also call hashcd to let other routines
2808  * know that the current directory has changed.
2809  */
2810 static int
2811 docd(const char *dest, int flags)
2812 {
2813         const char *dir = NULL;
2814         int err;
2815
2816         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2817
2818         INT_OFF;
2819         if (!(flags & CD_PHYSICAL)) {
2820                 dir = updatepwd(dest);
2821                 if (dir)
2822                         dest = dir;
2823         }
2824         err = chdir(dest);
2825         if (err)
2826                 goto out;
2827         setpwd(dir, 1);
2828         hashcd();
2829  out:
2830         INT_ON;
2831         return err;
2832 }
2833
2834 static int FAST_FUNC
2835 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2836 {
2837         const char *dest;
2838         const char *path;
2839         const char *p;
2840         char c;
2841         struct stat statb;
2842         int flags;
2843         int len;
2844
2845         flags = cdopt();
2846         dest = *argptr;
2847         if (!dest)
2848                 dest = bltinlookup("HOME");
2849         else if (LONE_DASH(dest)) {
2850                 dest = bltinlookup("OLDPWD");
2851                 flags |= CD_PRINT;
2852         }
2853         if (!dest)
2854                 dest = nullstr;
2855         if (*dest == '/')
2856                 goto step6;
2857         if (*dest == '.') {
2858                 c = dest[1];
2859  dotdot:
2860                 switch (c) {
2861                 case '\0':
2862                 case '/':
2863                         goto step6;
2864                 case '.':
2865                         c = dest[2];
2866                         if (c != '.')
2867                                 goto dotdot;
2868                 }
2869         }
2870         if (!*dest)
2871                 dest = ".";
2872         path = bltinlookup("CDPATH");
2873         while (p = path, (len = padvance(&path, dest)) >= 0) {
2874                 c = *p;
2875                 p = stalloc(len);
2876
2877                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2878                         if (c && c != ':')
2879                                 flags |= CD_PRINT;
2880  docd:
2881                         if (!docd(p, flags))
2882                                 goto out;
2883                         goto err;
2884                 }
2885         }
2886
2887  step6:
2888         p = dest;
2889         goto docd;
2890
2891  err:
2892         ash_msg_and_raise_perror("can't cd to %s", dest);
2893         /* NOTREACHED */
2894  out:
2895         if (flags & CD_PRINT)
2896                 out1fmt("%s\n", curdir);
2897         return 0;
2898 }
2899
2900 static int FAST_FUNC
2901 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2902 {
2903         int flags;
2904         const char *dir = curdir;
2905
2906         flags = cdopt();
2907         if (flags) {
2908                 if (physdir == nullstr)
2909                         setpwd(dir, 0);
2910                 dir = physdir;
2911         }
2912         out1fmt("%s\n", dir);
2913         return 0;
2914 }
2915
2916
2917 /* ============ ... */
2918
2919
2920 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2921
2922 /* Syntax classes */
2923 #define CWORD     0             /* character is nothing special */
2924 #define CNL       1             /* newline character */
2925 #define CBACK     2             /* a backslash character */
2926 #define CSQUOTE   3             /* single quote */
2927 #define CDQUOTE   4             /* double quote */
2928 #define CENDQUOTE 5             /* a terminating quote */
2929 #define CBQUOTE   6             /* backwards single quote */
2930 #define CVAR      7             /* a dollar sign */
2931 #define CENDVAR   8             /* a '}' character */
2932 #define CLP       9             /* a left paren in arithmetic */
2933 #define CRP      10             /* a right paren in arithmetic */
2934 #define CENDFILE 11             /* end of file */
2935 #define CCTL     12             /* like CWORD, except it must be escaped */
2936 #define CSPCL    13             /* these terminate a word */
2937 #define CIGN     14             /* character should be ignored */
2938
2939 #define PEOF     256
2940 #if ENABLE_ASH_ALIAS
2941 # define PEOA    257
2942 #endif
2943
2944 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2945
2946 #if ENABLE_FEATURE_SH_MATH
2947 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2948 #else
2949 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2950 #endif
2951 static const uint16_t S_I_T[] ALIGN2 = {
2952 #if ENABLE_ASH_ALIAS
2953         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2954 #endif
2955         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2956         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2957         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2958         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2959         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2960         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2961         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2962         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2963         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2964         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2965         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2966 #if !USE_SIT_FUNCTION
2967         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2968         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2969         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2970 #endif
2971 #undef SIT_ITEM
2972 };
2973 /* Constants below must match table above */
2974 enum {
2975 #if ENABLE_ASH_ALIAS
2976         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2977 #endif
2978         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2979         CNL_CNL_CNL_CNL                    , /*  2 */
2980         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2981         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2982         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2983         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2984         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2985         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2986         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2987         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2988         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2989         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2990         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2991         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2992 };
2993
2994 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2995  * caller must ensure proper cast on it if c is *char_ptr!
2996  */
2997 #if USE_SIT_FUNCTION
2998
2999 static int
3000 SIT(int c, int syntax)
3001 {
3002         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3003         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3004         /*
3005          * This causes '/' to be prepended with CTLESC in dquoted string,
3006          * making "./file"* treated incorrectly because we feed
3007          * ".\/file*" string to glob(), confusing it (see expandmeta func).
3008          * The "homegrown" glob implementation is okay with that,
3009          * but glibc one isn't. With '/' always treated as CWORD,
3010          * both work fine.
3011          */
3012 # if ENABLE_ASH_ALIAS
3013         static const uint8_t syntax_index_table[] ALIGN1 = {
3014                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
3015                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
3016                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
3017                 11, 3                           /* "}~" */
3018         };
3019 # else
3020         static const uint8_t syntax_index_table[] ALIGN1 = {
3021                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3022                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3023                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3024                 10, 2                           /* "}~" */
3025         };
3026 # endif
3027         const char *s;
3028         int indx;
3029
3030         if (c == PEOF)
3031                 return CENDFILE;
3032 # if ENABLE_ASH_ALIAS
3033         if (c == PEOA)
3034                 indx = 0;
3035         else
3036 # endif
3037         {
3038                 /* Cast is purely for paranoia here,
3039                  * just in case someone passed signed char to us */
3040                 if ((unsigned char)c >= CTL_FIRST
3041                  && (unsigned char)c <= CTL_LAST
3042                 ) {
3043                         return CCTL;
3044                 }
3045                 s = strchrnul(spec_symbls, c);
3046                 if (*s == '\0')
3047                         return CWORD;
3048                 indx = syntax_index_table[s - spec_symbls];
3049         }
3050         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3051 }
3052
3053 #else   /* !USE_SIT_FUNCTION */
3054
3055 static const uint8_t syntax_index_table[] ALIGN1 = {
3056         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3057         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3058         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3059         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3060         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3061         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3062         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3063         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3064         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3065         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3066         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3067         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3068         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3069         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3070         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3071         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3072         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3073         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3074         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3075         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3076         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3077         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3078         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3079         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3080         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3081         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3082         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3083         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3084         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3085         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3086         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3087         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3088         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3089         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3090         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3091         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3092         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3094         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3095         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3096         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3097         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3098         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3099         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3100         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3102         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3103         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3104 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3105         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3106         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3107         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3108         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3109         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3112         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3115         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3116         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3117         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3118         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3119         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3120         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3121         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3122         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3123         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3124         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3125         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3126         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3127         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3128         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3129         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3130         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3131         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3132         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3133         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3134         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3135         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3136         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3137         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3138         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3139         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3140         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3141         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3142         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3143         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3144         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3145         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3146         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3147         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3148         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3149         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3150         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3151         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3152         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3153         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3154         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3155         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3156         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3157         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3158         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3159         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3160         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3161         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3162         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3163         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3164         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3165         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3166         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3167         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3168         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3169         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3170         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3171         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3172         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3173         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3174         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3175         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3176         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3177         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3178         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3179         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3180         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3181         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3182         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3183         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3184         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3185         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3186         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3187         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3188         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3189         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3190         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3191         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3192         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3193         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3194         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3195         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3271         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3272         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3273         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3274         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3275         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3276         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3277         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3278         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3279         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3280         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3281         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3282         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3283         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3284         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3285         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3286         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3287         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3288         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3289         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3290         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3291         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3292         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3293         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3294         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3295         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3296         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3297         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3298         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3299         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3300         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3301         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3302         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3303         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3304         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3305         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3306         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3307         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3308         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3309         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3310         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3311         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3312         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3313         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3314         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3315 # if ENABLE_ASH_ALIAS
3316         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3317 # endif
3318 };
3319
3320 #if 1
3321 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3322 #else /* debug version, caught one signed char bug */
3323 # define SIT(c, syntax) \
3324         ({ \
3325                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3326                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3327                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3328                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3329                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3330         })
3331 #endif
3332
3333 #endif  /* !USE_SIT_FUNCTION */
3334
3335
3336 /* ============ Alias handling */
3337
3338 #if ENABLE_ASH_ALIAS
3339
3340 #define ALIASINUSE 1
3341 #define ALIASDEAD  2
3342
3343 struct alias {
3344         struct alias *next;
3345         char *name;
3346         char *val;
3347         int flag;
3348 };
3349
3350
3351 static struct alias **atab; // [ATABSIZE];
3352 #define INIT_G_alias() do { \
3353         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3354 } while (0)
3355
3356
3357 static struct alias **
3358 __lookupalias(const char *name)
3359 {
3360         unsigned int hashval;
3361         struct alias **app;
3362         const char *p;
3363         unsigned int ch;
3364
3365         p = name;
3366
3367         ch = (unsigned char)*p;
3368         hashval = ch << 4;
3369         while (ch) {
3370                 hashval += ch;
3371                 ch = (unsigned char)*++p;
3372         }
3373         app = &atab[hashval % ATABSIZE];
3374
3375         for (; *app; app = &(*app)->next) {
3376                 if (strcmp(name, (*app)->name) == 0) {
3377                         break;
3378                 }
3379         }
3380
3381         return app;
3382 }
3383
3384 static struct alias *
3385 lookupalias(const char *name, int check)
3386 {
3387         struct alias *ap = *__lookupalias(name);
3388
3389         if (check && ap && (ap->flag & ALIASINUSE))
3390                 return NULL;
3391         return ap;
3392 }
3393
3394 static struct alias *
3395 freealias(struct alias *ap)
3396 {
3397         struct alias *next;
3398
3399         if (ap->flag & ALIASINUSE) {
3400                 ap->flag |= ALIASDEAD;
3401                 return ap;
3402         }
3403
3404         next = ap->next;
3405         free(ap->name);
3406         free(ap->val);
3407         free(ap);
3408         return next;
3409 }
3410
3411 static void
3412 setalias(const char *name, const char *val)
3413 {
3414         struct alias *ap, **app;
3415
3416         app = __lookupalias(name);
3417         ap = *app;
3418         INT_OFF;
3419         if (ap) {
3420                 if (!(ap->flag & ALIASINUSE)) {
3421                         free(ap->val);
3422                 }
3423                 ap->val = ckstrdup(val);
3424                 ap->flag &= ~ALIASDEAD;
3425         } else {
3426                 /* not found */
3427                 ap = ckzalloc(sizeof(struct alias));
3428                 ap->name = ckstrdup(name);
3429                 ap->val = ckstrdup(val);
3430                 /*ap->flag = 0; - ckzalloc did it */
3431                 /*ap->next = NULL;*/
3432                 *app = ap;
3433         }
3434         INT_ON;
3435 }
3436
3437 static int
3438 unalias(const char *name)
3439 {
3440         struct alias **app;
3441
3442         app = __lookupalias(name);
3443
3444         if (*app) {
3445                 INT_OFF;
3446                 *app = freealias(*app);
3447                 INT_ON;
3448                 return 0;
3449         }
3450
3451         return 1;
3452 }
3453
3454 static void
3455 rmaliases(void)
3456 {
3457         struct alias *ap, **app;
3458         int i;
3459
3460         INT_OFF;
3461         for (i = 0; i < ATABSIZE; i++) {
3462                 app = &atab[i];
3463                 for (ap = *app; ap; ap = *app) {
3464                         *app = freealias(*app);
3465                         if (ap == *app) {
3466                                 app = &ap->next;
3467                         }
3468                 }
3469         }
3470         INT_ON;
3471 }
3472
3473 static void
3474 printalias(const struct alias *ap)
3475 {
3476         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3477 }
3478
3479 /*
3480  * TODO - sort output
3481  */
3482 static int FAST_FUNC
3483 aliascmd(int argc UNUSED_PARAM, char **argv)
3484 {
3485         char *n, *v;
3486         int ret = 0;
3487         struct alias *ap;
3488
3489         if (!argv[1]) {
3490                 int i;
3491
3492                 for (i = 0; i < ATABSIZE; i++) {
3493                         for (ap = atab[i]; ap; ap = ap->next) {
3494                                 printalias(ap);
3495                         }
3496                 }
3497                 return 0;
3498         }
3499         while ((n = *++argv) != NULL) {
3500                 v = strchr(n+1, '=');
3501                 if (v == NULL) { /* n+1: funny ksh stuff */
3502                         ap = *__lookupalias(n);
3503                         if (ap == NULL) {
3504                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3505                                 ret = 1;
3506                         } else
3507                                 printalias(ap);
3508                 } else {
3509                         *v++ = '\0';
3510                         setalias(n, v);
3511                 }
3512         }
3513
3514         return ret;
3515 }
3516
3517 static int FAST_FUNC
3518 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3519 {
3520         int i;
3521
3522         while (nextopt("a") != '\0') {
3523                 rmaliases();
3524                 return 0;
3525         }
3526         for (i = 0; *argptr; argptr++) {
3527                 if (unalias(*argptr)) {
3528                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3529                         i = 1;
3530                 }
3531         }
3532
3533         return i;
3534 }
3535
3536 #endif /* ASH_ALIAS */
3537
3538
3539 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3540 #define FORK_FG    0
3541 #define FORK_BG    1
3542 #define FORK_NOJOB 2
3543
3544 /* mode flags for showjob(s) */
3545 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3546 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3547 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3548 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3549
3550 /*
3551  * A job structure contains information about a job.  A job is either a
3552  * single process or a set of processes contained in a pipeline.  In the
3553  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3554  * array of pids.
3555  */
3556 struct procstat {
3557         pid_t   ps_pid;         /* process id */
3558         int     ps_status;      /* last process status from wait() */
3559         char    *ps_cmd;        /* text of command being run */
3560 };
3561
3562 struct job {
3563         struct procstat ps0;    /* status of process */
3564         struct procstat *ps;    /* status of processes when more than one */
3565 #if JOBS
3566         int stopstatus;         /* status of a stopped job */
3567 #endif
3568         unsigned nprocs;        /* number of processes */
3569
3570 #define JOBRUNNING      0       /* at least one proc running */
3571 #define JOBSTOPPED      1       /* all procs are stopped */
3572 #define JOBDONE         2       /* all procs are completed */
3573         unsigned
3574                 state: 8,
3575 #if JOBS
3576                 sigint: 1,      /* job was killed by SIGINT */
3577                 jobctl: 1,      /* job running under job control */
3578 #endif
3579                 waited: 1,      /* true if this entry has been waited for */
3580                 used: 1,        /* true if this entry is in used */
3581                 changed: 1;     /* true if status has changed */
3582         struct job *prev_job;   /* previous job */
3583 };
3584
3585 static struct job *makejob(/*union node *,*/ int);
3586 static int forkshell(struct job *, union node *, int);
3587 static int waitforjob(struct job *);
3588
3589 #if !JOBS
3590 enum { doing_jobctl = 0 };
3591 #define setjobctl(on) do {} while (0)
3592 #else
3593 static smallint doing_jobctl; //references:8
3594 static void setjobctl(int);
3595 #endif
3596
3597 /*
3598  * Ignore a signal.
3599  */
3600 static void
3601 ignoresig(int signo)
3602 {
3603         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3604         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3605                 /* No, need to do it */
3606                 signal(signo, SIG_IGN);
3607         }
3608         sigmode[signo - 1] = S_HARD_IGN;
3609 }
3610
3611 /*
3612  * Only one usage site - in setsignal()
3613  */
3614 static void
3615 signal_handler(int signo)
3616 {
3617         if (signo == SIGCHLD) {
3618                 got_sigchld = 1;
3619                 if (!trap[SIGCHLD])
3620                         return;
3621         }
3622
3623         gotsig[signo - 1] = 1;
3624         pending_sig = signo;
3625
3626         if (signo == SIGINT && !trap[SIGINT]) {
3627                 if (!suppress_int) {
3628                         pending_sig = 0;
3629                         raise_interrupt(); /* does not return */
3630                 }
3631                 pending_int = 1;
3632         }
3633 }
3634
3635 /*
3636  * Set the signal handler for the specified signal.  The routine figures
3637  * out what it should be set to.
3638  */
3639 static void
3640 setsignal(int signo)
3641 {
3642         char *t;
3643         char cur_act, new_act;
3644         struct sigaction act;
3645
3646         t = trap[signo];
3647         new_act = S_DFL;
3648         if (t != NULL) { /* trap for this sig is set */
3649                 new_act = S_CATCH;
3650                 if (t[0] == '\0') /* trap is "": ignore this sig */
3651                         new_act = S_IGN;
3652         }
3653
3654         if (rootshell && new_act == S_DFL) {
3655                 switch (signo) {
3656                 case SIGINT:
3657                         if (iflag || minusc || sflag == 0)
3658                                 new_act = S_CATCH;
3659                         break;
3660                 case SIGQUIT:
3661 #if DEBUG
3662                         if (debug)
3663                                 break;
3664 #endif
3665                         /* man bash:
3666                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3667                          * commands run by bash have signal handlers
3668                          * set to the values inherited by the shell
3669                          * from its parent". */
3670                         new_act = S_IGN;
3671                         break;
3672                 case SIGTERM:
3673                         if (iflag)
3674                                 new_act = S_IGN;
3675                         break;
3676 #if JOBS
3677                 case SIGTSTP:
3678                 case SIGTTOU:
3679                         if (mflag)
3680                                 new_act = S_IGN;
3681                         break;
3682 #endif
3683                 }
3684         }
3685         /* if !rootshell, we reset SIGQUIT to DFL,
3686          * whereas we have to restore it to what shell got on entry.
3687          * This is handled by the fact that if signal was IGNored on entry,
3688          * then cur_act is S_HARD_IGN and we never change its sigaction
3689          * (see code below).
3690          */
3691
3692         if (signo == SIGCHLD)
3693                 new_act = S_CATCH;
3694
3695         t = &sigmode[signo - 1];
3696         cur_act = *t;
3697         if (cur_act == 0) {
3698                 /* current setting is not yet known */
3699                 if (sigaction(signo, NULL, &act)) {
3700                         /* pretend it worked; maybe we should give a warning,
3701                          * but other shells don't. We don't alter sigmode,
3702                          * so we retry every time.
3703                          * btw, in Linux it never fails. --vda */
3704                         return;
3705                 }
3706                 if (act.sa_handler == SIG_IGN) {
3707                         cur_act = S_HARD_IGN;
3708                         if (mflag
3709                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3710                         ) {
3711                                 cur_act = S_IGN;   /* don't hard ignore these */
3712                         }
3713                 }
3714                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3715                         /* installing SIG_DFL over SIG_DFL is a no-op */
3716                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3717                         *t = S_DFL;
3718                         return;
3719                 }
3720         }
3721         if (cur_act == S_HARD_IGN || cur_act == new_act)
3722                 return;
3723
3724         *t = new_act;
3725
3726         act.sa_handler = SIG_DFL;
3727         switch (new_act) {
3728         case S_CATCH:
3729                 act.sa_handler = signal_handler;
3730                 break;
3731         case S_IGN:
3732                 act.sa_handler = SIG_IGN;
3733                 break;
3734         }
3735         /* flags and mask matter only if !DFL and !IGN, but we do it
3736          * for all cases for more deterministic behavior:
3737          */
3738         act.sa_flags = 0; //TODO: why not SA_RESTART?
3739         sigfillset(&act.sa_mask);
3740
3741         sigaction_set(signo, &act);
3742 }
3743
3744 /* mode flags for set_curjob */
3745 #define CUR_DELETE 2
3746 #define CUR_RUNNING 1
3747 #define CUR_STOPPED 0
3748
3749 #if JOBS
3750 /* pgrp of shell on invocation */
3751 static int initialpgrp; //references:2
3752 static int ttyfd = -1; //5
3753 #endif
3754 /* array of jobs */
3755 static struct job *jobtab; //5
3756 /* size of array */
3757 static unsigned njobs; //4
3758 /* current job */
3759 static struct job *curjob; //lots
3760 /* number of presumed living untracked jobs */
3761 static int jobless; //4
3762
3763 #if 0
3764 /* Bash has a feature: it restores termios after a successful wait for
3765  * a foreground job which had at least one stopped or sigkilled member.
3766  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3767  * properly restoring tty state. Should we do this too?
3768  * A reproducer: ^Z an interactive python:
3769  *
3770  * # python
3771  * Python 2.7.12 (...)
3772  * >>> ^Z
3773  *      { python leaves tty in -icanon -echo state. We do survive that... }
3774  *  [1]+  Stopped                    python
3775  *      { ...however, next program (python #2) does not survive it well: }
3776  * # python
3777  * Python 2.7.12 (...)
3778  * >>> Traceback (most recent call last):
3779  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3780  *   File "<stdin>", line 1, in <module>
3781  * NameError: name 'qwerty' is not defined
3782  *
3783  * The implementation below is modeled on bash code and seems to work.
3784  * However, I'm not sure we should do this. For one: what if I'd fg
3785  * the stopped python instead? It'll be confused by "restored" tty state.
3786  */
3787 static struct termios shell_tty_info;
3788 static void
3789 get_tty_state(void)
3790 {
3791         if (rootshell && ttyfd >= 0)
3792                 tcgetattr(ttyfd, &shell_tty_info);
3793 }
3794 static void
3795 set_tty_state(void)
3796 {
3797         /* if (rootshell) - caller ensures this */
3798         if (ttyfd >= 0)
3799                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3800 }
3801 static int
3802 job_signal_status(struct job *jp)
3803 {
3804         int status;
3805         unsigned i;
3806         struct procstat *ps = jp->ps;
3807         for (i = 0; i < jp->nprocs; i++) {
3808                 status = ps[i].ps_status;
3809                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3810                         return status;
3811         }
3812         return 0;
3813 }
3814 static void
3815 restore_tty_if_stopped_or_signaled(struct job *jp)
3816 {
3817 //TODO: check what happens if we come from waitforjob() in expbackq()
3818         if (rootshell) {
3819                 int s = job_signal_status(jp);
3820                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3821                         set_tty_state();
3822         }
3823 }
3824 #else
3825 # define get_tty_state() ((void)0)
3826 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3827 #endif
3828
3829 static void
3830 set_curjob(struct job *jp, unsigned mode)
3831 {
3832         struct job *jp1;
3833         struct job **jpp, **curp;
3834
3835         /* first remove from list */
3836         jpp = curp = &curjob;
3837         while (1) {
3838                 jp1 = *jpp;
3839                 if (jp1 == jp)
3840                         break;
3841                 jpp = &jp1->prev_job;
3842         }
3843         *jpp = jp1->prev_job;
3844
3845         /* Then re-insert in correct position */
3846         jpp = curp;
3847         switch (mode) {
3848         default:
3849 #if DEBUG
3850                 abort();
3851 #endif
3852         case CUR_DELETE:
3853                 /* job being deleted */
3854                 break;
3855         case CUR_RUNNING:
3856                 /* newly created job or backgrounded job,
3857                  * put after all stopped jobs.
3858                  */
3859                 while (1) {
3860                         jp1 = *jpp;
3861 #if JOBS
3862                         if (!jp1 || jp1->state != JOBSTOPPED)
3863 #endif
3864                                 break;
3865                         jpp = &jp1->prev_job;
3866                 }
3867                 /* FALLTHROUGH */
3868 #if JOBS
3869         case CUR_STOPPED:
3870 #endif
3871                 /* newly stopped job - becomes curjob */
3872                 jp->prev_job = *jpp;
3873                 *jpp = jp;
3874                 break;
3875         }
3876 }
3877
3878 #if JOBS || DEBUG
3879 static int
3880 jobno(const struct job *jp)
3881 {
3882         return jp - jobtab + 1;
3883 }
3884 #endif
3885
3886 /*
3887  * Convert a job name to a job structure.
3888  */
3889 #if !JOBS
3890 #define getjob(name, getctl) getjob(name)
3891 #endif
3892 static struct job *
3893 getjob(const char *name, int getctl)
3894 {
3895         struct job *jp;
3896         struct job *found;
3897         const char *err_msg = "%s: no such job";
3898         unsigned num;
3899         int c;
3900         const char *p;
3901         char *(*match)(const char *, const char *);
3902
3903         jp = curjob;
3904         p = name;
3905         if (!p)
3906                 goto currentjob;
3907
3908         if (*p != '%')
3909                 goto err;
3910
3911         c = *++p;
3912         if (!c)
3913                 goto currentjob;
3914
3915         if (!p[1]) {
3916                 if (c == '+' || c == '%') {
3917  currentjob:
3918                         err_msg = "No current job";
3919                         goto check;
3920                 }
3921                 if (c == '-') {
3922                         if (jp)
3923                                 jp = jp->prev_job;
3924                         err_msg = "No previous job";
3925  check:
3926                         if (!jp)
3927                                 goto err;
3928                         goto gotit;
3929                 }
3930         }
3931
3932         if (is_number(p)) {
3933                 num = atoi(p);
3934                 if (num > 0 && num <= njobs) {
3935                         jp = jobtab + num - 1;
3936                         if (jp->used)
3937                                 goto gotit;
3938                         goto err;
3939                 }
3940         }
3941
3942         match = prefix;
3943         if (*p == '?') {
3944                 match = strstr;
3945                 p++;
3946         }
3947
3948         found = NULL;
3949         while (jp) {
3950                 if (match(jp->ps[0].ps_cmd, p)) {
3951                         if (found)
3952                                 goto err;
3953                         found = jp;
3954                         err_msg = "%s: ambiguous";
3955                 }
3956                 jp = jp->prev_job;
3957         }
3958         if (!found)
3959                 goto err;
3960         jp = found;
3961
3962  gotit:
3963 #if JOBS
3964         err_msg = "job %s not created under job control";
3965         if (getctl && jp->jobctl == 0)
3966                 goto err;
3967 #endif
3968         return jp;
3969  err:
3970         ash_msg_and_raise_error(err_msg, name);
3971 }
3972
3973 /*
3974  * Mark a job structure as unused.
3975  */
3976 static void
3977 freejob(struct job *jp)
3978 {
3979         struct procstat *ps;
3980         int i;
3981
3982         INT_OFF;
3983         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3984                 if (ps->ps_cmd != nullstr)
3985                         free(ps->ps_cmd);
3986         }
3987         if (jp->ps != &jp->ps0)
3988                 free(jp->ps);
3989         jp->used = 0;
3990         set_curjob(jp, CUR_DELETE);
3991         INT_ON;
3992 }
3993
3994 #if JOBS
3995 static void
3996 xtcsetpgrp(int fd, pid_t pgrp)
3997 {
3998         if (tcsetpgrp(fd, pgrp))
3999                 ash_msg_and_raise_perror("can't set tty process group");
4000 }
4001
4002 /*
4003  * Turn job control on and off.
4004  *
4005  * Note:  This code assumes that the third arg to ioctl is a character
4006  * pointer, which is true on Berkeley systems but not System V.  Since
4007  * System V doesn't have job control yet, this isn't a problem now.
4008  *
4009  * Called with interrupts off.
4010  */
4011 static void
4012 setjobctl(int on)
4013 {
4014         int fd;
4015         int pgrp;
4016
4017         if (on == doing_jobctl || rootshell == 0)
4018                 return;
4019         if (on) {
4020                 int ofd;
4021                 ofd = fd = open(_PATH_TTY, O_RDWR);
4022                 if (fd < 0) {
4023         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4024          * That sometimes helps to acquire controlling tty.
4025          * Obviously, a workaround for bugs when someone
4026          * failed to provide a controlling tty to bash! :) */
4027                         fd = 2;
4028                         while (!isatty(fd))
4029                                 if (--fd < 0)
4030                                         goto out;
4031                 }
4032                 /* fd is a tty at this point */
4033                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4034                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4035                         close(ofd);
4036                 if (fd < 0)
4037                         goto out; /* F_DUPFD failed */
4038                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4039                         close_on_exec_on(fd);
4040                 while (1) { /* while we are in the background */
4041                         pgrp = tcgetpgrp(fd);
4042                         if (pgrp < 0) {
4043  out:
4044                                 ash_msg("can't access tty; job control turned off");
4045                                 mflag = on = 0;
4046                                 goto close;
4047                         }
4048                         if (pgrp == getpgrp())
4049                                 break;
4050                         killpg(0, SIGTTIN);
4051                 }
4052                 initialpgrp = pgrp;
4053
4054                 setsignal(SIGTSTP);
4055                 setsignal(SIGTTOU);
4056                 setsignal(SIGTTIN);
4057                 pgrp = rootpid;
4058                 setpgid(0, pgrp);
4059                 xtcsetpgrp(fd, pgrp);
4060         } else {
4061                 /* turning job control off */
4062                 fd = ttyfd;
4063                 pgrp = initialpgrp;
4064                 /* was xtcsetpgrp, but this can make exiting ash
4065                  * loop forever if pty is already deleted */
4066                 tcsetpgrp(fd, pgrp);
4067                 setpgid(0, pgrp);
4068                 setsignal(SIGTSTP);
4069                 setsignal(SIGTTOU);
4070                 setsignal(SIGTTIN);
4071  close:
4072                 if (fd >= 0)
4073                         close(fd);
4074                 fd = -1;
4075         }
4076         ttyfd = fd;
4077         doing_jobctl = on;
4078 }
4079
4080 static int FAST_FUNC
4081 killcmd(int argc, char **argv)
4082 {
4083         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4084                 int i = 1;
4085                 do {
4086                         if (argv[i][0] == '%') {
4087                                 /*
4088                                  * "kill %N" - job kill
4089                                  * Converting to pgrp / pid kill
4090                                  */
4091                                 struct job *jp;
4092                                 char *dst;
4093                                 int j, n;
4094
4095                                 jp = getjob(argv[i], 0);
4096                                 /*
4097                                  * In jobs started under job control, we signal
4098                                  * entire process group by kill -PGRP_ID.
4099                                  * This happens, f.e., in interactive shell.
4100                                  *
4101                                  * Otherwise, we signal each child via
4102                                  * kill PID1 PID2 PID3.
4103                                  * Testcases:
4104                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4105                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4106                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4107                                  */
4108                                 n = jp->nprocs; /* can't be 0 (I hope) */
4109                                 if (jp->jobctl)
4110                                         n = 1;
4111                                 dst = alloca(n * sizeof(int)*4);
4112                                 argv[i] = dst;
4113                                 for (j = 0; j < n; j++) {
4114                                         struct procstat *ps = &jp->ps[j];
4115                                         /* Skip non-running and not-stopped members
4116                                          * (i.e. dead members) of the job
4117                                          */
4118                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4119                                                 continue;
4120                                         /*
4121                                          * kill_main has matching code to expect
4122                                          * leading space. Needed to not confuse
4123                                          * negative pids with "kill -SIGNAL_NO" syntax
4124                                          */
4125                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4126                                 }
4127                                 *dst = '\0';
4128                         }
4129                 } while (argv[++i]);
4130         }
4131         return kill_main(argc, argv);
4132 }
4133
4134 static void
4135 showpipe(struct job *jp /*, FILE *out*/)
4136 {
4137         struct procstat *ps;
4138         struct procstat *psend;
4139
4140         psend = jp->ps + jp->nprocs;
4141         for (ps = jp->ps + 1; ps < psend; ps++)
4142                 printf(" | %s", ps->ps_cmd);
4143         newline_and_flush(stdout);
4144         flush_stdout_stderr();
4145 }
4146
4147
4148 static int
4149 restartjob(struct job *jp, int mode)
4150 {
4151         struct procstat *ps;
4152         int i;
4153         int status;
4154         pid_t pgid;
4155
4156         INT_OFF;
4157         if (jp->state == JOBDONE)
4158                 goto out;
4159         jp->state = JOBRUNNING;
4160         pgid = jp->ps[0].ps_pid;
4161         if (mode == FORK_FG) {
4162                 get_tty_state();
4163                 xtcsetpgrp(ttyfd, pgid);
4164         }
4165         killpg(pgid, SIGCONT);
4166         ps = jp->ps;
4167         i = jp->nprocs;
4168         do {
4169                 if (WIFSTOPPED(ps->ps_status)) {
4170                         ps->ps_status = -1;
4171                 }
4172                 ps++;
4173         } while (--i);
4174  out:
4175         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4176         INT_ON;
4177         return status;
4178 }
4179
4180 static int FAST_FUNC
4181 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4182 {
4183         struct job *jp;
4184         int mode;
4185         int retval;
4186
4187         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4188         nextopt(nullstr);
4189         argv = argptr;
4190         do {
4191                 jp = getjob(*argv, 1);
4192                 if (mode == FORK_BG) {
4193                         set_curjob(jp, CUR_RUNNING);
4194                         printf("[%d] ", jobno(jp));
4195                 }
4196                 out1str(jp->ps[0].ps_cmd);
4197                 showpipe(jp /*, stdout*/);
4198                 retval = restartjob(jp, mode);
4199         } while (*argv && *++argv);
4200         return retval;
4201 }
4202 #endif
4203
4204 static int
4205 sprint_status48(char *os, int status, int sigonly)
4206 {
4207         char *s = os;
4208         int st;
4209
4210         if (!WIFEXITED(status)) {
4211 #if JOBS
4212                 if (WIFSTOPPED(status))
4213                         st = WSTOPSIG(status);
4214                 else
4215 #endif
4216                         st = WTERMSIG(status);
4217                 if (sigonly) {
4218                         if (st == SIGINT || st == SIGPIPE)
4219                                 goto out;
4220 #if JOBS
4221                         if (WIFSTOPPED(status))
4222                                 goto out;
4223 #endif
4224                 }
4225                 st &= 0x7f;
4226 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4227                 //s = stpncpy(s, strsignal(st), 32); //not all libc have stpncpy()
4228                 s += fmtstr(s, 32, strsignal(st));
4229                 if (WCOREDUMP(status)) {
4230                         s = stpcpy(s, " (core dumped)");
4231                 }
4232         } else if (!sigonly) {
4233                 st = WEXITSTATUS(status);
4234                 s += fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4235         }
4236  out:
4237         return s - os;
4238 }
4239
4240 static int
4241 wait_block_or_sig(int *status)
4242 {
4243         int pid;
4244
4245         do {
4246                 sigset_t mask;
4247
4248                 /* Poll all children for changes in their state */
4249                 got_sigchld = 0;
4250                 /* if job control is active, accept stopped processes too */
4251                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4252                 if (pid != 0)
4253                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4254
4255                 /* Children exist, but none are ready. Sleep until interesting signal */
4256 #if 1
4257                 sigfillset(&mask);
4258                 sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
4259                 while (!got_sigchld && !pending_sig)
4260                         sigsuspend(&mask);
4261                 sigprocmask(SIG_SETMASK, &mask, NULL);
4262 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4263                 while (!got_sigchld && !pending_sig)
4264                         pause();
4265 #endif
4266
4267                 /* If it was SIGCHLD, poll children again */
4268         } while (got_sigchld);
4269
4270         return pid;
4271 }
4272
4273 #define DOWAIT_NONBLOCK 0
4274 #define DOWAIT_BLOCK    1
4275 #define DOWAIT_BLOCK_OR_SIG 2
4276 #if BASH_WAIT_N
4277 # define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4278 #endif
4279
4280 static int
4281 dowait(int block, struct job *job)
4282 {
4283         int pid;
4284         int status;
4285         struct job *jp;
4286         struct job *thisjob;
4287 #if BASH_WAIT_N
4288         bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4289         block = (block & ~DOWAIT_JOBSTATUS);
4290 #endif
4291
4292         TRACE(("dowait(0x%x) called\n", block));
4293
4294         /* It's wrong to call waitpid() outside of INT_OFF region:
4295          * signal can arrive just after syscall return and handler can
4296          * longjmp away, losing stop/exit notification processing.
4297          * Thus, for "jobs" builtin, and for waiting for a fg job,
4298          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4299          *
4300          * However, for "wait" builtin it is wrong to simply call waitpid()
4301          * in INT_OFF region: "wait" needs to wait for any running job
4302          * to change state, but should exit on any trap too.
4303          * In INT_OFF region, a signal just before syscall entry can set
4304          * pending_sig variables, but we can't check them, and we would
4305          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4306          *
4307          * Because of this, we run inside INT_OFF, but use a special routine
4308          * which combines waitpid() and sigsuspend().
4309          * This is the reason why we need to have a handler for SIGCHLD:
4310          * SIG_DFL handler does not wake sigsuspend().
4311          */
4312         INT_OFF;
4313         if (block == DOWAIT_BLOCK_OR_SIG) {
4314                 pid = wait_block_or_sig(&status);
4315         } else {
4316                 int wait_flags = 0;
4317                 if (block == DOWAIT_NONBLOCK)
4318                         wait_flags = WNOHANG;
4319                 /* if job control is active, accept stopped processes too */
4320                 if (doing_jobctl)
4321                         wait_flags |= WUNTRACED;
4322                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4323                 pid = waitpid(-1, &status, wait_flags);
4324         }
4325         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4326                                 pid, status, errno, strerror(errno)));
4327         thisjob = NULL;
4328         if (pid <= 0)
4329                 goto out;
4330
4331         for (jp = curjob; jp; jp = jp->prev_job) {
4332                 int jobstate;
4333                 struct procstat *ps;
4334                 struct procstat *psend;
4335                 if (jp->state == JOBDONE)
4336                         continue;
4337                 jobstate = JOBDONE;
4338                 ps = jp->ps;
4339                 psend = ps + jp->nprocs;
4340                 do {
4341                         if (ps->ps_pid == pid) {
4342                                 TRACE(("Job %d: changing status of proc %d "
4343                                         "from 0x%x to 0x%x\n",
4344                                         jobno(jp), pid, ps->ps_status, status));
4345                                 ps->ps_status = status;
4346                                 thisjob = jp;
4347                         }
4348                         if (ps->ps_status == -1)
4349                                 jobstate = JOBRUNNING;
4350 #if JOBS
4351                         if (jobstate == JOBRUNNING)
4352                                 continue;
4353                         if (WIFSTOPPED(ps->ps_status)) {
4354                                 jp->stopstatus = ps->ps_status;
4355                                 jobstate = JOBSTOPPED;
4356                         }
4357 #endif
4358                 } while (++ps < psend);
4359                 if (!thisjob)
4360                         continue;
4361
4362                 /* Found the job where one of its processes changed its state.
4363                  * Is there at least one live and running process in this job? */
4364                 if (jobstate != JOBRUNNING) {
4365                         /* No. All live processes in the job are stopped
4366                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4367                          */
4368                         thisjob->changed = 1;
4369                         if (thisjob->state != jobstate) {
4370                                 TRACE(("Job %d: changing state from %d to %d\n",
4371                                         jobno(thisjob), thisjob->state, jobstate));
4372                                 thisjob->state = jobstate;
4373 #if JOBS
4374                                 if (jobstate == JOBSTOPPED)
4375                                         set_curjob(thisjob, CUR_STOPPED);
4376 #endif
4377                         }
4378                 }
4379                 goto out;
4380         }
4381         /* The process wasn't found in job list */
4382 #if JOBS
4383         if (!WIFSTOPPED(status))
4384                 jobless--;
4385 #endif
4386  out:
4387         INT_ON;
4388
4389 #if BASH_WAIT_N
4390         if (want_jobexitstatus) {
4391                 pid = -1;
4392                 if (thisjob && thisjob->state == JOBDONE)
4393                         pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4394         }
4395 #endif
4396         if (thisjob && thisjob == job) {
4397                 char s[48 + 1];
4398                 int len;
4399
4400                 len = sprint_status48(s, status, 1);
4401                 if (len) {
4402                         s[len] = '\n';
4403                         s[len + 1] = '\0';
4404                         out2str(s);
4405                 }
4406         }
4407         return pid;
4408 }
4409
4410 #if JOBS
4411 static void
4412 showjob(struct job *jp, int mode)
4413 {
4414         struct procstat *ps;
4415         struct procstat *psend;
4416         int col;
4417         int indent_col;
4418         char s[16 + 16 + 48];
4419         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4420
4421         ps = jp->ps;
4422
4423         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4424                 /* just output process (group) id of pipeline */
4425                 fprintf(out, "%d\n", ps->ps_pid);
4426                 return;
4427         }
4428
4429         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4430         indent_col = col;
4431
4432         if (jp == curjob)
4433                 s[col - 3] = '+';
4434         else if (curjob && jp == curjob->prev_job)
4435                 s[col - 3] = '-';
4436
4437         if (mode & SHOW_PIDS)
4438                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4439
4440         psend = ps + jp->nprocs;
4441
4442         if (jp->state == JOBRUNNING) {
4443                 strcpy(s + col, "Running");
4444                 col += sizeof("Running") - 1;
4445         } else {
4446                 int status = psend[-1].ps_status;
4447                 if (jp->state == JOBSTOPPED)
4448                         status = jp->stopstatus;
4449                 col += sprint_status48(s + col, status, 0);
4450         }
4451         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4452
4453         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4454          * or prints several "PID             | <cmdN>" lines,
4455          * depending on SHOW_PIDS bit.
4456          * We do not print status of individual processes
4457          * between PID and <cmdN>. bash does it, but not very well:
4458          * first line shows overall job status, not process status,
4459          * making it impossible to know 1st process status.
4460          */
4461         goto start;
4462         do {
4463                 /* for each process */
4464                 s[0] = '\0';
4465                 col = 33;
4466                 if (mode & SHOW_PIDS)
4467                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4468  start:
4469                 fprintf(out, "%s%*c%s%s",
4470                                 s,
4471                                 33 - col >= 0 ? 33 - col : 0, ' ',
4472                                 ps == jp->ps ? "" : "| ",
4473                                 ps->ps_cmd
4474                 );
4475         } while (++ps != psend);
4476         newline_and_flush(out);
4477
4478         jp->changed = 0;
4479
4480         if (jp->state == JOBDONE) {
4481                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4482                 freejob(jp);
4483         }
4484 }
4485
4486 /*
4487  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4488  * statuses have changed since the last call to showjobs.
4489  */
4490 static void
4491 showjobs(int mode)
4492 {
4493         struct job *jp;
4494
4495         TRACE(("showjobs(0x%x) called\n", mode));
4496
4497         /* Handle all finished jobs */
4498         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4499                 continue;
4500
4501         for (jp = curjob; jp; jp = jp->prev_job) {
4502                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4503                         showjob(jp, mode);
4504                 }
4505         }
4506 }
4507
4508 static int FAST_FUNC
4509 jobscmd(int argc UNUSED_PARAM, char **argv)
4510 {
4511         int mode, m;
4512
4513         mode = 0;
4514         while ((m = nextopt("lp")) != '\0') {
4515                 if (m == 'l')
4516                         mode |= SHOW_PIDS;
4517                 else
4518                         mode |= SHOW_ONLY_PGID;
4519         }
4520
4521         argv = argptr;
4522         if (*argv) {
4523                 do
4524                         showjob(getjob(*argv, 0), mode);
4525                 while (*++argv);
4526         } else {
4527                 showjobs(mode);
4528         }
4529
4530         return 0;
4531 }
4532 #endif /* JOBS */
4533
4534 /* Called only on finished or stopped jobs (no members are running) */
4535 static int
4536 getstatus(struct job *job)
4537 {
4538         int status;
4539         int retval;
4540         struct procstat *ps;
4541
4542         /* Fetch last member's status */
4543         ps = job->ps + job->nprocs - 1;
4544         status = ps->ps_status;
4545         if (pipefail) {
4546                 /* "set -o pipefail" mode: use last _nonzero_ status */
4547                 while (status == 0 && --ps >= job->ps)
4548                         status = ps->ps_status;
4549         }
4550
4551         retval = WEXITSTATUS(status);
4552         if (!WIFEXITED(status)) {
4553 #if JOBS
4554                 retval = WSTOPSIG(status);
4555                 if (!WIFSTOPPED(status))
4556 #endif
4557                 {
4558                         /* XXX: limits number of signals */
4559                         retval = WTERMSIG(status);
4560 #if JOBS
4561                         if (retval == SIGINT)
4562                                 job->sigint = 1;
4563 #endif
4564                 }
4565                 retval += 128;
4566         }
4567         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4568                 jobno(job), job->nprocs, status, retval));
4569         return retval;
4570 }
4571
4572 static int FAST_FUNC
4573 waitcmd(int argc UNUSED_PARAM, char **argv)
4574 {
4575         struct job *job;
4576         int retval;
4577         struct job *jp;
4578 #if BASH_WAIT_N
4579         int status;
4580         char one = nextopt("n");
4581 #else
4582         nextopt(nullstr);
4583 #endif
4584         retval = 0;
4585
4586         argv = argptr;
4587         if (!argv[0]) {
4588                 /* wait for all jobs / one job if -n */
4589                 for (;;) {
4590                         jp = curjob;
4591 #if BASH_WAIT_N
4592                         if (one && !jp)
4593                                 /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4594                                 retval = 127;
4595 #endif
4596                         while (1) {
4597                                 if (!jp) /* no running procs */
4598                                         goto ret;
4599                                 if (jp->state == JOBRUNNING)
4600                                         break;
4601                                 jp->waited = 1;
4602                                 jp = jp->prev_job;
4603                         }
4604         /* man bash:
4605          * "When bash is waiting for an asynchronous command via
4606          * the wait builtin, the reception of a signal for which a trap
4607          * has been set will cause the wait builtin to return immediately
4608          * with an exit status greater than 128, immediately after which
4609          * the trap is executed."
4610          */
4611 #if BASH_WAIT_N
4612                         status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4613 #else
4614                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4615 #endif
4616         /* if child sends us a signal *and immediately exits*,
4617          * dowait() returns pid > 0. Check this case,
4618          * not "if (dowait() < 0)"!
4619          */
4620                         if (pending_sig)
4621                                 goto sigout;
4622 #if BASH_WAIT_N
4623                         if (one) {
4624                                 /* wait -n waits for one _job_, not one _process_.
4625                                  *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4626                                  * should wait for 2 seconds. Not 1 or 3.
4627                                  */
4628                                 if (status != -1 && !WIFSTOPPED(status)) {
4629                                         retval = WEXITSTATUS(status);
4630                                         if (WIFSIGNALED(status))
4631                                                 retval = WTERMSIG(status) + 128;
4632                                         goto ret;
4633                                 }
4634                         }
4635 #endif
4636                 }
4637         }
4638
4639         retval = 127;
4640         do {
4641                 if (**argv != '%') {
4642                         pid_t pid = number(*argv);
4643                         job = curjob;
4644                         while (1) {
4645                                 if (!job)
4646                                         goto repeat;
4647                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4648                                         break;
4649                                 job = job->prev_job;
4650                         }
4651                 } else {
4652                         job = getjob(*argv, 0);
4653                 }
4654                 /* loop until process terminated or stopped */
4655                 while (job->state == JOBRUNNING) {
4656                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4657                         if (pending_sig)
4658                                 goto sigout;
4659                 }
4660                 job->waited = 1;
4661                 retval = getstatus(job);
4662  repeat: ;
4663         } while (*++argv);
4664
4665  ret:
4666         return retval;
4667  sigout:
4668         retval = 128 + pending_sig;
4669         return retval;
4670 }
4671
4672 static struct job *
4673 growjobtab(void)
4674 {
4675         size_t len;
4676         ptrdiff_t offset;
4677         struct job *jp, *jq;
4678
4679         len = njobs * sizeof(*jp);
4680         jq = jobtab;
4681         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4682
4683         offset = (char *)jp - (char *)jq;
4684         if (offset) {
4685                 /* Relocate pointers */
4686                 size_t l = len;
4687
4688                 jq = (struct job *)((char *)jq + l);
4689                 while (l) {
4690                         l -= sizeof(*jp);
4691                         jq--;
4692 #define joff(p) ((struct job *)((char *)(p) + l))
4693 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4694                         if (joff(jp)->ps == &jq->ps0)
4695                                 jmove(joff(jp)->ps);
4696                         if (joff(jp)->prev_job)
4697                                 jmove(joff(jp)->prev_job);
4698                 }
4699                 if (curjob)
4700                         jmove(curjob);
4701 #undef joff
4702 #undef jmove
4703         }
4704
4705         njobs += 4;
4706         jobtab = jp;
4707         jp = (struct job *)((char *)jp + len);
4708         jq = jp + 3;
4709         do {
4710                 jq->used = 0;
4711         } while (--jq >= jp);
4712         return jp;
4713 }
4714
4715 /*
4716  * Return a new job structure.
4717  * Called with interrupts off.
4718  */
4719 static struct job *
4720 makejob(/*union node *node,*/ int nprocs)
4721 {
4722         int i;
4723         struct job *jp;
4724
4725         for (i = njobs, jp = jobtab; ; jp++) {
4726                 if (--i < 0) {
4727                         jp = growjobtab();
4728                         break;
4729                 }
4730                 if (jp->used == 0)
4731                         break;
4732                 if (jp->state != JOBDONE || !jp->waited)
4733                         continue;
4734 #if JOBS
4735                 if (doing_jobctl)
4736                         continue;
4737 #endif
4738                 freejob(jp);
4739                 break;
4740         }
4741         memset(jp, 0, sizeof(*jp));
4742 #if JOBS
4743         /* jp->jobctl is a bitfield.
4744          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4745         if (doing_jobctl)
4746                 jp->jobctl = 1;
4747 #endif
4748         jp->prev_job = curjob;
4749         curjob = jp;
4750         jp->used = 1;
4751         jp->ps = &jp->ps0;
4752         if (nprocs > 1) {
4753                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4754         }
4755         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4756                                 jobno(jp)));
4757         return jp;
4758 }
4759
4760 #if JOBS
4761 /*
4762  * Return a string identifying a command (to be printed by the
4763  * jobs command).
4764  */
4765 static char *cmdnextc;
4766
4767 static void
4768 cmdputs(const char *s)
4769 {
4770         static const char vstype[VSTYPE + 1][3] = {
4771                 "", "}", "-", "+", "?", "=",
4772                 "%", "%%", "#", "##"
4773                 IF_BASH_SUBSTR(, ":")
4774                 IF_BASH_PATTERN_SUBST(, "/", "//")
4775         };
4776
4777         const char *p, *str;
4778         char cc[2];
4779         char *nextc;
4780         unsigned char c;
4781         unsigned char subtype = 0;
4782         int quoted = 0;
4783
4784         cc[1] = '\0';
4785         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4786         p = s;
4787         while ((c = *p++) != '\0') {
4788                 str = NULL;
4789                 switch (c) {
4790                 case CTLESC:
4791                         c = *p++;
4792                         break;
4793                 case CTLVAR:
4794                         subtype = *p++;
4795                         if ((subtype & VSTYPE) == VSLENGTH)
4796                                 str = "${#";
4797                         else
4798                                 str = "${";
4799                         goto dostr;
4800                 case CTLENDVAR:
4801                         str = "\"}";
4802                         str += !(quoted & 1);
4803                         quoted >>= 1;
4804                         subtype = 0;
4805                         goto dostr;
4806                 case CTLBACKQ:
4807                         str = "$(...)";
4808                         goto dostr;
4809 #if ENABLE_FEATURE_SH_MATH
4810                 case CTLARI:
4811                         str = "$((";
4812                         goto dostr;
4813                 case CTLENDARI:
4814                         str = "))";
4815                         goto dostr;
4816 #endif
4817                 case CTLQUOTEMARK:
4818                         quoted ^= 1;
4819                         c = '"';
4820                         break;
4821                 case '=':
4822                         if (subtype == 0)
4823                                 break;
4824                         if ((subtype & VSTYPE) != VSNORMAL)
4825                                 quoted <<= 1;
4826                         str = vstype[subtype & VSTYPE];
4827                         if (subtype & VSNUL)
4828                                 c = ':';
4829                         else
4830                                 goto checkstr;
4831                         break;
4832                 case '\'':
4833                 case '\\':
4834                 case '"':
4835                 case '$':
4836                         /* These can only happen inside quotes */
4837                         cc[0] = c;
4838                         str = cc;
4839 //FIXME:
4840 // $ true $$ &
4841 // $ <cr>
4842 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4843                         c = '\\';
4844                         break;
4845                 default:
4846                         break;
4847                 }
4848                 USTPUTC(c, nextc);
4849  checkstr:
4850                 if (!str)
4851                         continue;
4852  dostr:
4853                 while ((c = *str++) != '\0') {
4854                         USTPUTC(c, nextc);
4855                 }
4856         } /* while *p++ not NUL */
4857
4858         if (quoted & 1) {
4859                 USTPUTC('"', nextc);
4860         }
4861         *nextc = 0;
4862         cmdnextc = nextc;
4863 }
4864
4865 /* cmdtxt() and cmdlist() call each other */
4866 static void cmdtxt(union node *n);
4867
4868 static void
4869 cmdlist(union node *np, int sep)
4870 {
4871         for (; np; np = np->narg.next) {
4872                 if (!sep)
4873                         cmdputs(" ");
4874                 cmdtxt(np);
4875                 if (sep && np->narg.next)
4876                         cmdputs(" ");
4877         }
4878 }
4879
4880 static void
4881 cmdtxt(union node *n)
4882 {
4883         union node *np;
4884         struct nodelist *lp;
4885         const char *p;
4886
4887         if (!n)
4888                 return;
4889         switch (n->type) {
4890         default:
4891 #if DEBUG
4892                 abort();
4893 #endif
4894         case NPIPE:
4895                 lp = n->npipe.cmdlist;
4896                 for (;;) {
4897                         cmdtxt(lp->n);
4898                         lp = lp->next;
4899                         if (!lp)
4900                                 break;
4901                         cmdputs(" | ");
4902                 }
4903                 break;
4904         case NSEMI:
4905                 p = "; ";
4906                 goto binop;
4907         case NAND:
4908                 p = " && ";
4909                 goto binop;
4910         case NOR:
4911                 p = " || ";
4912  binop:
4913                 cmdtxt(n->nbinary.ch1);
4914                 cmdputs(p);
4915                 n = n->nbinary.ch2;
4916                 goto donode;
4917         case NREDIR:
4918         case NBACKGND:
4919                 n = n->nredir.n;
4920                 goto donode;
4921         case NNOT:
4922                 cmdputs("!");
4923                 n = n->nnot.com;
4924  donode:
4925                 cmdtxt(n);
4926                 break;
4927         case NIF:
4928                 cmdputs("if ");
4929                 cmdtxt(n->nif.test);
4930                 cmdputs("; then ");
4931                 if (n->nif.elsepart) {
4932                         cmdtxt(n->nif.ifpart);
4933                         cmdputs("; else ");
4934                         n = n->nif.elsepart;
4935                 } else {
4936                         n = n->nif.ifpart;
4937                 }
4938                 p = "; fi";
4939                 goto dotail;
4940         case NSUBSHELL:
4941                 cmdputs("(");
4942                 n = n->nredir.n;
4943                 p = ")";
4944                 goto dotail;
4945         case NWHILE:
4946                 p = "while ";
4947                 goto until;
4948         case NUNTIL:
4949                 p = "until ";
4950  until:
4951                 cmdputs(p);
4952                 cmdtxt(n->nbinary.ch1);
4953                 n = n->nbinary.ch2;
4954                 p = "; done";
4955  dodo:
4956                 cmdputs("; do ");
4957  dotail:
4958                 cmdtxt(n);
4959                 goto dotail2;
4960         case NFOR:
4961                 cmdputs("for ");
4962                 cmdputs(n->nfor.var);
4963                 cmdputs(" in ");
4964                 cmdlist(n->nfor.args, 1);
4965                 n = n->nfor.body;
4966                 p = "; done";
4967                 goto dodo;
4968         case NDEFUN:
4969                 cmdputs(n->ndefun.text);
4970                 p = "() { ... }";
4971                 goto dotail2;
4972         case NCMD:
4973                 cmdlist(n->ncmd.args, 1);
4974                 cmdlist(n->ncmd.redirect, 0);
4975                 break;
4976         case NARG:
4977                 p = n->narg.text;
4978  dotail2:
4979                 cmdputs(p);
4980                 break;
4981         case NHERE:
4982         case NXHERE:
4983                 p = "<<...";
4984                 goto dotail2;
4985         case NCASE:
4986                 cmdputs("case ");
4987                 cmdputs(n->ncase.expr->narg.text);
4988                 cmdputs(" in ");
4989                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4990                         cmdtxt(np->nclist.pattern);
4991                         cmdputs(") ");
4992                         cmdtxt(np->nclist.body);
4993                         cmdputs(";; ");
4994                 }
4995                 p = "esac";
4996                 goto dotail2;
4997         case NTO:
4998                 p = ">";
4999                 goto redir;
5000         case NCLOBBER:
5001                 p = ">|";
5002                 goto redir;
5003         case NAPPEND:
5004                 p = ">>";
5005                 goto redir;
5006 #if BASH_REDIR_OUTPUT
5007         case NTO2:
5008 #endif
5009         case NTOFD:
5010                 p = ">&";
5011                 goto redir;
5012         case NFROM:
5013                 p = "<";
5014                 goto redir;
5015         case NFROMFD:
5016                 p = "<&";
5017                 goto redir;
5018         case NFROMTO:
5019                 p = "<>";
5020  redir:
5021                 cmdputs(utoa(n->nfile.fd));
5022                 cmdputs(p);
5023                 if (n->type == NTOFD || n->type == NFROMFD) {
5024                         if (n->ndup.dupfd >= 0)
5025                                 cmdputs(utoa(n->ndup.dupfd));
5026                         else
5027                                 cmdputs("-");
5028                         break;
5029                 }
5030                 n = n->nfile.fname;
5031                 goto donode;
5032         }
5033 }
5034
5035 static char *
5036 commandtext(union node *n)
5037 {
5038         char *name;
5039
5040         STARTSTACKSTR(cmdnextc);
5041         cmdtxt(n);
5042         name = stackblock();
5043         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5044         return ckstrdup(name);
5045 }
5046 #endif /* JOBS */
5047
5048 /*
5049  * Fork off a subshell.  If we are doing job control, give the subshell its
5050  * own process group.  Jp is a job structure that the job is to be added to.
5051  * N is the command that will be evaluated by the child.  Both jp and n may
5052  * be NULL.  The mode parameter can be one of the following:
5053  *      FORK_FG - Fork off a foreground process.
5054  *      FORK_BG - Fork off a background process.
5055  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5056  *                   process group even if job control is on.
5057  *
5058  * When job control is turned off, background processes have their standard
5059  * input redirected to /dev/null (except for the second and later processes
5060  * in a pipeline).
5061  *
5062  * Called with interrupts off.
5063  */
5064 /*
5065  * Clear traps on a fork.
5066  */
5067 static void
5068 clear_traps(void)
5069 {
5070         char **tp;
5071
5072         INT_OFF;
5073         for (tp = trap; tp < &trap[NSIG]; tp++) {
5074                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5075                         if (trap_ptr == trap)
5076                                 free(*tp);
5077                         /* else: it "belongs" to trap_ptr vector, don't free */
5078                         *tp = NULL;
5079                         if ((tp - trap) != 0)
5080                                 setsignal(tp - trap);
5081                 }
5082         }
5083         may_have_traps = 0;
5084         INT_ON;
5085 }
5086
5087 /* Lives far away from here, needed for forkchild */
5088 static void closescript(void);
5089
5090 /* Called after fork(), in child */
5091 /* jp and n are NULL when called by openhere() for heredoc support */
5092 static NOINLINE void
5093 forkchild(struct job *jp, union node *n, int mode)
5094 {
5095         int oldlvl;
5096
5097         TRACE(("Child shell %d\n", getpid()));
5098         oldlvl = shlvl;
5099         shlvl++;
5100
5101         /* man bash: "Non-builtin commands run by bash have signal handlers
5102          * set to the values inherited by the shell from its parent".
5103          * Do we do it correctly? */
5104
5105         closescript();
5106
5107         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5108          && n && n->type == NCMD        /* is it single cmd? */
5109         /* && n->ncmd.args->type == NARG - always true? */
5110          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5111          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5112         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5113         ) {
5114                 TRACE(("Trap hack\n"));
5115                 /* Awful hack for `trap` or $(trap).
5116                  *
5117                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5118                  * contains an example where "trap" is executed in a subshell:
5119                  *
5120                  * save_traps=$(trap)
5121                  * ...
5122                  * eval "$save_traps"
5123                  *
5124                  * Standard does not say that "trap" in subshell shall print
5125                  * parent shell's traps. It only says that its output
5126                  * must have suitable form, but then, in the above example
5127                  * (which is not supposed to be normative), it implies that.
5128                  *
5129                  * bash (and probably other shell) does implement it
5130                  * (traps are reset to defaults, but "trap" still shows them),
5131                  * but as a result, "trap" logic is hopelessly messed up:
5132                  *
5133                  * # trap
5134                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5135                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5136                  * # true | trap   <--- trap is in subshell - no output (ditto)
5137                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5138                  * trap -- 'echo Ho' SIGWINCH
5139                  * # echo `(trap)`         <--- in subshell in subshell - output
5140                  * trap -- 'echo Ho' SIGWINCH
5141                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5142                  * trap -- 'echo Ho' SIGWINCH
5143                  *
5144                  * The rules when to forget and when to not forget traps
5145                  * get really complex and nonsensical.
5146                  *
5147                  * Our solution: ONLY bare $(trap) or `trap` is special.
5148                  */
5149                 /* Save trap handler strings for trap builtin to print */
5150                 trap_ptr = xmemdup(trap, sizeof(trap));
5151                 /* Fall through into clearing traps */
5152         }
5153         clear_traps();
5154 #if JOBS
5155         /* do job control only in root shell */
5156         doing_jobctl = 0;
5157         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5158                 pid_t pgrp;
5159
5160                 if (jp->nprocs == 0)
5161                         pgrp = getpid();
5162                 else
5163                         pgrp = jp->ps[0].ps_pid;
5164                 /* this can fail because we are doing it in the parent also */
5165                 setpgid(0, pgrp);
5166                 if (mode == FORK_FG)
5167                         xtcsetpgrp(ttyfd, pgrp);
5168                 setsignal(SIGTSTP);
5169                 setsignal(SIGTTOU);
5170         } else
5171 #endif
5172         if (mode == FORK_BG) {
5173                 /* man bash: "When job control is not in effect,
5174                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5175                 ignoresig(SIGINT);
5176                 ignoresig(SIGQUIT);
5177                 if (jp->nprocs == 0) {
5178                         close(0);
5179                         if (open(bb_dev_null, O_RDONLY) != 0)
5180                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5181                 }
5182         }
5183         if (oldlvl == 0) {
5184                 if (iflag) { /* why if iflag only? */
5185                         setsignal(SIGINT);
5186                         setsignal(SIGTERM);
5187                 }
5188                 /* man bash:
5189                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5190                  * commands run by bash have signal handlers
5191                  * set to the values inherited by the shell
5192                  * from its parent".
5193                  * Take care of the second rule: */
5194                 setsignal(SIGQUIT);
5195         }
5196 #if JOBS
5197         if (n && n->type == NCMD
5198          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5199         ) {
5200                 TRACE(("Job hack\n"));
5201                 /* "jobs": we do not want to clear job list for it,
5202                  * instead we remove only _its_ own_ job from job list.
5203                  * This makes "jobs .... | cat" more useful.
5204                  */
5205                 freejob(curjob);
5206                 return;
5207         }
5208 #endif
5209         for (jp = curjob; jp; jp = jp->prev_job)
5210                 freejob(jp);
5211         jobless = 0;
5212 }
5213
5214 /* Called after fork(), in parent */
5215 #if !JOBS
5216 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5217 #endif
5218 static void
5219 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5220 {
5221         TRACE(("In parent shell: child = %d\n", pid));
5222         if (!jp) {
5223                 /* jp is NULL when called by openhere() for heredoc support */
5224                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5225                         continue;
5226                 jobless++;
5227                 return;
5228         }
5229 #if JOBS
5230         if (mode != FORK_NOJOB && jp->jobctl) {
5231                 int pgrp;
5232
5233                 if (jp->nprocs == 0)
5234                         pgrp = pid;
5235                 else
5236                         pgrp = jp->ps[0].ps_pid;
5237                 /* This can fail because we are doing it in the child also */
5238                 setpgid(pid, pgrp);
5239         }
5240 #endif
5241         if (mode == FORK_BG) {
5242                 backgndpid = pid;               /* set $! */
5243                 set_curjob(jp, CUR_RUNNING);
5244         }
5245         if (jp) {
5246                 struct procstat *ps = &jp->ps[jp->nprocs++];
5247                 ps->ps_pid = pid;
5248                 ps->ps_status = -1;
5249                 ps->ps_cmd = nullstr;
5250 #if JOBS
5251                 if (doing_jobctl && n)
5252                         ps->ps_cmd = commandtext(n);
5253 #endif
5254         }
5255 }
5256
5257 /* jp and n are NULL when called by openhere() for heredoc support */
5258 static int
5259 forkshell(struct job *jp, union node *n, int mode)
5260 {
5261         int pid;
5262
5263         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5264         pid = fork();
5265         if (pid < 0) {
5266                 TRACE(("Fork failed, errno=%d", errno));
5267                 if (jp)
5268                         freejob(jp);
5269                 ash_msg_and_raise_perror("can't fork");
5270         }
5271         if (pid == 0) {
5272                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5273                 forkchild(jp, n, mode);
5274         } else {
5275                 forkparent(jp, n, mode, pid);
5276         }
5277         return pid;
5278 }
5279
5280 /*
5281  * Wait for job to finish.
5282  *
5283  * Under job control we have the problem that while a child process
5284  * is running interrupts generated by the user are sent to the child
5285  * but not to the shell.  This means that an infinite loop started by
5286  * an interactive user may be hard to kill.  With job control turned off,
5287  * an interactive user may place an interactive program inside a loop.
5288  * If the interactive program catches interrupts, the user doesn't want
5289  * these interrupts to also abort the loop.  The approach we take here
5290  * is to have the shell ignore interrupt signals while waiting for a
5291  * foreground process to terminate, and then send itself an interrupt
5292  * signal if the child process was terminated by an interrupt signal.
5293  * Unfortunately, some programs want to do a bit of cleanup and then
5294  * exit on interrupt; unless these processes terminate themselves by
5295  * sending a signal to themselves (instead of calling exit) they will
5296  * confuse this approach.
5297  *
5298  * Called with interrupts off.
5299  */
5300 static int
5301 waitforjob(struct job *jp)
5302 {
5303         int st;
5304
5305         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5306
5307         INT_OFF;
5308         while (jp->state == JOBRUNNING) {
5309                 /* In non-interactive shells, we _can_ get
5310                  * a keyboard signal here and be EINTRed,
5311                  * but we just loop back, waiting for command to complete.
5312                  *
5313                  * man bash:
5314                  * "If bash is waiting for a command to complete and receives
5315                  * a signal for which a trap has been set, the trap
5316                  * will not be executed until the command completes."
5317                  *
5318                  * Reality is that even if trap is not set, bash
5319                  * will not act on the signal until command completes.
5320                  * Try this. sleep5intoff.c:
5321                  * #include <signal.h>
5322                  * #include <unistd.h>
5323                  * int main() {
5324                  *         sigset_t set;
5325                  *         sigemptyset(&set);
5326                  *         sigaddset(&set, SIGINT);
5327                  *         sigaddset(&set, SIGQUIT);
5328                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5329                  *         sleep(5);
5330                  *         return 0;
5331                  * }
5332                  * $ bash -c './sleep5intoff; echo hi'
5333                  * ^C^C^C^C <--- pressing ^C once a second
5334                  * $ _
5335                  * $ bash -c './sleep5intoff; echo hi'
5336                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5337                  * $ _
5338                  */
5339                 dowait(DOWAIT_BLOCK, jp);
5340         }
5341         INT_ON;
5342
5343         st = getstatus(jp);
5344 #if JOBS
5345         if (jp->jobctl) {
5346                 xtcsetpgrp(ttyfd, rootpid);
5347                 restore_tty_if_stopped_or_signaled(jp);
5348
5349                 /*
5350                  * This is truly gross.
5351                  * If we're doing job control, then we did a TIOCSPGRP which
5352                  * caused us (the shell) to no longer be in the controlling
5353                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5354                  * intuit from the subprocess exit status whether a SIGINT
5355                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5356                  */
5357                 if (jp->sigint) /* TODO: do the same with all signals */
5358                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5359         }
5360         if (jp->state == JOBDONE)
5361 #endif
5362                 freejob(jp);
5363         return st;
5364 }
5365
5366 /*
5367  * return 1 if there are stopped jobs, otherwise 0
5368  */
5369 static int
5370 stoppedjobs(void)
5371 {
5372         struct job *jp;
5373         int retval;
5374
5375         retval = 0;
5376         if (job_warning)
5377                 goto out;
5378         jp = curjob;
5379         if (jp && jp->state == JOBSTOPPED) {
5380                 out2str("You have stopped jobs.\n");
5381                 job_warning = 2;
5382                 retval++;
5383         }
5384  out:
5385         return retval;
5386 }
5387
5388
5389 /*
5390  * Code for dealing with input/output redirection.
5391  */
5392
5393 #undef EMPTY
5394 #undef CLOSED
5395 #define EMPTY -2                /* marks an unused slot in redirtab */
5396 #define CLOSED -1               /* marks a slot of previously-closed fd */
5397
5398 /*
5399  * Handle here documents.  Normally we fork off a process to write the
5400  * data to a pipe.  If the document is short, we can stuff the data in
5401  * the pipe without forking.
5402  */
5403 /* openhere needs this forward reference */
5404 static void expandhere(union node *arg, int fd);
5405 static int
5406 openhere(union node *redir)
5407 {
5408         int pip[2];
5409         size_t len = 0;
5410
5411         if (pipe(pip) < 0)
5412                 ash_msg_and_raise_perror("can't create pipe");
5413         if (redir->type == NHERE) {
5414                 len = strlen(redir->nhere.doc->narg.text);
5415                 if (len <= PIPE_BUF) {
5416                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5417                         goto out;
5418                 }
5419         }
5420         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5421                 /* child */
5422                 close(pip[0]);
5423                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5424                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5425                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5426                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5427                 signal(SIGPIPE, SIG_DFL);
5428                 if (redir->type == NHERE)
5429                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5430                 else /* NXHERE */
5431                         expandhere(redir->nhere.doc, pip[1]);
5432                 _exit(EXIT_SUCCESS);
5433         }
5434  out:
5435         close(pip[1]);
5436         return pip[0];
5437 }
5438
5439 static int
5440 openredirect(union node *redir)
5441 {
5442         struct stat sb;
5443         char *fname;
5444         int f;
5445
5446         switch (redir->nfile.type) {
5447 /* Can't happen, our single caller does this itself */
5448 //      case NTOFD:
5449 //      case NFROMFD:
5450 //              return -1;
5451         case NHERE:
5452         case NXHERE:
5453                 return openhere(redir);
5454         }
5455
5456         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5457          * allocated space. Do it only when we know it is safe.
5458          */
5459         fname = redir->nfile.expfname;
5460
5461         switch (redir->nfile.type) {
5462         default:
5463 #if DEBUG
5464                 abort();
5465 #endif
5466         case NFROM:
5467                 f = open(fname, O_RDONLY);
5468                 if (f < 0)
5469                         goto eopen;
5470                 break;
5471         case NFROMTO:
5472                 f = open(fname, O_RDWR|O_CREAT, 0666);
5473                 if (f < 0)
5474                         goto ecreate;
5475                 break;
5476         case NTO:
5477 #if BASH_REDIR_OUTPUT
5478         case NTO2:
5479 #endif
5480                 /* Take care of noclobber mode. */
5481                 if (Cflag) {
5482                         if (stat(fname, &sb) < 0) {
5483                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5484                                 if (f < 0)
5485                                         goto ecreate;
5486                         } else if (!S_ISREG(sb.st_mode)) {
5487                                 f = open(fname, O_WRONLY, 0666);
5488                                 if (f < 0)
5489                                         goto ecreate;
5490                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5491                                         close(f);
5492                                         errno = EEXIST;
5493                                         goto ecreate;
5494                                 }
5495                         } else {
5496                                 errno = EEXIST;
5497                                 goto ecreate;
5498                         }
5499                         break;
5500                 }
5501                 /* FALLTHROUGH */
5502         case NCLOBBER:
5503                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5504                 if (f < 0)
5505                         goto ecreate;
5506                 break;
5507         case NAPPEND:
5508                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5509                 if (f < 0)
5510                         goto ecreate;
5511                 break;
5512         }
5513
5514         return f;
5515  ecreate:
5516         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5517  eopen:
5518         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5519 }
5520
5521 /*
5522  * Copy a file descriptor to be >= 10. Throws exception on error.
5523  */
5524 static int
5525 savefd(int from)
5526 {
5527         int newfd;
5528         int err;
5529
5530         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5531         err = newfd < 0 ? errno : 0;
5532         if (err != EBADF) {
5533                 if (err)
5534                         ash_msg_and_raise_perror("%d", from);
5535                 close(from);
5536                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5537                         close_on_exec_on(newfd);
5538         }
5539
5540         return newfd;
5541 }
5542 static int
5543 dup2_or_raise(int from, int to)
5544 {
5545         int newfd;
5546
5547         newfd = (from != to) ? dup2(from, to) : to;
5548         if (newfd < 0) {
5549                 /* Happens when source fd is not open: try "echo >&99" */
5550                 ash_msg_and_raise_perror("%d", from);
5551         }
5552         return newfd;
5553 }
5554 static int
5555 dup_CLOEXEC(int fd, int avoid_fd)
5556 {
5557         int newfd;
5558  repeat:
5559         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5560         if (newfd >= 0) {
5561                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5562                         close_on_exec_on(newfd);
5563         } else { /* newfd < 0 */
5564                 if (errno == EBUSY)
5565                         goto repeat;
5566                 if (errno == EINTR)
5567                         goto repeat;
5568         }
5569         return newfd;
5570 }
5571 static int
5572 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5573 {
5574         int newfd;
5575  repeat:
5576         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5577         if (newfd < 0) {
5578                 if (errno == EBUSY)
5579                         goto repeat;
5580                 if (errno == EINTR)
5581                         goto repeat;
5582                 /* fd was not open? */
5583                 if (errno == EBADF)
5584                         return fd;
5585                 ash_msg_and_raise_perror("%d", newfd);
5586         }
5587         if (F_DUPFD_CLOEXEC == F_DUPFD)
5588                 close_on_exec_on(newfd);
5589         close(fd);
5590         return newfd;
5591 }
5592
5593 /* Struct def and variable are moved down to the first usage site */
5594 struct squirrel {
5595         int orig_fd;
5596         int moved_to;
5597 };
5598 struct redirtab {
5599         struct redirtab *next;
5600         int pair_count;
5601         struct squirrel two_fd[];
5602 };
5603 #define redirlist (G_var.redirlist)
5604
5605 static void
5606 add_squirrel_closed(struct redirtab *sq, int fd)
5607 {
5608         int i;
5609
5610         if (!sq)
5611                 return;
5612
5613         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5614                 /* If we collide with an already moved fd... */
5615                 if (fd == sq->two_fd[i].orig_fd) {
5616                         /* Examples:
5617                          * "echo 3>FILE 3>&- 3>FILE"
5618                          * "echo 3>&- 3>FILE"
5619                          * No need for last redirect to insert
5620                          * another "need to close 3" indicator.
5621                          */
5622                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5623                         return;
5624                 }
5625         }
5626         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5627         sq->two_fd[i].orig_fd = fd;
5628         sq->two_fd[i].moved_to = CLOSED;
5629 }
5630
5631 static int
5632 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5633 {
5634         int i, new_fd;
5635
5636         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5637                 avoid_fd = 9;
5638
5639 #if JOBS
5640         if (fd == ttyfd) {
5641                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5642                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5643                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5644                 return 1; /* "we closed fd" */
5645         }
5646 #endif
5647         /* Are we called from redirect(0)? E.g. redirect
5648          * in a forked child. No need to save fds,
5649          * we aren't going to use them anymore, ok to trash.
5650          */
5651         if (!sq)
5652                 return 0;
5653
5654         /* If this one of script's fds? */
5655         if (fd != 0) {
5656                 struct parsefile *pf = g_parsefile;
5657                 while (pf) {
5658                         /* We skip fd == 0 case because of the following:
5659                          * $ ash  # running ash interactively
5660                          * $ . ./script.sh
5661                          * and in script.sh: "exec 9>&0".
5662                          * Even though top-level pf_fd _is_ 0,
5663                          * it's still ok to use it: "read" builtin uses it,
5664                          * why should we cripple "exec" builtin?
5665                          */
5666                         if (fd == pf->pf_fd) {
5667                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5668                                 return 1; /* "we closed fd" */
5669                         }
5670                         pf = pf->prev;
5671                 }
5672         }
5673
5674         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5675
5676         /* First: do we collide with some already moved fds? */
5677         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5678                 /* If we collide with an already moved fd... */
5679                 if (fd == sq->two_fd[i].moved_to) {
5680                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5681                         sq->two_fd[i].moved_to = new_fd;
5682                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5683                         if (new_fd < 0) /* what? */
5684                                 xfunc_die();
5685                         return 0; /* "we did not close fd" */
5686                 }
5687                 if (fd == sq->two_fd[i].orig_fd) {
5688                         /* Example: echo Hello >/dev/null 1>&2 */
5689                         TRACE(("redirect_fd %d: already moved\n", fd));
5690                         return 0; /* "we did not close fd" */
5691                 }
5692         }
5693
5694         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5695         new_fd = dup_CLOEXEC(fd, avoid_fd);
5696         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5697         if (new_fd < 0) {
5698                 if (errno != EBADF)
5699                         xfunc_die();
5700                 /* new_fd = CLOSED; - already is -1 */
5701         }
5702         sq->two_fd[i].moved_to = new_fd;
5703         sq->two_fd[i].orig_fd = fd;
5704
5705         /* if we move stderr, let "set -x" code know */
5706         if (fd == preverrout_fd)
5707                 preverrout_fd = new_fd;
5708
5709         return 0; /* "we did not close fd" */
5710 }
5711
5712 static int
5713 internally_opened_fd(int fd, struct redirtab *sq)
5714 {
5715         int i;
5716 #if JOBS
5717         if (fd == ttyfd)
5718                 return 1;
5719 #endif
5720         /* If this one of script's fds? */
5721         if (fd != 0) {
5722                 struct parsefile *pf = g_parsefile;
5723                 while (pf) {
5724                         if (fd == pf->pf_fd)
5725                                 return 1;
5726                         pf = pf->prev;
5727                 }
5728         }
5729
5730         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5731                 if (fd == sq->two_fd[i].moved_to)
5732                         return 1;
5733         }
5734         return 0;
5735 }
5736
5737 /*
5738  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5739  * old file descriptors are stashed away so that the redirection can be
5740  * undone by calling popredir.
5741  */
5742 /* flags passed to redirect */
5743 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5744 static void
5745 redirect(union node *redir, int flags)
5746 {
5747         struct redirtab *sv;
5748
5749         if (!redir)
5750                 return;
5751
5752         sv = NULL;
5753         INT_OFF;
5754         if (flags & REDIR_PUSH)
5755                 sv = redirlist;
5756         do {
5757                 int fd;
5758                 int newfd;
5759                 int close_fd;
5760                 int closed;
5761
5762                 fd = redir->nfile.fd;
5763                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5764                         //bb_error_msg("doing %d > %d", fd, newfd);
5765                         newfd = redir->ndup.dupfd;
5766                         close_fd = -1;
5767                 } else {
5768                         newfd = openredirect(redir); /* always >= 0 */
5769                         if (fd == newfd) {
5770                                 /* open() gave us precisely the fd we wanted.
5771                                  * This means that this fd was not busy
5772                                  * (not opened to anywhere).
5773                                  * Remember to close it on restore:
5774                                  */
5775                                 add_squirrel_closed(sv, fd);
5776                                 continue;
5777                         }
5778                         close_fd = newfd;
5779                 }
5780
5781                 if (fd == newfd)
5782                         continue;
5783
5784                 /* if "N>FILE": move newfd to fd */
5785                 /* if "N>&M": dup newfd to fd */
5786                 /* if "N>&-": close fd (newfd is -1) */
5787
5788  IF_BASH_REDIR_OUTPUT(redirect_more:)
5789
5790                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5791                 if (newfd == -1) {
5792                         /* "N>&-" means "close me" */
5793                         if (!closed) {
5794                                 /* ^^^ optimization: saving may already
5795                                  * have closed it. If not... */
5796                                 close(fd);
5797                         }
5798                 } else {
5799                         /* if newfd is a script fd or saved fd, simulate EBADF */
5800                         if (internally_opened_fd(newfd, sv)) {
5801                                 errno = EBADF;
5802                                 ash_msg_and_raise_perror("%d", newfd);
5803                         }
5804                         dup2_or_raise(newfd, fd);
5805                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5806                                 close(close_fd);
5807 #if BASH_REDIR_OUTPUT
5808                         if (redir->nfile.type == NTO2 && fd == 1) {
5809                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5810                                 fd = 2;
5811                                 newfd = 1;
5812                                 close_fd = -1;
5813                                 goto redirect_more;
5814                         }
5815 #endif
5816                 }
5817         } while ((redir = redir->nfile.next) != NULL);
5818         INT_ON;
5819
5820 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5821 #define REDIR_SAVEFD2 0
5822         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5823         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5824         // not only for calls with flags containing REDIR_SAVEFD2.
5825         // We do this unconditionally (see save_fd_on_redirect()).
5826         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5827         //      preverrout_fd = copied_fd2;
5828 }
5829
5830 static int
5831 redirectsafe(union node *redir, int flags)
5832 {
5833         int err;
5834         volatile int saveint;
5835         struct jmploc *volatile savehandler = exception_handler;
5836         struct jmploc jmploc;
5837
5838         SAVE_INT(saveint);
5839         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5840         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5841         if (!err) {
5842                 exception_handler = &jmploc;
5843                 redirect(redir, flags);
5844         }
5845         exception_handler = savehandler;
5846         if (err && exception_type != EXERROR)
5847                 longjmp(exception_handler->loc, 1);
5848         RESTORE_INT(saveint);
5849         return err;
5850 }
5851
5852 static struct redirtab*
5853 pushredir(union node *redir)
5854 {
5855         struct redirtab *sv;
5856         int i;
5857
5858         if (!redir)
5859                 return redirlist;
5860
5861         i = 0;
5862         do {
5863                 i++;
5864 #if BASH_REDIR_OUTPUT
5865                 if (redir->nfile.type == NTO2)
5866                         i++;
5867 #endif
5868                 redir = redir->nfile.next;
5869         } while (redir);
5870
5871         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5872         sv->pair_count = i;
5873         while (--i >= 0)
5874                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5875         sv->next = redirlist;
5876         redirlist = sv;
5877         return sv->next;
5878 }
5879
5880 /*
5881  * Undo the effects of the last redirection.
5882  */
5883 static void
5884 popredir(int drop)
5885 {
5886         struct redirtab *rp;
5887         int i;
5888
5889         if (redirlist == NULL)
5890                 return;
5891         INT_OFF;
5892         rp = redirlist;
5893         for (i = 0; i < rp->pair_count; i++) {
5894                 int fd = rp->two_fd[i].orig_fd;
5895                 int copy = rp->two_fd[i].moved_to;
5896                 if (copy == CLOSED) {
5897                         if (!drop)
5898                                 close(fd);
5899                         continue;
5900                 }
5901                 if (copy != EMPTY) {
5902                         if (!drop) {
5903                                 /*close(fd);*/
5904                                 dup2_or_raise(copy, fd);
5905                         }
5906                         close(copy);
5907                 }
5908         }
5909         redirlist = rp->next;
5910         free(rp);
5911         INT_ON;
5912 }
5913
5914 static void
5915 unwindredir(struct redirtab *stop)
5916 {
5917         while (redirlist != stop)
5918                 popredir(/*drop:*/ 0);
5919 }
5920
5921
5922 /* ============ Routines to expand arguments to commands
5923  *
5924  * We have to deal with backquotes, shell variables, and file metacharacters.
5925  */
5926
5927 #if ENABLE_FEATURE_SH_MATH
5928 static arith_t
5929 ash_arith(const char *s)
5930 {
5931         arith_state_t math_state;
5932         arith_t result;
5933
5934         math_state.lookupvar = lookupvar;
5935         math_state.setvar    = setvar0;
5936         //math_state.endofname = endofname;
5937
5938         INT_OFF;
5939         result = arith(&math_state, s);
5940         if (math_state.errmsg)
5941                 ash_msg_and_raise_error(math_state.errmsg);
5942         INT_ON;
5943
5944         return result;
5945 }
5946 #endif
5947 #if BASH_SUBSTR
5948 # if ENABLE_FEATURE_SH_MATH
5949 static int substr_atoi(const char *s)
5950 {
5951         arith_t t = ash_arith(s);
5952         if (sizeof(t) > sizeof(int)) {
5953                 /* clamp very large or very large negative nums for ${v:N:M}:
5954                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5955                  */
5956                 if (t > INT_MAX)
5957                         t = INT_MAX;
5958                 if (t < INT_MIN)
5959                         t = INT_MIN;
5960         }
5961         return t;
5962 }
5963 # else
5964 #  define substr_atoi(s) number(s)
5965 # endif
5966 #endif
5967
5968 /*
5969  * expandarg flags
5970  */
5971 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5972 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5973 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5974 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5975 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5976  * POSIX says for this case:
5977  *  Pathname expansion shall not be performed on the word by a
5978  *  non-interactive shell; an interactive shell may perform it, but shall
5979  *  do so only when the expansion would result in one word.
5980  * Currently, our code complies to the above rule by never globbing
5981  * redirection filenames.
5982  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5983  * (this means that on a typical Linux distro, bash almost always
5984  * performs globbing, and thus diverges from what we do).
5985  */
5986 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5987 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5988 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5989 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5990 /*
5991  * rmescape() flags
5992  */
5993 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5994 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5995 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5996 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5997
5998 /* Add CTLESC when necessary. */
5999 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
6000 /* Do not skip NUL characters. */
6001 #define QUOTES_KEEPNUL EXP_TILDE
6002
6003 /*
6004  * Structure specifying which parts of the string should be searched
6005  * for IFS characters.
6006  */
6007 struct ifsregion {
6008         struct ifsregion *next; /* next region in list */
6009         int begoff;             /* offset of start of region */
6010         int endoff;             /* offset of end of region */
6011         int nulonly;            /* search for nul bytes only */
6012 };
6013
6014 struct arglist {
6015         struct strlist *list;
6016         struct strlist **lastp;
6017 };
6018
6019 /* output of current string */
6020 static char *expdest;
6021 /* list of back quote expressions */
6022 static struct nodelist *argbackq;
6023 /* first struct in list of ifs regions */
6024 static struct ifsregion ifsfirst;
6025 /* last struct in list */
6026 static struct ifsregion *ifslastp;
6027 /* holds expanded arg list */
6028 static struct arglist exparg;
6029
6030 /*
6031  * Our own itoa().
6032  * cvtnum() is used even if math support is off (to prepare $? values and such).
6033  */
6034 static int
6035 cvtnum(arith_t num)
6036 {
6037         int len;
6038
6039         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6040         len = sizeof(arith_t) * 3;
6041         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6042         if (sizeof(arith_t) < 4) len += 2;
6043
6044         expdest = makestrspace(len, expdest);
6045         len = fmtstr(expdest, len, ARITH_FMT, num);
6046         STADJUST(len, expdest);
6047         return len;
6048 }
6049
6050 /*
6051  * Break the argument string into pieces based upon IFS and add the
6052  * strings to the argument list.  The regions of the string to be
6053  * searched for IFS characters have been stored by recordregion.
6054  */
6055 static void
6056 ifsbreakup(char *string, struct arglist *arglist)
6057 {
6058         struct ifsregion *ifsp;
6059         struct strlist *sp;
6060         char *start;
6061         char *p;
6062         char *q;
6063         const char *ifs, *realifs;
6064         int ifsspc;
6065         int nulonly;
6066
6067         start = string;
6068         if (ifslastp != NULL) {
6069                 ifsspc = 0;
6070                 nulonly = 0;
6071                 realifs = ifsset() ? ifsval() : defifs;
6072                 ifsp = &ifsfirst;
6073                 do {
6074                         int afternul;
6075
6076                         p = string + ifsp->begoff;
6077                         afternul = nulonly;
6078                         nulonly = ifsp->nulonly;
6079                         ifs = nulonly ? nullstr : realifs;
6080                         ifsspc = 0;
6081                         while (p < string + ifsp->endoff) {
6082                                 q = p;
6083                                 if ((unsigned char)*p == CTLESC)
6084                                         p++;
6085                                 if (!strchr(ifs, *p)) {
6086                                         p++;
6087                                         continue;
6088                                 }
6089                                 if (!(afternul || nulonly))
6090                                         ifsspc = (strchr(defifs, *p) != NULL);
6091                                 /* Ignore IFS whitespace at start */
6092                                 if (q == start && ifsspc) {
6093                                         p++;
6094                                         start = p;
6095                                         continue;
6096                                 }
6097                                 *q = '\0';
6098                                 sp = stzalloc(sizeof(*sp));
6099                                 sp->text = start;
6100                                 *arglist->lastp = sp;
6101                                 arglist->lastp = &sp->next;
6102                                 p++;
6103                                 if (!nulonly) {
6104                                         for (;;) {
6105                                                 if (p >= string + ifsp->endoff) {
6106                                                         break;
6107                                                 }
6108                                                 q = p;
6109                                                 if ((unsigned char)*p == CTLESC)
6110                                                         p++;
6111                                                 if (strchr(ifs, *p) == NULL) {
6112                                                         p = q;
6113                                                         break;
6114                                                 }
6115                                                 if (strchr(defifs, *p) == NULL) {
6116                                                         if (ifsspc) {
6117                                                                 p++;
6118                                                                 ifsspc = 0;
6119                                                         } else {
6120                                                                 p = q;
6121                                                                 break;
6122                                                         }
6123                                                 } else
6124                                                         p++;
6125                                         }
6126                                 }
6127                                 start = p;
6128                         } /* while */
6129                         ifsp = ifsp->next;
6130                 } while (ifsp != NULL);
6131                 if (nulonly)
6132                         goto add;
6133         }
6134
6135         if (!*start)
6136                 return;
6137
6138  add:
6139         sp = stzalloc(sizeof(*sp));
6140         sp->text = start;
6141         *arglist->lastp = sp;
6142         arglist->lastp = &sp->next;
6143 }
6144
6145 static void
6146 ifsfree(void)
6147 {
6148         struct ifsregion *p = ifsfirst.next;
6149
6150         if (!p)
6151                 goto out;
6152
6153         INT_OFF;
6154         do {
6155                 struct ifsregion *ifsp;
6156                 ifsp = p->next;
6157                 free(p);
6158                 p = ifsp;
6159         } while (p);
6160         ifsfirst.next = NULL;
6161         INT_ON;
6162  out:
6163         ifslastp = NULL;
6164 }
6165
6166 static size_t
6167 esclen(const char *start, const char *p)
6168 {
6169         size_t esc = 0;
6170
6171         while (p > start && (unsigned char)*--p == CTLESC) {
6172                 esc++;
6173         }
6174         return esc;
6175 }
6176
6177 /*
6178  * Remove any CTLESC characters from a string.
6179  */
6180 #if !BASH_PATTERN_SUBST
6181 #define rmescapes(str, flag, slash_position) \
6182         rmescapes(str, flag)
6183 #endif
6184 static char *
6185 rmescapes(char *str, int flag, int *slash_position)
6186 {
6187         static const char qchars[] ALIGN1 = {
6188                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6189
6190         char *p, *q, *r;
6191         unsigned protect_against_glob;
6192         unsigned globbing;
6193
6194         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6195         if (!p)
6196                 return str;
6197
6198         q = p;
6199         r = str;
6200         if (flag & RMESCAPE_ALLOC) {
6201                 size_t len = p - str;
6202                 size_t fulllen = len + strlen(p) + 1;
6203
6204                 if (flag & RMESCAPE_GROW) {
6205                         int strloc = str - (char *)stackblock();
6206                         r = makestrspace(fulllen, expdest);
6207                         /* p and str may be invalidated by makestrspace */
6208                         str = (char *)stackblock() + strloc;
6209                         p = str + len;
6210                 } else if (flag & RMESCAPE_HEAP) {
6211                         r = ckmalloc(fulllen);
6212                 } else {
6213                         r = stalloc(fulllen);
6214                 }
6215                 q = r;
6216                 if (len > 0) {
6217                         q = (char *)mempcpy(q, str, len);
6218                 }
6219         }
6220
6221         globbing = flag & RMESCAPE_GLOB;
6222         protect_against_glob = globbing;
6223         while (*p) {
6224                 if ((unsigned char)*p == CTLQUOTEMARK) {
6225 // Note: protect_against_glob only affect whether
6226 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6227                         p++;
6228                         protect_against_glob = globbing;
6229                         continue;
6230                 }
6231                 if (*p == '\\') {
6232                         /* naked back slash */
6233                         protect_against_glob = 0;
6234                         goto copy;
6235                 }
6236                 if ((unsigned char)*p == CTLESC) {
6237                         p++;
6238 #if DEBUG
6239                         if (*p == '\0')
6240                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6241 #endif
6242                         if (protect_against_glob) {
6243                                 /*
6244                                  * We used to trust glob() and fnmatch() to eat
6245                                  * superfluous escapes (\z where z has no
6246                                  * special meaning anyway). But this causes
6247                                  * bugs such as string of one greek letter rho
6248                                  * (unicode-encoded as two bytes "cf,81")
6249                                  * getting encoded as "cf,CTLESC,81"
6250                                  * and here, converted to "cf,\,81" -
6251                                  * which does not go well with some flavors
6252                                  * of fnmatch() in unicode locales
6253                                  * (for example, glibc <= 2.22).
6254                                  *
6255                                  * Lets add "\" only on the chars which need it.
6256                                  * Testcases for less obvious chars are shown.
6257                                  */
6258                                 if (*p == '*'
6259                                  || *p == '?'
6260                                  || *p == '['
6261                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6262                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6263                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6264                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6265                                 /* Some libc support [^negate], that's why "^" also needs love */
6266                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6267                                 ) {
6268                                         *q++ = '\\';
6269                                 }
6270                         }
6271                 }
6272 #if BASH_PATTERN_SUBST
6273                 else if (slash_position && p == str + *slash_position) {
6274                         /* stop handling globbing */
6275                         globbing = 0;
6276                         *slash_position = q - r;
6277                         slash_position = NULL;
6278                 }
6279 #endif
6280                 protect_against_glob = globbing;
6281  copy:
6282                 *q++ = *p++;
6283         }
6284         *q = '\0';
6285         if (flag & RMESCAPE_GROW) {
6286                 expdest = r;
6287                 STADJUST(q - r + 1, expdest);
6288         }
6289         return r;
6290 }
6291 #define pmatch(a, b) !fnmatch((a), (b), 0)
6292
6293 /*
6294  * Prepare a pattern for a expmeta (internal glob(3)) call.
6295  *
6296  * Returns an stalloced string.
6297  */
6298 static char *
6299 preglob(const char *pattern, int flag)
6300 {
6301         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6302 }
6303
6304 /*
6305  * Put a string on the stack.
6306  */
6307 static void
6308 memtodest(const char *p, size_t len, int syntax, int quotes)
6309 {
6310         char *q;
6311
6312         if (!len)
6313                 return;
6314
6315         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6316
6317         do {
6318                 unsigned char c = *p++;
6319                 if (c) {
6320                         if (quotes & QUOTES_ESC) {
6321                                 int n = SIT(c, syntax);
6322                                 if (n == CCTL
6323                                  || (syntax != BASESYNTAX && n == CBACK)
6324                                 ) {
6325                                         USTPUTC(CTLESC, q);
6326                                 }
6327                         }
6328                 } else if (!(quotes & QUOTES_KEEPNUL))
6329                         continue;
6330                 USTPUTC(c, q);
6331         } while (--len);
6332
6333         expdest = q;
6334 }
6335
6336 static size_t
6337 strtodest(const char *p, int syntax, int quotes)
6338 {
6339         size_t len = strlen(p);
6340         memtodest(p, len, syntax, quotes);
6341         return len;
6342 }
6343
6344 /*
6345  * Record the fact that we have to scan this region of the
6346  * string for IFS characters.
6347  */
6348 static void
6349 recordregion(int start, int end, int nulonly)
6350 {
6351         struct ifsregion *ifsp;
6352
6353         if (ifslastp == NULL) {
6354                 ifsp = &ifsfirst;
6355         } else {
6356                 INT_OFF;
6357                 ifsp = ckzalloc(sizeof(*ifsp));
6358                 /*ifsp->next = NULL; - ckzalloc did it */
6359                 ifslastp->next = ifsp;
6360                 INT_ON;
6361         }
6362         ifslastp = ifsp;
6363         ifslastp->begoff = start;
6364         ifslastp->endoff = end;
6365         ifslastp->nulonly = nulonly;
6366 }
6367
6368 static void
6369 removerecordregions(int endoff)
6370 {
6371         if (ifslastp == NULL)
6372                 return;
6373
6374         if (ifsfirst.endoff > endoff) {
6375                 while (ifsfirst.next) {
6376                         struct ifsregion *ifsp;
6377                         INT_OFF;
6378                         ifsp = ifsfirst.next->next;
6379                         free(ifsfirst.next);
6380                         ifsfirst.next = ifsp;
6381                         INT_ON;
6382                 }
6383                 if (ifsfirst.begoff > endoff) {
6384                         ifslastp = NULL;
6385                 } else {
6386                         ifslastp = &ifsfirst;
6387                         ifsfirst.endoff = endoff;
6388                 }
6389                 return;
6390         }
6391
6392         ifslastp = &ifsfirst;
6393         while (ifslastp->next && ifslastp->next->begoff < endoff)
6394                 ifslastp = ifslastp->next;
6395         while (ifslastp->next) {
6396                 struct ifsregion *ifsp;
6397                 INT_OFF;
6398                 ifsp = ifslastp->next->next;
6399                 free(ifslastp->next);
6400                 ifslastp->next = ifsp;
6401                 INT_ON;
6402         }
6403         if (ifslastp->endoff > endoff)
6404                 ifslastp->endoff = endoff;
6405 }
6406
6407 static char *
6408 exptilde(char *startp, char *p, int flags)
6409 {
6410         unsigned char c;
6411         char *name;
6412         struct passwd *pw;
6413         const char *home;
6414         int quotes = flags & QUOTES_ESC;
6415
6416         name = p + 1;
6417
6418         while ((c = *++p) != '\0') {
6419                 switch (c) {
6420                 case CTLESC:
6421                         return startp;
6422                 case CTLQUOTEMARK:
6423                         return startp;
6424                 case ':':
6425                         if (flags & EXP_VARTILDE)
6426                                 goto done;
6427                         break;
6428                 case '/':
6429                 case CTLENDVAR:
6430                         goto done;
6431                 }
6432         }
6433  done:
6434         *p = '\0';
6435         if (*name == '\0') {
6436                 home = lookupvar("HOME");
6437         } else {
6438                 pw = getpwnam(name);
6439                 if (pw == NULL)
6440                         goto lose;
6441                 home = pw->pw_dir;
6442         }
6443         if (!home)
6444                 goto lose;
6445         *p = c;
6446         strtodest(home, SQSYNTAX, quotes);
6447         return p;
6448  lose:
6449         *p = c;
6450         return startp;
6451 }
6452
6453 /*
6454  * Execute a command inside back quotes.  If it's a builtin command, we
6455  * want to save its output in a block obtained from malloc.  Otherwise
6456  * we fork off a subprocess and get the output of the command via a pipe.
6457  * Should be called with interrupts off.
6458  */
6459 struct backcmd {                /* result of evalbackcmd */
6460         int fd;                 /* file descriptor to read from */
6461         int nleft;              /* number of chars in buffer */
6462         char *buf;              /* buffer */
6463         struct job *jp;         /* job structure for command */
6464 };
6465
6466 /* These forward decls are needed to use "eval" code for backticks handling: */
6467 /* flags in argument to evaltree */
6468 #define EV_EXIT    01           /* exit after evaluating tree */
6469 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6470 static int evaltree(union node *, int);
6471
6472 /* An evaltree() which is known to never return.
6473  * Used to use an alias:
6474  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6475  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6476  */
6477 static ALWAYS_INLINE NORETURN void
6478 evaltreenr(union node *n, int flags)
6479 {
6480         evaltree(n, flags);
6481         bb_unreachable(abort());
6482         /* NOTREACHED */
6483 }
6484
6485 static void FAST_FUNC
6486 evalbackcmd(union node *n, struct backcmd *result)
6487 {
6488         int pip[2];
6489         struct job *jp;
6490
6491         result->fd = -1;
6492         result->buf = NULL;
6493         result->nleft = 0;
6494         result->jp = NULL;
6495         if (n == NULL) {
6496                 goto out;
6497         }
6498
6499         if (pipe(pip) < 0)
6500                 ash_msg_and_raise_perror("can't create pipe");
6501         jp = makejob(/*n,*/ 1);
6502         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6503                 /* child */
6504                 FORCE_INT_ON;
6505                 close(pip[0]);
6506                 if (pip[1] != 1) {
6507                         /*close(1);*/
6508                         dup2_or_raise(pip[1], 1);
6509                         close(pip[1]);
6510                 }
6511 /* TODO: eflag clearing makes the following not abort:
6512  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6513  * which is what bash does (unless it is in POSIX mode).
6514  * dash deleted "eflag = 0" line in the commit
6515  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6516  *  [EVAL] Don't clear eflag in evalbackcmd
6517  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6518  */
6519                 eflag = 0;
6520                 ifsfree();
6521                 evaltreenr(n, EV_EXIT);
6522                 /* NOTREACHED */
6523         }
6524         /* parent */
6525         close(pip[1]);
6526         result->fd = pip[0];
6527         result->jp = jp;
6528
6529  out:
6530         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6531                 result->fd, result->buf, result->nleft, result->jp));
6532 }
6533
6534 /*
6535  * Expand stuff in backwards quotes.
6536  */
6537 static void
6538 expbackq(union node *cmd, int flag)
6539 {
6540         struct backcmd in;
6541         int i;
6542         char buf[128];
6543         char *p;
6544         char *dest;
6545         int startloc;
6546         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6547         struct stackmark smark;
6548
6549         INT_OFF;
6550         startloc = expdest - (char *)stackblock();
6551         pushstackmark(&smark, startloc);
6552         evalbackcmd(cmd, &in);
6553         popstackmark(&smark);
6554
6555         p = in.buf;
6556         i = in.nleft;
6557         if (i == 0)
6558                 goto read;
6559         for (;;) {
6560                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6561  read:
6562                 if (in.fd < 0)
6563                         break;
6564                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6565                 TRACE(("expbackq: read returns %d\n", i));
6566                 if (i <= 0)
6567                         break;
6568                 p = buf;
6569         }
6570
6571         free(in.buf);
6572         if (in.fd >= 0) {
6573                 close(in.fd);
6574                 back_exitstatus = waitforjob(in.jp);
6575         }
6576         INT_ON;
6577
6578         /* Eat all trailing newlines */
6579         dest = expdest;
6580         for (; dest > ((char *)stackblock() + startloc) && dest[-1] == '\n';)
6581                 STUNPUTC(dest);
6582         expdest = dest;
6583
6584         if (!(flag & EXP_QUOTED))
6585                 recordregion(startloc, dest - (char *)stackblock(), 0);
6586         TRACE(("evalbackq: size:%d:'%.*s'\n",
6587                 (int)((dest - (char *)stackblock()) - startloc),
6588                 (int)((dest - (char *)stackblock()) - startloc),
6589                 stackblock() + startloc));
6590 }
6591
6592 #if ENABLE_FEATURE_SH_MATH
6593 /*
6594  * Expand arithmetic expression.  Backup to start of expression,
6595  * evaluate, place result in (backed up) result, adjust string position.
6596  */
6597 static void
6598 expari(int flag)
6599 {
6600         char *p, *start;
6601         int begoff;
6602         int len;
6603
6604         /* ifsfree(); */
6605
6606         /*
6607          * This routine is slightly over-complicated for
6608          * efficiency.  Next we scan backwards looking for the
6609          * start of arithmetic.
6610          */
6611         start = stackblock();
6612         p = expdest - 1;
6613         *p = '\0';
6614         p--;
6615         while (1) {
6616                 int esc;
6617
6618                 while ((unsigned char)*p != CTLARI) {
6619                         p--;
6620 #if DEBUG
6621                         if (p < start) {
6622                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6623                         }
6624 #endif
6625                 }
6626
6627                 esc = esclen(start, p);
6628                 if (!(esc % 2)) {
6629                         break;
6630                 }
6631
6632                 p -= esc + 1;
6633         }
6634
6635         begoff = p - start;
6636
6637         removerecordregions(begoff);
6638
6639         expdest = p;
6640
6641         if (flag & QUOTES_ESC)
6642                 rmescapes(p + 1, 0, NULL);
6643
6644         len = cvtnum(ash_arith(p + 1));
6645
6646         if (!(flag & EXP_QUOTED))
6647                 recordregion(begoff, begoff + len, 0);
6648 }
6649 #endif
6650
6651 /* argstr needs it */
6652 static char *evalvar(char *p, int flags);
6653
6654 /*
6655  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6656  * characters to allow for further processing.  Otherwise treat
6657  * $@ like $* since no splitting will be performed.
6658  */
6659 static void
6660 argstr(char *p, int flags)
6661 {
6662         static const char spclchars[] ALIGN1 = {
6663                 '=',
6664                 ':',
6665                 CTLQUOTEMARK,
6666                 CTLENDVAR,
6667                 CTLESC,
6668                 CTLVAR,
6669                 CTLBACKQ,
6670 #if ENABLE_FEATURE_SH_MATH
6671                 CTLENDARI,
6672 #endif
6673                 '\0'
6674         };
6675         const char *reject = spclchars;
6676         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6677         int inquotes;
6678         size_t length;
6679         int startloc;
6680
6681         if (!(flags & EXP_VARTILDE)) {
6682                 reject += 2;
6683         } else if (flags & EXP_VARTILDE2) {
6684                 reject++;
6685         }
6686         inquotes = 0;
6687         length = 0;
6688         if (flags & EXP_TILDE) {
6689                 char *q;
6690
6691                 flags &= ~EXP_TILDE;
6692  tilde:
6693                 q = p;
6694                 if (*q == '~')
6695                         p = exptilde(p, q, flags);
6696         }
6697  start:
6698         startloc = expdest - (char *)stackblock();
6699         for (;;) {
6700                 unsigned char c;
6701
6702                 length += strcspn(p + length, reject);
6703                 c = p[length];
6704                 if (c) {
6705                         if (!(c & 0x80)
6706                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6707                         ) {
6708                                 /* c == '=' || c == ':' || c == CTLENDARI */
6709                                 length++;
6710                         }
6711                 }
6712                 if (length > 0) {
6713                         int newloc;
6714                         expdest = stack_nputstr(p, length, expdest);
6715                         newloc = expdest - (char *)stackblock();
6716                         if (breakall && !inquotes && newloc > startloc) {
6717                                 recordregion(startloc, newloc, 0);
6718                         }
6719                         startloc = newloc;
6720                 }
6721                 p += length + 1;
6722                 length = 0;
6723
6724                 switch (c) {
6725                 case '\0':
6726                         goto breakloop;
6727                 case '=':
6728                         if (flags & EXP_VARTILDE2) {
6729                                 p--;
6730                                 continue;
6731                         }
6732                         flags |= EXP_VARTILDE2;
6733                         reject++;
6734                         /* fall through */
6735                 case ':':
6736                         /*
6737                          * sort of a hack - expand tildes in variable
6738                          * assignments (after the first '=' and after ':'s).
6739                          */
6740                         if (*--p == '~') {
6741                                 goto tilde;
6742                         }
6743                         continue;
6744                 }
6745
6746                 switch (c) {
6747                 case CTLENDVAR: /* ??? */
6748                         goto breakloop;
6749                 case CTLQUOTEMARK:
6750                         /* "$@" syntax adherence hack */
6751                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6752                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6753                                 goto start;
6754                         }
6755                         inquotes ^= EXP_QUOTED;
6756  addquote:
6757                         if (flags & QUOTES_ESC) {
6758                                 p--;
6759                                 length++;
6760                                 startloc++;
6761                         }
6762                         break;
6763                 case CTLESC:
6764                         startloc++;
6765                         length++;
6766                         goto addquote;
6767                 case CTLVAR:
6768                         TRACE(("argstr: evalvar('%s')\n", p));
6769                         p = evalvar(p, flags | inquotes);
6770                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6771                         goto start;
6772                 case CTLBACKQ:
6773                         expbackq(argbackq->n, flags | inquotes);
6774                         argbackq = argbackq->next;
6775                         goto start;
6776 #if ENABLE_FEATURE_SH_MATH
6777                 case CTLENDARI:
6778                         p--;
6779                         expari(flags | inquotes);
6780                         goto start;
6781 #endif
6782                 }
6783         }
6784  breakloop: ;
6785 }
6786
6787 static char *
6788 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6789                 char *pattern, int quotes, int zero)
6790 {
6791         char *loc, *loc2;
6792         char c;
6793
6794         loc = startp;
6795         loc2 = rmesc;
6796         do {
6797                 int match;
6798                 const char *s = loc2;
6799
6800                 c = *loc2;
6801                 if (zero) {
6802                         *loc2 = '\0';
6803                         s = rmesc;
6804                 }
6805                 match = pmatch(pattern, s);
6806
6807                 *loc2 = c;
6808                 if (match)
6809                         return loc;
6810                 if (quotes && (unsigned char)*loc == CTLESC)
6811                         loc++;
6812                 loc++;
6813                 loc2++;
6814         } while (c);
6815         return NULL;
6816 }
6817
6818 static char *
6819 scanright(char *startp, char *rmesc, char *rmescend,
6820                 char *pattern, int quotes, int match_at_start)
6821 {
6822 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6823         int try2optimize = match_at_start;
6824 #endif
6825         int esc = 0;
6826         char *loc;
6827         char *loc2;
6828
6829         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6830          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6831          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6832          * Logic:
6833          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6834          * and on each iteration they go back two/one char until they reach the beginning.
6835          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6836          */
6837         /* TODO: document in what other circumstances we are called. */
6838
6839         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6840                 int match;
6841                 char c = *loc2;
6842                 const char *s = loc2;
6843                 if (match_at_start) {
6844                         *loc2 = '\0';
6845                         s = rmesc;
6846                 }
6847                 match = pmatch(pattern, s);
6848                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6849                 *loc2 = c;
6850                 if (match)
6851                         return loc;
6852 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6853                 if (try2optimize) {
6854                         /* Maybe we can optimize this:
6855                          * if pattern ends with unescaped *, we can avoid checking
6856                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6857                          * it won't match truncated "raw_value_of_" strings too.
6858                          */
6859                         unsigned plen = strlen(pattern);
6860                         /* Does it end with "*"? */
6861                         if (plen != 0 && pattern[--plen] == '*') {
6862                                 /* "xxxx*" is not escaped */
6863                                 /* "xxx\*" is escaped */
6864                                 /* "xx\\*" is not escaped */
6865                                 /* "x\\\*" is escaped */
6866                                 int slashes = 0;
6867                                 while (plen != 0 && pattern[--plen] == '\\')
6868                                         slashes++;
6869                                 if (!(slashes & 1))
6870                                         break; /* ends with unescaped "*" */
6871                         }
6872                         try2optimize = 0;
6873                 }
6874 #endif
6875                 loc--;
6876                 if (quotes) {
6877                         if (--esc < 0) {
6878                                 esc = esclen(startp, loc);
6879                         }
6880                         if (esc % 2) {
6881                                 esc--;
6882                                 loc--;
6883                         }
6884                 }
6885         }
6886         return NULL;
6887 }
6888
6889 static void varunset(const char *, const char *, const char *, int) NORETURN;
6890 static void
6891 varunset(const char *end, const char *var, const char *umsg, int varflags)
6892 {
6893         const char *msg;
6894         const char *tail;
6895
6896         tail = nullstr;
6897         msg = "parameter not set";
6898         if (umsg) {
6899                 if ((unsigned char)*end == CTLENDVAR) {
6900                         if (varflags & VSNUL)
6901                                 tail = " or null";
6902                 } else {
6903                         msg = umsg;
6904                 }
6905         }
6906         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6907 }
6908
6909 static const char *
6910 subevalvar(char *p, char *varname, int strloc, int subtype,
6911                 int startloc, int varflags, int flag)
6912 {
6913         struct nodelist *saveargbackq = argbackq;
6914         int quotes = flag & QUOTES_ESC;
6915         char *startp;
6916         char *loc;
6917         char *rmesc, *rmescend;
6918         char *str;
6919         int amount, resetloc;
6920         int argstr_flags;
6921         IF_BASH_PATTERN_SUBST(int workloc;)
6922         IF_BASH_PATTERN_SUBST(int slash_pos;)
6923         IF_BASH_PATTERN_SUBST(char *repl;)
6924         int zero;
6925         char *(*scan)(char*, char*, char*, char*, int, int);
6926
6927         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6928         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6929
6930 #if BASH_PATTERN_SUBST
6931         /* For "${v/pattern/repl}", we must find the delimiter _before_
6932          * argstr() call expands possible variable references in pattern:
6933          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6934          */
6935         repl = NULL;
6936         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6937                 /* Find '/' and replace with NUL */
6938                 repl = p;
6939                 /* The pattern can't be empty.
6940                  * IOW: if the first char after "${v//" is a slash,
6941                  * it does not terminate the pattern - it's the first char of the pattern:
6942                  *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
6943                  *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
6944                  */
6945                 if (*repl == '/')
6946                         repl++;
6947                 for (;;) {
6948                         if (*repl == '\0') {
6949                                 repl = NULL;
6950                                 break;
6951                         }
6952                         if (*repl == '/') {
6953                                 *repl = '\0';
6954                                 break;
6955                         }
6956                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6957                         if ((unsigned char)*repl == CTLESC && repl[1])
6958                                 repl++;
6959                         repl++;
6960                 }
6961         }
6962 #endif
6963         argstr_flags = EXP_TILDE;
6964         if (subtype != VSASSIGN
6965          && subtype != VSQUESTION
6966 #if BASH_SUBSTR
6967          && subtype != VSSUBSTR
6968 #endif
6969         ) {
6970                 /* EXP_CASE keeps CTLESC's */
6971                 argstr_flags = EXP_TILDE | EXP_CASE;
6972         }
6973         argstr(p, argstr_flags);
6974         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6975 #if BASH_PATTERN_SUBST
6976         slash_pos = -1;
6977         if (repl) {
6978                 slash_pos = expdest - ((char *)stackblock() + strloc);
6979                 STPUTC('/', expdest);
6980                 //bb_error_msg("repl+1:'%s'", repl + 1);
6981                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6982                 *repl = '/';
6983         }
6984 #endif
6985         STPUTC('\0', expdest);
6986         argbackq = saveargbackq;
6987         startp = (char *)stackblock() + startloc;
6988         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6989
6990         switch (subtype) {
6991         case VSASSIGN:
6992                 setvar0(varname, startp);
6993                 amount = startp - expdest;
6994                 STADJUST(amount, expdest);
6995                 return startp;
6996
6997         case VSQUESTION:
6998                 varunset(p, varname, startp, varflags);
6999                 /* NOTREACHED */
7000
7001 #if BASH_SUBSTR
7002         case VSSUBSTR: {
7003                 int pos, len, orig_len;
7004                 char *colon;
7005
7006                 loc = str = stackblock() + strloc;
7007
7008                 /* Read POS in ${var:POS:LEN} */
7009                 colon = strchr(loc, ':');
7010                 if (colon) *colon = '\0';
7011                 pos = substr_atoi(loc);
7012                 if (colon) *colon = ':';
7013
7014                 /* Read LEN in ${var:POS:LEN} */
7015                 len = str - startp - 1;
7016                 /* *loc != '\0', guaranteed by parser */
7017                 if (quotes) {
7018                         char *ptr;
7019                         /* Adjust the length by the number of escapes */
7020                         for (ptr = startp; ptr < (str - 1); ptr++) {
7021                                 if ((unsigned char)*ptr == CTLESC) {
7022                                         len--;
7023                                         ptr++;
7024                                 }
7025                         }
7026                 }
7027                 orig_len = len;
7028                 if (*loc++ == ':') {
7029                         /* ${var::LEN} */
7030                         len = substr_atoi(loc);
7031                 } else {
7032                         /* Skip POS in ${var:POS:LEN} */
7033                         len = orig_len;
7034                         while (*loc && *loc != ':')
7035                                 loc++;
7036                         if (*loc++ == ':')
7037                                 len = substr_atoi(loc);
7038                 }
7039                 if (pos < 0) {
7040                         /* ${VAR:$((-n)):l} starts n chars from the end */
7041                         pos = orig_len + pos;
7042                 }
7043                 if ((unsigned)pos >= orig_len) {
7044                         /* apart from obvious ${VAR:999999:l},
7045                          * covers ${VAR:$((-9999999)):l} - result is ""
7046                          * (bash compat)
7047                          */
7048                         pos = 0;
7049                         len = 0;
7050                 }
7051                 if (len < 0) {
7052                         /* ${VAR:N:-M} sets LEN to strlen()-M */
7053                         len = (orig_len - pos) + len;
7054                 }
7055                 if ((unsigned)len > (orig_len - pos))
7056                         len = orig_len - pos;
7057
7058                 for (str = startp; pos; str++, pos--) {
7059                         if (quotes && (unsigned char)*str == CTLESC)
7060                                 str++;
7061                 }
7062                 for (loc = startp; len; len--) {
7063                         if (quotes && (unsigned char)*str == CTLESC)
7064                                 *loc++ = *str++;
7065                         *loc++ = *str++;
7066                 }
7067                 *loc = '\0';
7068                 amount = loc - expdest;
7069                 STADJUST(amount, expdest);
7070                 return loc;
7071         }
7072 #endif /* BASH_SUBSTR */
7073         }
7074
7075         resetloc = expdest - (char *)stackblock();
7076
7077 #if BASH_PATTERN_SUBST
7078         repl = NULL;
7079
7080         /* We'll comeback here if we grow the stack while handling
7081          * a VSREPLACE or VSREPLACEALL, since our pointers into the
7082          * stack will need rebasing, and we'll need to remove our work
7083          * areas each time
7084          */
7085  restart:
7086 #endif
7087
7088         amount = expdest - ((char *)stackblock() + resetloc);
7089         STADJUST(-amount, expdest);
7090         startp = (char *)stackblock() + startloc;
7091
7092         rmesc = startp;
7093         rmescend = (char *)stackblock() + strloc;
7094         //bb_error_msg("str7:'%s'", rmescend);
7095         if (quotes) {
7096 //TODO: how to handle slash_pos here if string changes (shortens?)
7097                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7098                 if (rmesc != startp) {
7099                         rmescend = expdest;
7100                         startp = (char *)stackblock() + startloc;
7101                 }
7102         }
7103         rmescend--;
7104         str = (char *)stackblock() + strloc;
7105         /*
7106          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7107          * The result is a_\_z_c (not a\_\_z_c)!
7108          *
7109          * The search pattern and replace string treat backslashes differently!
7110          * "&slash_pos" causes rmescapes() to work differently on the pattern
7111          * and string.  It's only used on the first call.
7112          */
7113         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7114         rmescapes(str, RMESCAPE_GLOB,
7115                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7116         );
7117
7118 #if BASH_PATTERN_SUBST
7119         workloc = expdest - (char *)stackblock();
7120         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7121                 int len;
7122                 char *idx, *end;
7123
7124                 if (!repl) {
7125                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7126                         repl = nullstr;
7127                         if (slash_pos >= 0) {
7128                                 repl = str + slash_pos;
7129                                 *repl++ = '\0';
7130                         }
7131                 }
7132                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7133
7134                 /* If there's no pattern to match, return the expansion unmolested */
7135                 if (str[0] == '\0')
7136                         return NULL;
7137
7138                 len = 0;
7139                 idx = startp;
7140                 end = str - 1;
7141                 while (idx < end) {
7142  try_to_match:
7143                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7144                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7145                         if (!loc) {
7146                                 /* No match, advance */
7147                                 char *restart_detect = stackblock();
7148  skip_matching:
7149                                 STPUTC(*idx, expdest);
7150                                 if (quotes && (unsigned char)*idx == CTLESC) {
7151                                         idx++;
7152                                         len++;
7153                                         STPUTC(*idx, expdest);
7154                                 }
7155                                 if (stackblock() != restart_detect)
7156                                         goto restart;
7157                                 idx++;
7158                                 len++;
7159                                 rmesc++;
7160                                 /* continue; - prone to quadratic behavior, smarter code: */
7161                                 if (idx >= end)
7162                                         break;
7163                                 if (str[0] == '*') {
7164                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7165                                          * it would never match "ong_string" etc, no point in trying.
7166                                          */
7167                                         goto skip_matching;
7168                                 }
7169                                 goto try_to_match;
7170                         }
7171
7172                         if (subtype == VSREPLACEALL) {
7173                                 while (idx < loc) {
7174                                         if (quotes && (unsigned char)*idx == CTLESC)
7175                                                 idx++;
7176                                         idx++;
7177                                         rmesc++;
7178                                 }
7179                         } else {
7180                                 idx = loc;
7181                         }
7182
7183                         //bb_error_msg("repl:'%s'", repl);
7184                         for (loc = (char*)repl; *loc; loc++) {
7185                                 char *restart_detect = stackblock();
7186                                 if (quotes && *loc == '\\') {
7187                                         STPUTC(CTLESC, expdest);
7188                                         len++;
7189                                 }
7190                                 STPUTC(*loc, expdest);
7191                                 if (stackblock() != restart_detect)
7192                                         goto restart;
7193                                 len++;
7194                         }
7195
7196                         if (subtype == VSREPLACE) {
7197                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7198                                 while (*idx) {
7199                                         char *restart_detect = stackblock();
7200                                         STPUTC(*idx, expdest);
7201                                         if (stackblock() != restart_detect)
7202                                                 goto restart;
7203                                         len++;
7204                                         idx++;
7205                                 }
7206                                 break;
7207                         }
7208                 }
7209
7210                 /* We've put the replaced text into a buffer at workloc, now
7211                  * move it to the right place and adjust the stack.
7212                  */
7213                 STPUTC('\0', expdest);
7214                 startp = (char *)stackblock() + startloc;
7215                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7216                 //bb_error_msg("startp:'%s'", startp);
7217                 amount = expdest - (startp + len);
7218                 STADJUST(-amount, expdest);
7219                 return startp;
7220         }
7221 #endif /* BASH_PATTERN_SUBST */
7222
7223         subtype -= VSTRIMRIGHT;
7224 #if DEBUG
7225         if (subtype < 0 || subtype > 7)
7226                 abort();
7227 #endif
7228         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7229         zero = subtype >> 1;
7230         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7231         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7232
7233         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7234         if (loc) {
7235                 if (zero) {
7236                         memmove(startp, loc, str - loc);
7237                         loc = startp + (str - loc) - 1;
7238                 }
7239                 *loc = '\0';
7240                 amount = loc - expdest;
7241                 STADJUST(amount, expdest);
7242         }
7243         return loc;
7244 }
7245
7246 /*
7247  * Add the value of a specialized variable to the stack string.
7248  * name parameter (examples):
7249  * ash -c 'echo $1'      name:'1='
7250  * ash -c 'echo $qwe'    name:'qwe='
7251  * ash -c 'echo $$'      name:'$='
7252  * ash -c 'echo ${$}'    name:'$='
7253  * ash -c 'echo ${$##q}' name:'$=q'
7254  * ash -c 'echo ${#$}'   name:'$='
7255  * note: examples with bad shell syntax:
7256  * ash -c 'echo ${#$1}'  name:'$=1'
7257  * ash -c 'echo ${#1#}'  name:'1=#'
7258  */
7259 static NOINLINE ssize_t
7260 varvalue(char *name, int varflags, int flags, int quoted)
7261 {
7262         const char *p;
7263         int num;
7264         int i;
7265         ssize_t len = 0;
7266         int sep;
7267         int subtype = varflags & VSTYPE;
7268         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7269         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7270         int syntax;
7271
7272         sep = (flags & EXP_FULL) << CHAR_BIT;
7273         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7274
7275         switch (*name) {
7276         case '$':
7277                 num = rootpid;
7278                 goto numvar;
7279         case '?':
7280                 num = exitstatus;
7281                 goto numvar;
7282         case '#':
7283                 num = shellparam.nparam;
7284                 goto numvar;
7285         case '!':
7286                 num = backgndpid;
7287                 if (num == 0)
7288                         return -1;
7289  numvar:
7290                 len = cvtnum(num);
7291                 goto check_1char_name;
7292         case '-':
7293                 expdest = makestrspace(NOPTS, expdest);
7294                 for (i = NOPTS - 1; i >= 0; i--) {
7295                         if (optlist[i] && optletters(i)) {
7296                                 USTPUTC(optletters(i), expdest);
7297                                 len++;
7298                         }
7299                 }
7300  check_1char_name:
7301 #if 0
7302                 /* handles cases similar to ${#$1} */
7303                 if (name[2] != '\0')
7304                         raise_error_syntax("bad substitution");
7305 #endif
7306                 break;
7307         case '@':
7308                 if (quoted && sep)
7309                         goto param;
7310                 /* fall through */
7311         case '*': {
7312                 char **ap;
7313                 char sepc;
7314                 char c;
7315
7316                 /* We will set c to 0 or ~0 depending on whether
7317                  * we're doing field splitting.  We won't do field
7318                  * splitting if either we're quoted or sep is zero.
7319                  *
7320                  * Instead of testing (quoted || !sep) the following
7321                  * trick optimises away any branches by using the
7322                  * fact that EXP_QUOTED (which is the only bit that
7323                  * can be set in quoted) is the same as EXP_FULL <<
7324                  * CHAR_BIT (which is the only bit that can be set
7325                  * in sep).
7326                  */
7327 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7328 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7329 #endif
7330                 c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7331                 sep &= ~quoted;
7332                 sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7333  param:
7334                 sepc = sep;
7335                 ap = shellparam.p;
7336                 if (!ap)
7337                         return -1;
7338                 while ((p = *ap++) != NULL) {
7339                         len += strtodest(p, syntax, quotes);
7340
7341                         if (*ap && sep) {
7342                                 len++;
7343                                 memtodest(&sepc, 1, syntax, quotes);
7344                         }
7345                 }
7346                 break;
7347         } /* case '*' */
7348         case '0':
7349         case '1':
7350         case '2':
7351         case '3':
7352         case '4':
7353         case '5':
7354         case '6':
7355         case '7':
7356         case '8':
7357         case '9':
7358                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7359                 if (num < 0 || num > shellparam.nparam)
7360                         return -1;
7361                 p = num ? shellparam.p[num - 1] : arg0;
7362                 goto value;
7363         default:
7364                 /* NB: name has form "VAR=..." */
7365                 p = lookupvar(name);
7366  value:
7367                 if (!p)
7368                         return -1;
7369
7370                 len = strtodest(p, syntax, quotes);
7371 #if ENABLE_UNICODE_SUPPORT
7372                 if (subtype == VSLENGTH && len > 0) {
7373                         reinit_unicode_for_ash();
7374                         if (unicode_status == UNICODE_ON) {
7375                                 STADJUST(-len, expdest);
7376                                 discard = 0;
7377                                 len = unicode_strlen(p);
7378                         }
7379                 }
7380 #endif
7381                 break;
7382         }
7383
7384         if (discard)
7385                 STADJUST(-len, expdest);
7386         return len;
7387 }
7388
7389 /*
7390  * Expand a variable, and return a pointer to the next character in the
7391  * input string.
7392  */
7393 static char *
7394 evalvar(char *p, int flag)
7395 {
7396         char varflags;
7397         char subtype;
7398         int quoted;
7399         char *var;
7400         int patloc;
7401         int startloc;
7402         ssize_t varlen;
7403
7404         varflags = (unsigned char) *p++;
7405         subtype = varflags & VSTYPE;
7406
7407         if (!subtype)
7408                 raise_error_syntax("bad substitution");
7409
7410         quoted = flag & EXP_QUOTED;
7411         var = p;
7412         startloc = expdest - (char *)stackblock();
7413         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7414
7415  again:
7416         varlen = varvalue(var, varflags, flag, quoted);
7417         if (varflags & VSNUL)
7418                 varlen--;
7419
7420         if (subtype == VSPLUS) {
7421                 varlen = -1 - varlen;
7422                 goto vsplus;
7423         }
7424
7425         if (subtype == VSMINUS) {
7426  vsplus:
7427                 if (varlen < 0) {
7428                         argstr(
7429                                 p,
7430                                 flag | EXP_TILDE | EXP_WORD
7431                         );
7432                         goto end;
7433                 }
7434                 goto record;
7435         }
7436
7437         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7438                 if (varlen >= 0)
7439                         goto record;
7440
7441                 subevalvar(p, var, 0, subtype, startloc, varflags,
7442                            flag & ~QUOTES_ESC);
7443                 varflags &= ~VSNUL;
7444                 /*
7445                  * Remove any recorded regions beyond
7446                  * start of variable
7447                  */
7448                 removerecordregions(startloc);
7449                 goto again;
7450         }
7451
7452         if (varlen < 0 && uflag)
7453                 varunset(p, var, 0, 0);
7454
7455         if (subtype == VSLENGTH) {
7456                 cvtnum(varlen > 0 ? varlen : 0);
7457                 goto record;
7458         }
7459
7460         if (subtype == VSNORMAL) {
7461  record:
7462                 if (quoted) {
7463                         quoted = *var == '@' && shellparam.nparam;
7464                         if (!quoted)
7465                                 goto end;
7466                 }
7467                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7468                 goto end;
7469         }
7470
7471 #if DEBUG
7472         switch (subtype) {
7473         case VSTRIMLEFT:
7474         case VSTRIMLEFTMAX:
7475         case VSTRIMRIGHT:
7476         case VSTRIMRIGHTMAX:
7477 #if BASH_SUBSTR
7478         case VSSUBSTR:
7479 #endif
7480 #if BASH_PATTERN_SUBST
7481         case VSREPLACE:
7482         case VSREPLACEALL:
7483 #endif
7484                 break;
7485         default:
7486                 abort();
7487         }
7488 #endif
7489
7490         if (varlen >= 0) {
7491                 /*
7492                  * Terminate the string and start recording the pattern
7493                  * right after it
7494                  */
7495                 STPUTC('\0', expdest);
7496                 patloc = expdest - (char *)stackblock();
7497                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7498                                 startloc, varflags, flag)) {
7499                         int amount = expdest - (
7500                                 (char *)stackblock() + patloc - 1
7501                         );
7502                         STADJUST(-amount, expdest);
7503                 }
7504                 /* Remove any recorded regions beyond start of variable */
7505                 removerecordregions(startloc);
7506                 goto record;
7507         }
7508
7509         varlen = 0;
7510
7511  end:
7512         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7513                 int nesting = 1;
7514                 for (;;) {
7515                         unsigned char c = *p++;
7516                         if (c == CTLESC)
7517                                 p++;
7518                         else if (c == CTLBACKQ) {
7519                                 if (varlen >= 0)
7520                                         argbackq = argbackq->next;
7521                         } else if (c == CTLVAR) {
7522                                 if ((*p++ & VSTYPE) != VSNORMAL)
7523                                         nesting++;
7524                         } else if (c == CTLENDVAR) {
7525                                 if (--nesting == 0)
7526                                         break;
7527                         }
7528                 }
7529         }
7530         return p;
7531 }
7532
7533 /*
7534  * Add a file name to the list.
7535  */
7536 static void
7537 addfname(const char *name)
7538 {
7539         struct strlist *sp;
7540
7541         sp = stzalloc(sizeof(*sp));
7542         sp->text = sstrdup(name);
7543         *exparg.lastp = sp;
7544         exparg.lastp = &sp->next;
7545 }
7546
7547 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7548 static int
7549 hasmeta(const char *p)
7550 {
7551         static const char chars[] ALIGN1 = {
7552                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7553         };
7554
7555         for (;;) {
7556                 p = strpbrk(p, chars);
7557                 if (!p)
7558                         break;
7559                 switch ((unsigned char)*p) {
7560                 case CTLQUOTEMARK:
7561                         for (;;) {
7562                                 p++;
7563                                 if ((unsigned char)*p == CTLQUOTEMARK)
7564                                         break;
7565                                 if ((unsigned char)*p == CTLESC)
7566                                         p++;
7567                                 if (*p == '\0') /* huh? */
7568                                         return 0;
7569                         }
7570                         break;
7571                 case '\\':
7572                 case CTLESC:
7573                         p++;
7574                         if (*p == '\0')
7575                                 return 0;
7576                         break;
7577                 case '[':
7578                         if (!strchr(p + 1, ']')) {
7579                                 /* It's not a properly closed [] pattern,
7580                                  * but other metas may follow. Continue checking.
7581                                  * my[file* _is_ globbed by bash
7582                                  * and matches filenames like "my[file1".
7583                                  */
7584                                 break;
7585                         }
7586                         /* fallthrough */
7587                 default:
7588                 /* case '*': */
7589                 /* case '?': */
7590                         return 1;
7591                 }
7592                 p++;
7593         }
7594
7595         return 0;
7596 }
7597
7598 /* If we want to use glob() from libc... */
7599 #if !ENABLE_ASH_INTERNAL_GLOB
7600
7601 /* Add the result of glob() to the list */
7602 static void
7603 addglob(const glob_t *pglob)
7604 {
7605         char **p = pglob->gl_pathv;
7606
7607         do {
7608                 addfname(*p);
7609         } while (*++p);
7610 }
7611 static void
7612 expandmeta(struct strlist *str /*, int flag*/)
7613 {
7614         /* TODO - EXP_REDIR */
7615
7616         while (str) {
7617                 char *p;
7618                 glob_t pglob;
7619                 int i;
7620
7621                 if (fflag)
7622                         goto nometa;
7623
7624                 if (!hasmeta(str->text))
7625                         goto nometa;
7626
7627                 INT_OFF;
7628                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7629 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7630 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7631 //
7632 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7633 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7634 // Which means you need to unescape the string, right? Not so fast:
7635 // if there _is_ a file named "file\?" (with backslash), it is returned
7636 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7637 // You DON'T KNOW by looking at the result whether you need to unescape it.
7638 //
7639 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7640 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7641 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7642 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7643 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7644 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7645                 i = glob(p, 0, NULL, &pglob);
7646                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7647                 if (p != str->text)
7648                         free(p);
7649                 switch (i) {
7650                 case 0:
7651 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7652                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7653                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7654                                 goto nometa2;
7655 #endif
7656                         addglob(&pglob);
7657                         globfree(&pglob);
7658                         INT_ON;
7659                         break;
7660                 case GLOB_NOMATCH:
7661  //nometa2:
7662                         globfree(&pglob);
7663                         INT_ON;
7664  nometa:
7665                         *exparg.lastp = str;
7666                         rmescapes(str->text, 0, NULL);
7667                         exparg.lastp = &str->next;
7668                         break;
7669                 default:        /* GLOB_NOSPACE */
7670                         globfree(&pglob);
7671                         INT_ON;
7672                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7673                 }
7674                 str = str->next;
7675         }
7676 }
7677
7678 #else
7679 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7680
7681 /*
7682  * Do metacharacter (i.e. *, ?, [...]) expansion.
7683  */
7684 typedef struct exp_t {
7685         char *dir;
7686         unsigned dir_max;
7687 } exp_t;
7688 static void
7689 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7690 {
7691 #define expdir exp->dir
7692 #define expdir_max exp->dir_max
7693         char *enddir = expdir + expdir_len;
7694         char *p;
7695         const char *cp;
7696         char *start;
7697         char *endname;
7698         int metaflag;
7699         struct stat statb;
7700         DIR *dirp;
7701         struct dirent *dp;
7702         int atend;
7703         int matchdot;
7704         int esc;
7705
7706         metaflag = 0;
7707         start = name;
7708         for (p = name; esc = 0, *p; p += esc + 1) {
7709                 if (*p == '*' || *p == '?')
7710                         metaflag = 1;
7711                 else if (*p == '[') {
7712                         char *q = p + 1;
7713                         if (*q == '!')
7714                                 q++;
7715                         for (;;) {
7716                                 if (*q == '\\')
7717                                         q++;
7718                                 if (*q == '/' || *q == '\0')
7719                                         break;
7720                                 if (*++q == ']') {
7721                                         metaflag = 1;
7722                                         break;
7723                                 }
7724                         }
7725                 } else {
7726                         if (*p == '\\' && p[1])
7727                                 esc++;
7728                         if (p[esc] == '/') {
7729                                 if (metaflag)
7730                                         break;
7731                                 start = p + esc + 1;
7732                         }
7733                 }
7734         }
7735         if (metaflag == 0) {    /* we've reached the end of the file name */
7736                 if (!expdir_len)
7737                         return;
7738                 p = name;
7739                 do {
7740                         if (*p == '\\' && p[1])
7741                                 p++;
7742                         *enddir++ = *p;
7743                 } while (*p++);
7744                 if (lstat(expdir, &statb) == 0)
7745                         addfname(expdir);
7746                 return;
7747         }
7748         endname = p;
7749         if (name < start) {
7750                 p = name;
7751                 do {
7752                         if (*p == '\\' && p[1])
7753                                 p++;
7754                         *enddir++ = *p++;
7755                 } while (p < start);
7756         }
7757         *enddir = '\0';
7758         cp = expdir;
7759         expdir_len = enddir - cp;
7760         if (!expdir_len)
7761                 cp = ".";
7762         dirp = opendir(cp);
7763         if (dirp == NULL)
7764                 return;
7765         if (*endname == 0) {
7766                 atend = 1;
7767         } else {
7768                 atend = 0;
7769                 *endname = '\0';
7770                 endname += esc + 1;
7771         }
7772         name_len -= endname - name;
7773         matchdot = 0;
7774         p = start;
7775         if (*p == '\\')
7776                 p++;
7777         if (*p == '.')
7778                 matchdot++;
7779         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7780                 if (dp->d_name[0] == '.' && !matchdot)
7781                         continue;
7782                 if (pmatch(start, dp->d_name)) {
7783                         if (atend) {
7784                                 strcpy(enddir, dp->d_name);
7785                                 addfname(expdir);
7786                         } else {
7787                                 unsigned offset;
7788                                 unsigned len;
7789
7790                                 p = stpcpy(enddir, dp->d_name);
7791                                 *p = '/';
7792
7793                                 offset = p - expdir + 1;
7794                                 len = offset + name_len + NAME_MAX;
7795                                 if (len > expdir_max) {
7796                                         len += PATH_MAX;
7797                                         expdir = ckrealloc(expdir, len);
7798                                         expdir_max = len;
7799                                 }
7800
7801                                 expmeta(exp, endname, name_len, offset);
7802                                 enddir = expdir + expdir_len;
7803                         }
7804                 }
7805         }
7806         closedir(dirp);
7807         if (!atend)
7808                 endname[-esc - 1] = esc ? '\\' : '/';
7809 #undef expdir
7810 #undef expdir_max
7811 }
7812
7813 static struct strlist *
7814 msort(struct strlist *list, int len)
7815 {
7816         struct strlist *p, *q = NULL;
7817         struct strlist **lpp;
7818         int half;
7819         int n;
7820
7821         if (len <= 1)
7822                 return list;
7823         half = len >> 1;
7824         p = list;
7825         for (n = half; --n >= 0;) {
7826                 q = p;
7827                 p = p->next;
7828         }
7829         q->next = NULL;                 /* terminate first half of list */
7830         q = msort(list, half);          /* sort first half of list */
7831         p = msort(p, len - half);               /* sort second half */
7832         lpp = &list;
7833         for (;;) {
7834 #if ENABLE_LOCALE_SUPPORT
7835                 if (strcoll(p->text, q->text) < 0)
7836 #else
7837                 if (strcmp(p->text, q->text) < 0)
7838 #endif
7839                                                 {
7840                         *lpp = p;
7841                         lpp = &p->next;
7842                         p = *lpp;
7843                         if (p == NULL) {
7844                                 *lpp = q;
7845                                 break;
7846                         }
7847                 } else {
7848                         *lpp = q;
7849                         lpp = &q->next;
7850                         q = *lpp;
7851                         if (q == NULL) {
7852                                 *lpp = p;
7853                                 break;
7854                         }
7855                 }
7856         }
7857         return list;
7858 }
7859
7860 /*
7861  * Sort the results of file name expansion.  It calculates the number of
7862  * strings to sort and then calls msort (short for merge sort) to do the
7863  * work.
7864  */
7865 static struct strlist *
7866 expsort(struct strlist *str)
7867 {
7868         int len;
7869         struct strlist *sp;
7870
7871         len = 0;
7872         for (sp = str; sp; sp = sp->next)
7873                 len++;
7874         return msort(str, len);
7875 }
7876
7877 static void
7878 expandmeta(struct strlist *str /*, int flag*/)
7879 {
7880         /* TODO - EXP_REDIR */
7881
7882         while (str) {
7883                 exp_t exp;
7884                 struct strlist **savelastp;
7885                 struct strlist *sp;
7886                 char *p;
7887                 unsigned len;
7888
7889                 if (fflag)
7890                         goto nometa;
7891                 if (!hasmeta(str->text))
7892                         goto nometa;
7893                 savelastp = exparg.lastp;
7894
7895                 INT_OFF;
7896                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7897                 len = strlen(p);
7898                 exp.dir_max = len + PATH_MAX;
7899                 exp.dir = ckmalloc(exp.dir_max);
7900
7901                 expmeta(&exp, p, len, 0);
7902                 free(exp.dir);
7903                 if (p != str->text)
7904                         free(p);
7905                 INT_ON;
7906                 if (exparg.lastp == savelastp) {
7907                         /*
7908                          * no matches
7909                          */
7910  nometa:
7911                         *exparg.lastp = str;
7912                         rmescapes(str->text, 0, NULL);
7913                         exparg.lastp = &str->next;
7914                 } else {
7915                         *exparg.lastp = NULL;
7916                         *savelastp = sp = expsort(*savelastp);
7917                         while (sp->next != NULL)
7918                                 sp = sp->next;
7919                         exparg.lastp = &sp->next;
7920                 }
7921                 str = str->next;
7922         }
7923 }
7924 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7925
7926 /*
7927  * Perform variable substitution and command substitution on an argument,
7928  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7929  * perform splitting and file name expansion.  When arglist is NULL, perform
7930  * here document expansion.
7931  */
7932 static void
7933 expandarg(union node *arg, struct arglist *arglist, int flag)
7934 {
7935         struct strlist *sp;
7936         char *p;
7937
7938         argbackq = arg->narg.backquote;
7939         STARTSTACKSTR(expdest);
7940         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7941         argstr(arg->narg.text, flag);
7942         p = _STPUTC('\0', expdest);
7943         expdest = p - 1;
7944         if (arglist == NULL) {
7945                 /* here document expanded */
7946                 goto out;
7947         }
7948         p = grabstackstr(p);
7949         TRACE(("expandarg: p:'%s'\n", p));
7950         exparg.lastp = &exparg.list;
7951         /*
7952          * TODO - EXP_REDIR
7953          */
7954         if (flag & EXP_FULL) {
7955                 ifsbreakup(p, &exparg);
7956                 *exparg.lastp = NULL;
7957                 exparg.lastp = &exparg.list;
7958                 expandmeta(exparg.list /*, flag*/);
7959         } else {
7960                 sp = stzalloc(sizeof(*sp));
7961                 sp->text = p;
7962                 *exparg.lastp = sp;
7963                 exparg.lastp = &sp->next;
7964         }
7965         *exparg.lastp = NULL;
7966         if (exparg.list) {
7967                 *arglist->lastp = exparg.list;
7968                 arglist->lastp = exparg.lastp;
7969         }
7970
7971  out:
7972         ifsfree();
7973 }
7974
7975 /*
7976  * Expand shell variables and backquotes inside a here document.
7977  */
7978 static void
7979 expandhere(union node *arg, int fd)
7980 {
7981         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7982         full_write(fd, stackblock(), expdest - (char *)stackblock());
7983 }
7984
7985 /*
7986  * Returns true if the pattern matches the string.
7987  */
7988 static int
7989 patmatch(char *pattern, const char *string)
7990 {
7991         char *p = preglob(pattern, 0);
7992         int r = pmatch(p, string);
7993         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7994         return r;
7995 }
7996
7997 /*
7998  * See if a pattern matches in a case statement.
7999  */
8000 static int
8001 casematch(union node *pattern, char *val)
8002 {
8003         struct stackmark smark;
8004         int result;
8005
8006         setstackmark(&smark);
8007         argbackq = pattern->narg.backquote;
8008         STARTSTACKSTR(expdest);
8009         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8010         STACKSTRNUL(expdest);
8011         ifsfree();
8012         result = patmatch(stackblock(), val);
8013         popstackmark(&smark);
8014         return result;
8015 }
8016
8017
8018 /* ============ find_command */
8019
8020 struct builtincmd {
8021         const char *name;
8022         int (*builtin)(int, char **) FAST_FUNC;
8023         /* unsigned flags; */
8024 };
8025 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8026 /* "regular" builtins always take precedence over commands,
8027  * regardless of PATH=....%builtin... position */
8028 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8029 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
8030
8031 struct cmdentry {
8032         smallint cmdtype;       /* CMDxxx */
8033         union param {
8034                 int index;
8035                 /* index >= 0 for commands without path (slashes) */
8036                 /* (TODO: what exactly does the value mean? PATH position?) */
8037                 /* index == -1 for commands with slashes */
8038                 /* index == (-2 - applet_no) for NOFORK applets */
8039                 const struct builtincmd *cmd;
8040                 struct funcnode *func;
8041         } u;
8042 };
8043 /* values of cmdtype */
8044 #define CMDUNKNOWN      -1      /* no entry in table for command */
8045 #define CMDNORMAL       0       /* command is an executable program */
8046 #define CMDFUNCTION     1       /* command is a shell function */
8047 #define CMDBUILTIN      2       /* command is a shell builtin */
8048
8049 /* action to find_command() */
8050 #define DO_ERR          0x01    /* prints errors */
8051 #define DO_ABS          0x02    /* checks absolute paths */
8052 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
8053 #define DO_ALTPATH      0x08    /* using alternate path */
8054 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
8055
8056 static void find_command(char *, struct cmdentry *, int, const char *);
8057
8058
8059 /* ============ Hashing commands */
8060
8061 /*
8062  * When commands are first encountered, they are entered in a hash table.
8063  * This ensures that a full path search will not have to be done for them
8064  * on each invocation.
8065  *
8066  * We should investigate converting to a linear search, even though that
8067  * would make the command name "hash" a misnomer.
8068  */
8069
8070 struct tblentry {
8071         struct tblentry *next;  /* next entry in hash chain */
8072         union param param;      /* definition of builtin function */
8073         smallint cmdtype;       /* CMDxxx */
8074         char rehash;            /* if set, cd done since entry created */
8075         char cmdname[1];        /* name of command */
8076 };
8077
8078 static struct tblentry **cmdtable;
8079 #define INIT_G_cmdtable() do { \
8080         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8081 } while (0)
8082
8083 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8084
8085
8086 static void
8087 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8088 {
8089 #if ENABLE_FEATURE_SH_STANDALONE
8090         if (applet_no >= 0) {
8091                 if (APPLET_IS_NOEXEC(applet_no)) {
8092                         clearenv();
8093                         while (*envp)
8094                                 putenv(*envp++);
8095                         popredir(/*drop:*/ 1);
8096                         run_noexec_applet_and_exit(applet_no, cmd, argv);
8097                 }
8098                 /* re-exec ourselves with the new arguments */
8099                 execve(bb_busybox_exec_path, argv, envp);
8100                 /* If they called chroot or otherwise made the binary no longer
8101                  * executable, fall through */
8102         }
8103 #endif
8104
8105  repeat:
8106 #ifdef SYSV
8107         do {
8108                 execve(cmd, argv, envp);
8109         } while (errno == EINTR);
8110 #else
8111         execve(cmd, argv, envp);
8112 #endif
8113
8114         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8115                 /* Run "cmd" as a shell script:
8116                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8117                  * "If the execve() function fails with ENOEXEC, the shell
8118                  * shall execute a command equivalent to having a shell invoked
8119                  * with the command name as its first operand,
8120                  * with any remaining arguments passed to the new shell"
8121                  *
8122                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8123                  * just call ourselves.
8124                  *
8125                  * Note that bash reads ~80 chars of the file, and if it sees
8126                  * a zero byte before it sees newline, it doesn't try to
8127                  * interpret it, but fails with "cannot execute binary file"
8128                  * message and exit code 126. For one, this prevents attempts
8129                  * to interpret foreign ELF binaries as shell scripts.
8130                  */
8131                 argv[0] = (char*) cmd;
8132                 cmd = bb_busybox_exec_path;
8133                 /* NB: this is only possible because all callers of shellexec()
8134                  * ensure that the argv[-1] slot exists!
8135                  */
8136                 argv--;
8137                 argv[0] = (char*) "ash";
8138                 goto repeat;
8139         }
8140 }
8141
8142 /*
8143  * Exec a program.  Never returns.  If you change this routine, you may
8144  * have to change the find_command routine as well.
8145  * argv[-1] must exist and be writable! See tryexec() for why.
8146  */
8147 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8148 static void shellexec(char *prog, char **argv, const char *path, int idx)
8149 {
8150         char *cmdname;
8151         int e;
8152         char **envp;
8153         int exerrno;
8154         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8155
8156         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8157         if (strchr(prog, '/') != NULL
8158 #if ENABLE_FEATURE_SH_STANDALONE
8159          || (applet_no = find_applet_by_name(prog)) >= 0
8160 #endif
8161         ) {
8162                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8163                 if (applet_no >= 0) {
8164                         /* We tried execing ourself, but it didn't work.
8165                          * Maybe /proc/self/exe doesn't exist?
8166                          * Try $PATH search.
8167                          */
8168                         goto try_PATH;
8169                 }
8170                 e = errno;
8171         } else {
8172  try_PATH:
8173                 e = ENOENT;
8174                 while (padvance(&path, argv[0]) >= 0) {
8175                         cmdname = stackblock();
8176                         if (--idx < 0 && pathopt == NULL) {
8177                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8178                                 if (errno != ENOENT && errno != ENOTDIR)
8179                                         e = errno;
8180                         }
8181                 }
8182         }
8183
8184         /* Map to POSIX errors */
8185         switch (e) {
8186         default:
8187                 exerrno = 126;
8188                 break;
8189         case ELOOP:
8190         case ENAMETOOLONG:
8191         case ENOENT:
8192         case ENOTDIR:
8193                 exerrno = 127;
8194                 break;
8195         }
8196         exitstatus = exerrno;
8197         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8198                 prog, e, suppress_int));
8199         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8200         /* NOTREACHED */
8201 }
8202
8203 static void
8204 printentry(struct tblentry *cmdp)
8205 {
8206         int idx;
8207         const char *path;
8208         char *name;
8209
8210         idx = cmdp->param.index;
8211         path = pathval();
8212         do {
8213                 padvance(&path, cmdp->cmdname);
8214         } while (--idx >= 0);
8215         name = stackblock();
8216         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8217 }
8218
8219 /*
8220  * Clear out command entries.  The argument specifies the first entry in
8221  * PATH which has changed.
8222  */
8223 static void
8224 clearcmdentry(int firstchange)
8225 {
8226         struct tblentry **tblp;
8227         struct tblentry **pp;
8228         struct tblentry *cmdp;
8229
8230         INT_OFF;
8231         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8232                 pp = tblp;
8233                 while ((cmdp = *pp) != NULL) {
8234                         if ((cmdp->cmdtype == CMDNORMAL &&
8235                              cmdp->param.index >= firstchange)
8236                          || (cmdp->cmdtype == CMDBUILTIN &&
8237                              builtinloc >= firstchange)
8238                         ) {
8239                                 *pp = cmdp->next;
8240                                 free(cmdp);
8241                         } else {
8242                                 pp = &cmdp->next;
8243                         }
8244                 }
8245         }
8246         INT_ON;
8247 }
8248
8249 /*
8250  * Locate a command in the command hash table.  If "add" is nonzero,
8251  * add the command to the table if it is not already present.  The
8252  * variable "lastcmdentry" is set to point to the address of the link
8253  * pointing to the entry, so that delete_cmd_entry can delete the
8254  * entry.
8255  *
8256  * Interrupts must be off if called with add != 0.
8257  */
8258 static struct tblentry **lastcmdentry;
8259
8260 static struct tblentry *
8261 cmdlookup(const char *name, int add)
8262 {
8263         unsigned int hashval;
8264         const char *p;
8265         struct tblentry *cmdp;
8266         struct tblentry **pp;
8267
8268         p = name;
8269         hashval = (unsigned char)*p << 4;
8270         while (*p)
8271                 hashval += (unsigned char)*p++;
8272         hashval &= 0x7FFF;
8273         pp = &cmdtable[hashval % CMDTABLESIZE];
8274         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8275                 if (strcmp(cmdp->cmdname, name) == 0)
8276                         break;
8277                 pp = &cmdp->next;
8278         }
8279         if (add && cmdp == NULL) {
8280                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8281                                 + strlen(name)
8282                                 /* + 1 - already done because
8283                                  * tblentry::cmdname is char[1] */);
8284                 /*cmdp->next = NULL; - ckzalloc did it */
8285                 cmdp->cmdtype = CMDUNKNOWN;
8286                 strcpy(cmdp->cmdname, name);
8287         }
8288         lastcmdentry = pp;
8289         return cmdp;
8290 }
8291
8292 /*
8293  * Delete the command entry returned on the last lookup.
8294  */
8295 static void
8296 delete_cmd_entry(void)
8297 {
8298         struct tblentry *cmdp;
8299
8300         INT_OFF;
8301         cmdp = *lastcmdentry;
8302         *lastcmdentry = cmdp->next;
8303         if (cmdp->cmdtype == CMDFUNCTION)
8304                 freefunc(cmdp->param.func);
8305         free(cmdp);
8306         INT_ON;
8307 }
8308
8309 /*
8310  * Add a new command entry, replacing any existing command entry for
8311  * the same name - except special builtins.
8312  */
8313 static void
8314 addcmdentry(char *name, struct cmdentry *entry)
8315 {
8316         struct tblentry *cmdp;
8317
8318         cmdp = cmdlookup(name, 1);
8319         if (cmdp->cmdtype == CMDFUNCTION) {
8320                 freefunc(cmdp->param.func);
8321         }
8322         cmdp->cmdtype = entry->cmdtype;
8323         cmdp->param = entry->u;
8324         cmdp->rehash = 0;
8325 }
8326
8327 static int FAST_FUNC
8328 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8329 {
8330         struct tblentry **pp;
8331         struct tblentry *cmdp;
8332         int c;
8333         struct cmdentry entry;
8334         char *name;
8335
8336         if (nextopt("r") != '\0') {
8337                 clearcmdentry(0);
8338                 return 0;
8339         }
8340
8341         if (*argptr == NULL) {
8342                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8343                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8344                                 if (cmdp->cmdtype == CMDNORMAL)
8345                                         printentry(cmdp);
8346                         }
8347                 }
8348                 return 0;
8349         }
8350
8351         c = 0;
8352         while ((name = *argptr) != NULL) {
8353                 cmdp = cmdlookup(name, 0);
8354                 if (cmdp != NULL
8355                  && (cmdp->cmdtype == CMDNORMAL
8356                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8357                 ) {
8358                         delete_cmd_entry();
8359                 }
8360                 find_command(name, &entry, DO_ERR, pathval());
8361                 if (entry.cmdtype == CMDUNKNOWN)
8362                         c = 1;
8363                 argptr++;
8364         }
8365         return c;
8366 }
8367
8368 /*
8369  * Called when a cd is done.  Marks all commands so the next time they
8370  * are executed they will be rehashed.
8371  */
8372 static void
8373 hashcd(void)
8374 {
8375         struct tblentry **pp;
8376         struct tblentry *cmdp;
8377
8378         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8379                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8380                         if (cmdp->cmdtype == CMDNORMAL
8381                          || (cmdp->cmdtype == CMDBUILTIN
8382                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8383                              && builtinloc > 0)
8384                         ) {
8385                                 cmdp->rehash = 1;
8386                         }
8387                 }
8388         }
8389 }
8390
8391 /*
8392  * Fix command hash table when PATH changed.
8393  * Called before PATH is changed.  The argument is the new value of PATH;
8394  * pathval() still returns the old value at this point.
8395  * Called with interrupts off.
8396  */
8397 static void FAST_FUNC
8398 changepath(const char *new)
8399 {
8400         const char *old;
8401         int firstchange;
8402         int idx;
8403         int idx_bltin;
8404
8405         old = pathval();
8406         firstchange = 9999;     /* assume no change */
8407         idx = 0;
8408         idx_bltin = -1;
8409         for (;;) {
8410                 if (*old != *new) {
8411                         firstchange = idx;
8412                         if ((*old == '\0' && *new == ':')
8413                          || (*old == ':' && *new == '\0')
8414                         ) {
8415                                 firstchange++;
8416                         }
8417                         old = new;      /* ignore subsequent differences */
8418                 }
8419                 if (*new == '\0')
8420                         break;
8421                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8422                         idx_bltin = idx;
8423                 if (*new == ':')
8424                         idx++;
8425                 new++;
8426                 old++;
8427         }
8428         if (builtinloc < 0 && idx_bltin >= 0)
8429                 builtinloc = idx_bltin;             /* zap builtins */
8430         if (builtinloc >= 0 && idx_bltin < 0)
8431                 firstchange = 0;
8432         clearcmdentry(firstchange);
8433         builtinloc = idx_bltin;
8434 }
8435 enum {
8436         TEOF,
8437         TNL,
8438         TREDIR,
8439         TWORD,
8440         TSEMI,
8441         TBACKGND,
8442         TAND,
8443         TOR,
8444         TPIPE,
8445         TLP,
8446         TRP,
8447         TENDCASE,
8448         TENDBQUOTE,
8449         TNOT,
8450         TCASE,
8451         TDO,
8452         TDONE,
8453         TELIF,
8454         TELSE,
8455         TESAC,
8456         TFI,
8457         TFOR,
8458 #if BASH_FUNCTION
8459         TFUNCTION,
8460 #endif
8461         TIF,
8462         TIN,
8463         TTHEN,
8464         TUNTIL,
8465         TWHILE,
8466         TBEGIN,
8467         TEND
8468 };
8469 typedef smallint token_id_t;
8470
8471 /* Nth bit indicates if token marks the end of a list */
8472 enum {
8473         tokendlist = 0
8474         /*  0 */ | (1u << TEOF)
8475         /*  1 */ | (0u << TNL)
8476         /*  2 */ | (0u << TREDIR)
8477         /*  3 */ | (0u << TWORD)
8478         /*  4 */ | (0u << TSEMI)
8479         /*  5 */ | (0u << TBACKGND)
8480         /*  6 */ | (0u << TAND)
8481         /*  7 */ | (0u << TOR)
8482         /*  8 */ | (0u << TPIPE)
8483         /*  9 */ | (0u << TLP)
8484         /* 10 */ | (1u << TRP)
8485         /* 11 */ | (1u << TENDCASE)
8486         /* 12 */ | (1u << TENDBQUOTE)
8487         /* 13 */ | (0u << TNOT)
8488         /* 14 */ | (0u << TCASE)
8489         /* 15 */ | (1u << TDO)
8490         /* 16 */ | (1u << TDONE)
8491         /* 17 */ | (1u << TELIF)
8492         /* 18 */ | (1u << TELSE)
8493         /* 19 */ | (1u << TESAC)
8494         /* 20 */ | (1u << TFI)
8495         /* 21 */ | (0u << TFOR)
8496 #if BASH_FUNCTION
8497         /* 22 */ | (0u << TFUNCTION)
8498 #endif
8499         /* 23 */ | (0u << TIF)
8500         /* 24 */ | (0u << TIN)
8501         /* 25 */ | (1u << TTHEN)
8502         /* 26 */ | (0u << TUNTIL)
8503         /* 27 */ | (0u << TWHILE)
8504         /* 28 */ | (0u << TBEGIN)
8505         /* 29 */ | (1u << TEND)
8506         , /* thus far 29 bits used */
8507 };
8508
8509 static const char *const tokname_array[] = {
8510         "end of file",
8511         "newline",
8512         "redirection",
8513         "word",
8514         ";",
8515         "&",
8516         "&&",
8517         "||",
8518         "|",
8519         "(",
8520         ")",
8521         ";;",
8522         "`",
8523 #define KWDOFFSET 13
8524         /* the following are keywords */
8525         "!",
8526         "case",
8527         "do",
8528         "done",
8529         "elif",
8530         "else",
8531         "esac",
8532         "fi",
8533         "for",
8534 #if BASH_FUNCTION
8535         "function",
8536 #endif
8537         "if",
8538         "in",
8539         "then",
8540         "until",
8541         "while",
8542         "{",
8543         "}",
8544 };
8545
8546 /* Wrapper around strcmp for qsort/bsearch/... */
8547 static int
8548 pstrcmp(const void *a, const void *b)
8549 {
8550         return strcmp((char*)a, *(char**)b);
8551 }
8552
8553 static const char *const *
8554 findkwd(const char *s)
8555 {
8556         return bsearch(s, tokname_array + KWDOFFSET,
8557                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8558                         sizeof(tokname_array[0]), pstrcmp);
8559 }
8560
8561 /*
8562  * Locate and print what a word is...
8563  */
8564 static int
8565 describe_command(char *command, const char *path, int describe_command_verbose)
8566 {
8567         struct cmdentry entry;
8568 #if ENABLE_ASH_ALIAS
8569         const struct alias *ap;
8570 #endif
8571
8572         path = path ? path : pathval();
8573
8574         if (describe_command_verbose) {
8575                 out1str(command);
8576         }
8577
8578         /* First look at the keywords */
8579         if (findkwd(command)) {
8580                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8581                 goto out;
8582         }
8583
8584 #if ENABLE_ASH_ALIAS
8585         /* Then look at the aliases */
8586         ap = lookupalias(command, 0);
8587         if (ap != NULL) {
8588                 if (!describe_command_verbose) {
8589                         out1str("alias ");
8590                         printalias(ap);
8591                         return 0;
8592                 }
8593                 out1fmt(" is an alias for %s", ap->val);
8594                 goto out;
8595         }
8596 #endif
8597         /* Brute force */
8598         find_command(command, &entry, DO_ABS, path);
8599
8600         switch (entry.cmdtype) {
8601         case CMDNORMAL: {
8602                 int j = entry.u.index;
8603                 char *p;
8604                 if (j < 0) {
8605                         p = command;
8606                 } else {
8607                         do {
8608                                 padvance(&path, command);
8609                         } while (--j >= 0);
8610                         p = stackblock();
8611                 }
8612                 if (describe_command_verbose) {
8613                         out1fmt(" is %s", p);
8614                 } else {
8615                         out1str(p);
8616                 }
8617                 break;
8618         }
8619
8620         case CMDFUNCTION:
8621                 if (describe_command_verbose) {
8622                         /*out1str(" is a shell function");*/
8623                         out1str(" is a function"); /* bash says this */
8624                 } else {
8625                         out1str(command);
8626                 }
8627                 break;
8628
8629         case CMDBUILTIN:
8630                 if (describe_command_verbose) {
8631                         out1fmt(" is a %sshell builtin",
8632                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8633                                         "special " : nullstr
8634                         );
8635                 } else {
8636                         out1str(command);
8637                 }
8638                 break;
8639
8640         default:
8641                 if (describe_command_verbose) {
8642                         out1str(": not found\n");
8643                 }
8644                 return 127;
8645         }
8646  out:
8647         out1str("\n");
8648         return 0;
8649 }
8650
8651 static int FAST_FUNC
8652 typecmd(int argc UNUSED_PARAM, char **argv)
8653 {
8654         int i = 1;
8655         int err = 0;
8656         int verbose = 1;
8657
8658         /* type -p ... ? (we don't bother checking for 'p') */
8659         if (argv[1] && argv[1][0] == '-') {
8660                 i++;
8661                 verbose = 0;
8662         }
8663         while (argv[i]) {
8664                 err |= describe_command(argv[i++], NULL, verbose);
8665         }
8666         return err;
8667 }
8668
8669 #if ENABLE_ASH_CMDCMD
8670 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8671 static char **
8672 parse_command_args(char **argv, const char **path)
8673 {
8674         char *cp, c;
8675
8676         for (;;) {
8677                 cp = *++argv;
8678                 if (!cp)
8679                         return NULL;
8680                 if (*cp++ != '-')
8681                         break;
8682                 c = *cp++;
8683                 if (!c)
8684                         break;
8685                 if (c == '-' && !*cp) {
8686                         if (!*++argv)
8687                                 return NULL;
8688                         break;
8689                 }
8690                 do {
8691                         switch (c) {
8692                         case 'p':
8693                                 *path = bb_default_path;
8694                                 break;
8695                         default:
8696                                 /* run 'typecmd' for other options */
8697                                 return NULL;
8698                         }
8699                         c = *cp++;
8700                 } while (c);
8701         }
8702         return argv;
8703 }
8704
8705 static int FAST_FUNC
8706 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8707 {
8708         char *cmd;
8709         int c;
8710         enum {
8711                 VERIFY_BRIEF = 1,
8712                 VERIFY_VERBOSE = 2,
8713         } verify = 0;
8714         const char *path = NULL;
8715
8716         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8717          * never reaches this function.
8718          */
8719
8720         while ((c = nextopt("pvV")) != '\0')
8721                 if (c == 'V')
8722                         verify |= VERIFY_VERBOSE;
8723                 else if (c == 'v')
8724                         /*verify |= VERIFY_BRIEF*/;
8725 #if DEBUG
8726                 else if (c != 'p')
8727                         abort();
8728 #endif
8729                 else
8730                         path = bb_default_path;
8731
8732         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8733         cmd = *argptr;
8734         if (/*verify && */ cmd)
8735                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8736
8737         return 0;
8738 }
8739 #endif
8740
8741
8742 /*static int funcblocksize;     // size of structures in function */
8743 /*static int funcstringsize;    // size of strings in node */
8744 static void *funcblock;         /* block to allocate function from */
8745 static char *funcstring_end;    /* end of block to allocate strings from */
8746
8747 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8748         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8749         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8750         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8751         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8752         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8753         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8754         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8755         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8756         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8757         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8758         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8759         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8760         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8761         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8762         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8763         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8764         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8765 #if BASH_REDIR_OUTPUT
8766         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8767 #endif
8768         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8769         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8770         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8771         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8772         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8773         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8774         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8775         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8776         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8777 };
8778
8779 static int calcsize(int funcblocksize, union node *n);
8780
8781 static int
8782 sizenodelist(int funcblocksize, struct nodelist *lp)
8783 {
8784         while (lp) {
8785                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8786                 funcblocksize = calcsize(funcblocksize, lp->n);
8787                 lp = lp->next;
8788         }
8789         return funcblocksize;
8790 }
8791
8792 static int
8793 calcsize(int funcblocksize, union node *n)
8794 {
8795         if (n == NULL)
8796                 return funcblocksize;
8797         funcblocksize += nodesize[n->type];
8798         switch (n->type) {
8799         case NCMD:
8800                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8801                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8802                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8803                 break;
8804         case NPIPE:
8805                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8806                 break;
8807         case NREDIR:
8808         case NBACKGND:
8809         case NSUBSHELL:
8810                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8811                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8812                 break;
8813         case NAND:
8814         case NOR:
8815         case NSEMI:
8816         case NWHILE:
8817         case NUNTIL:
8818                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8819                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8820                 break;
8821         case NIF:
8822                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8823                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8824                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8825                 break;
8826         case NFOR:
8827                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8828                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8829                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8830                 break;
8831         case NCASE:
8832                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8833                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8834                 break;
8835         case NCLIST:
8836                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8837                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8838                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8839                 break;
8840         case NDEFUN:
8841                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8842                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8843                 break;
8844         case NARG:
8845                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8846                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8847                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8848                 break;
8849         case NTO:
8850 #if BASH_REDIR_OUTPUT
8851         case NTO2:
8852 #endif
8853         case NCLOBBER:
8854         case NFROM:
8855         case NFROMTO:
8856         case NAPPEND:
8857                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8858                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8859                 break;
8860         case NTOFD:
8861         case NFROMFD:
8862                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8863                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8864         break;
8865         case NHERE:
8866         case NXHERE:
8867                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8868                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8869                 break;
8870         case NNOT:
8871                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8872                 break;
8873         };
8874         return funcblocksize;
8875 }
8876
8877 static char *
8878 nodeckstrdup(char *s)
8879 {
8880         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8881         return strcpy(funcstring_end, s);
8882 }
8883
8884 static union node *copynode(union node *);
8885
8886 static struct nodelist *
8887 copynodelist(struct nodelist *lp)
8888 {
8889         struct nodelist *start;
8890         struct nodelist **lpp;
8891
8892         lpp = &start;
8893         while (lp) {
8894                 *lpp = funcblock;
8895                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8896                 (*lpp)->n = copynode(lp->n);
8897                 lp = lp->next;
8898                 lpp = &(*lpp)->next;
8899         }
8900         *lpp = NULL;
8901         return start;
8902 }
8903
8904 static union node *
8905 copynode(union node *n)
8906 {
8907         union node *new;
8908
8909         if (n == NULL)
8910                 return NULL;
8911         new = funcblock;
8912         funcblock = (char *) funcblock + nodesize[n->type];
8913
8914         switch (n->type) {
8915         case NCMD:
8916                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8917                 new->ncmd.args = copynode(n->ncmd.args);
8918                 new->ncmd.assign = copynode(n->ncmd.assign);
8919                 new->ncmd.linno = n->ncmd.linno;
8920                 break;
8921         case NPIPE:
8922                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8923                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8924                 break;
8925         case NREDIR:
8926         case NBACKGND:
8927         case NSUBSHELL:
8928                 new->nredir.redirect = copynode(n->nredir.redirect);
8929                 new->nredir.n = copynode(n->nredir.n);
8930                 new->nredir.linno = n->nredir.linno;
8931                 break;
8932         case NAND:
8933         case NOR:
8934         case NSEMI:
8935         case NWHILE:
8936         case NUNTIL:
8937                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8938                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8939                 break;
8940         case NIF:
8941                 new->nif.elsepart = copynode(n->nif.elsepart);
8942                 new->nif.ifpart = copynode(n->nif.ifpart);
8943                 new->nif.test = copynode(n->nif.test);
8944                 break;
8945         case NFOR:
8946                 new->nfor.var = nodeckstrdup(n->nfor.var);
8947                 new->nfor.body = copynode(n->nfor.body);
8948                 new->nfor.args = copynode(n->nfor.args);
8949                 new->nfor.linno = n->nfor.linno;
8950                 break;
8951         case NCASE:
8952                 new->ncase.cases = copynode(n->ncase.cases);
8953                 new->ncase.expr = copynode(n->ncase.expr);
8954                 new->ncase.linno = n->ncase.linno;
8955                 break;
8956         case NCLIST:
8957                 new->nclist.body = copynode(n->nclist.body);
8958                 new->nclist.pattern = copynode(n->nclist.pattern);
8959                 new->nclist.next = copynode(n->nclist.next);
8960                 break;
8961         case NDEFUN:
8962                 new->ndefun.body = copynode(n->ndefun.body);
8963                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8964                 new->ndefun.linno = n->ndefun.linno;
8965                 break;
8966         case NARG:
8967                 new->narg.backquote = copynodelist(n->narg.backquote);
8968                 new->narg.text = nodeckstrdup(n->narg.text);
8969                 new->narg.next = copynode(n->narg.next);
8970                 break;
8971         case NTO:
8972 #if BASH_REDIR_OUTPUT
8973         case NTO2:
8974 #endif
8975         case NCLOBBER:
8976         case NFROM:
8977         case NFROMTO:
8978         case NAPPEND:
8979                 new->nfile.fname = copynode(n->nfile.fname);
8980                 new->nfile.fd = n->nfile.fd;
8981                 new->nfile.next = copynode(n->nfile.next);
8982                 break;
8983         case NTOFD:
8984         case NFROMFD:
8985                 new->ndup.vname = copynode(n->ndup.vname);
8986                 new->ndup.dupfd = n->ndup.dupfd;
8987                 new->ndup.fd = n->ndup.fd;
8988                 new->ndup.next = copynode(n->ndup.next);
8989                 break;
8990         case NHERE:
8991         case NXHERE:
8992                 new->nhere.doc = copynode(n->nhere.doc);
8993                 new->nhere.fd = n->nhere.fd;
8994                 new->nhere.next = copynode(n->nhere.next);
8995                 break;
8996         case NNOT:
8997                 new->nnot.com = copynode(n->nnot.com);
8998                 break;
8999         };
9000         new->type = n->type;
9001         return new;
9002 }
9003
9004 /*
9005  * Make a copy of a parse tree.
9006  */
9007 static struct funcnode *
9008 copyfunc(union node *n)
9009 {
9010         struct funcnode *f;
9011         size_t blocksize;
9012
9013         /*funcstringsize = 0;*/
9014         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
9015         f = ckzalloc(blocksize /* + funcstringsize */);
9016         funcblock = (char *) f + offsetof(struct funcnode, n);
9017         funcstring_end = (char *) f + blocksize;
9018         copynode(n);
9019         /* f->count = 0; - ckzalloc did it */
9020         return f;
9021 }
9022
9023 /*
9024  * Define a shell function.
9025  */
9026 static void
9027 defun(union node *func)
9028 {
9029         struct cmdentry entry;
9030
9031         INT_OFF;
9032         entry.cmdtype = CMDFUNCTION;
9033         entry.u.func = copyfunc(func);
9034         addcmdentry(func->ndefun.text, &entry);
9035         INT_ON;
9036 }
9037
9038 /* Reasons for skipping commands (see comment on breakcmd routine) */
9039 #define SKIPBREAK      (1 << 0)
9040 #define SKIPCONT       (1 << 1)
9041 #define SKIPFUNC       (1 << 2)
9042 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
9043 static int skipcount;           /* number of levels to skip */
9044 static int loopnest;            /* current loop nesting level */
9045 static int funcline;            /* starting line number of current function, or 0 if not in a function */
9046
9047 /* Forward decl way out to parsing code - dotrap needs it */
9048 static int evalstring(char *s, int flags);
9049
9050 /* Called to execute a trap.
9051  * Single callsite - at the end of evaltree().
9052  * If we return non-zero, evaltree raises EXEXIT exception.
9053  *
9054  * Perhaps we should avoid entering new trap handlers
9055  * while we are executing a trap handler. [is it a TODO?]
9056  */
9057 static void
9058 dotrap(void)
9059 {
9060         uint8_t *g;
9061         int sig;
9062         int status, last_status;
9063
9064         if (!pending_sig)
9065                 return;
9066
9067         status = savestatus;
9068         last_status = status;
9069         if (status < 0) {
9070                 status = exitstatus;
9071                 savestatus = status;
9072         }
9073         pending_sig = 0;
9074         barrier();
9075
9076         TRACE(("dotrap entered\n"));
9077         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9078                 char *p;
9079
9080                 if (!*g)
9081                         continue;
9082
9083                 if (evalskip) {
9084                         pending_sig = sig;
9085                         break;
9086                 }
9087
9088                 p = trap[sig];
9089                 /* non-trapped SIGINT is handled separately by raise_interrupt,
9090                  * don't upset it by resetting gotsig[SIGINT-1] */
9091                 if (sig == SIGINT && !p)
9092                         continue;
9093
9094                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9095                 *g = 0;
9096                 if (!p)
9097                         continue;
9098                 evalstring(p, 0);
9099                 exitstatus = status;
9100         }
9101
9102         savestatus = last_status;
9103         TRACE(("dotrap returns\n"));
9104 }
9105
9106 /* forward declarations - evaluation is fairly recursive business... */
9107 static int evalloop(union node *, int);
9108 static int evalfor(union node *, int);
9109 static int evalcase(union node *, int);
9110 static int evalsubshell(union node *, int);
9111 static void expredir(union node *);
9112 static int evalpipe(union node *, int);
9113 static int evalcommand(union node *, int);
9114 static int evalbltin(const struct builtincmd *, int, char **, int);
9115 static void prehash(union node *);
9116
9117 /*
9118  * Evaluate a parse tree.  The value is left in the global variable
9119  * exitstatus.
9120  */
9121 static int
9122 evaltree(union node *n, int flags)
9123 {
9124         int checkexit = 0;
9125         int (*evalfn)(union node *, int);
9126         struct stackmark smark;
9127         int status = 0;
9128
9129         setstackmark(&smark);
9130
9131         if (n == NULL) {
9132                 TRACE(("evaltree(NULL) called\n"));
9133                 goto out;
9134         }
9135         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9136
9137         dotrap();
9138
9139         switch (n->type) {
9140         default:
9141 #if DEBUG
9142                 out1fmt("Node type = %d\n", n->type);
9143                 fflush_all();
9144                 break;
9145 #endif
9146         case NNOT:
9147                 status = !evaltree(n->nnot.com, EV_TESTED);
9148                 goto setstatus;
9149         case NREDIR:
9150                 errlinno = lineno = n->nredir.linno;
9151                 if (funcline)
9152                         lineno -= funcline - 1;
9153                 expredir(n->nredir.redirect);
9154                 pushredir(n->nredir.redirect);
9155                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9156                 if (!status) {
9157                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9158                 }
9159                 if (n->nredir.redirect)
9160                         popredir(/*drop:*/ 0);
9161                 goto setstatus;
9162         case NCMD:
9163                 evalfn = evalcommand;
9164  checkexit:
9165                 if (eflag && !(flags & EV_TESTED))
9166                         checkexit = ~0;
9167                 goto calleval;
9168         case NFOR:
9169                 evalfn = evalfor;
9170                 goto calleval;
9171         case NWHILE:
9172         case NUNTIL:
9173                 evalfn = evalloop;
9174                 goto calleval;
9175         case NSUBSHELL:
9176         case NBACKGND:
9177                 evalfn = evalsubshell;
9178                 goto checkexit;
9179         case NPIPE:
9180                 evalfn = evalpipe;
9181                 goto checkexit;
9182         case NCASE:
9183                 evalfn = evalcase;
9184                 goto calleval;
9185         case NAND:
9186         case NOR:
9187         case NSEMI: {
9188
9189 #if NAND + 1 != NOR
9190 #error NAND + 1 != NOR
9191 #endif
9192 #if NOR + 1 != NSEMI
9193 #error NOR + 1 != NSEMI
9194 #endif
9195                 unsigned is_or = n->type - NAND;
9196                 status = evaltree(
9197                         n->nbinary.ch1,
9198                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9199                 );
9200                 if ((!status) == is_or || evalskip)
9201                         break;
9202                 n = n->nbinary.ch2;
9203  evaln:
9204                 evalfn = evaltree;
9205  calleval:
9206                 status = evalfn(n, flags);
9207                 goto setstatus;
9208         }
9209         case NIF:
9210                 status = evaltree(n->nif.test, EV_TESTED);
9211                 if (evalskip)
9212                         break;
9213                 if (!status) {
9214                         n = n->nif.ifpart;
9215                         goto evaln;
9216                 }
9217                 if (n->nif.elsepart) {
9218                         n = n->nif.elsepart;
9219                         goto evaln;
9220                 }
9221                 status = 0;
9222                 goto setstatus;
9223         case NDEFUN:
9224                 defun(n);
9225                 /* Not necessary. To test it:
9226                  * "false; f() { qwerty; }; echo $?" should print 0.
9227                  */
9228                 /* status = 0; */
9229  setstatus:
9230                 exitstatus = status;
9231                 break;
9232         }
9233  out:
9234         /* Order of checks below is important:
9235          * signal handlers trigger before exit caused by "set -e".
9236          */
9237         dotrap();
9238
9239         if (checkexit & status)
9240                 raise_exception(EXEXIT);
9241         if (flags & EV_EXIT)
9242                 raise_exception(EXEXIT);
9243
9244         popstackmark(&smark);
9245         TRACE(("leaving evaltree (no interrupts)\n"));
9246         return exitstatus;
9247 }
9248
9249 static int
9250 skiploop(void)
9251 {
9252         int skip = evalskip;
9253
9254         switch (skip) {
9255         case 0:
9256                 break;
9257         case SKIPBREAK:
9258         case SKIPCONT:
9259                 if (--skipcount <= 0) {
9260                         evalskip = 0;
9261                         break;
9262                 }
9263                 skip = SKIPBREAK;
9264                 break;
9265         }
9266         return skip;
9267 }
9268
9269 static int
9270 evalloop(union node *n, int flags)
9271 {
9272         int skip;
9273         int status;
9274
9275         loopnest++;
9276         status = 0;
9277         flags &= EV_TESTED;
9278         do {
9279                 int i;
9280
9281                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9282                 skip = skiploop();
9283                 if (skip == SKIPFUNC)
9284                         status = i;
9285                 if (skip)
9286                         continue;
9287                 if (n->type != NWHILE)
9288                         i = !i;
9289                 if (i != 0)
9290                         break;
9291                 status = evaltree(n->nbinary.ch2, flags);
9292                 skip = skiploop();
9293         } while (!(skip & ~SKIPCONT));
9294         loopnest--;
9295
9296         return status;
9297 }
9298
9299 static int
9300 evalfor(union node *n, int flags)
9301 {
9302         struct arglist arglist;
9303         union node *argp;
9304         struct strlist *sp;
9305         int status = 0;
9306
9307         errlinno = lineno = n->ncase.linno;
9308         if (funcline)
9309                 lineno -= funcline - 1;
9310
9311         arglist.list = NULL;
9312         arglist.lastp = &arglist.list;
9313         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9314                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9315         }
9316         *arglist.lastp = NULL;
9317
9318         loopnest++;
9319         flags &= EV_TESTED;
9320         for (sp = arglist.list; sp; sp = sp->next) {
9321                 setvar0(n->nfor.var, sp->text);
9322                 status = evaltree(n->nfor.body, flags);
9323                 if (skiploop() & ~SKIPCONT)
9324                         break;
9325         }
9326         loopnest--;
9327
9328         return status;
9329 }
9330
9331 static int
9332 evalcase(union node *n, int flags)
9333 {
9334         union node *cp;
9335         union node *patp;
9336         struct arglist arglist;
9337         int status = 0;
9338
9339         errlinno = lineno = n->ncase.linno;
9340         if (funcline)
9341                 lineno -= funcline - 1;
9342
9343         arglist.list = NULL;
9344         arglist.lastp = &arglist.list;
9345         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9346         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9347                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9348                         if (casematch(patp, arglist.list->text)) {
9349                                 /* Ensure body is non-empty as otherwise
9350                                  * EV_EXIT may prevent us from setting the
9351                                  * exit status.
9352                                  */
9353                                 if (evalskip == 0 && cp->nclist.body) {
9354                                         status = evaltree(cp->nclist.body, flags);
9355                                 }
9356                                 goto out;
9357                         }
9358                 }
9359         }
9360  out:
9361         return status;
9362 }
9363
9364 /*
9365  * Kick off a subshell to evaluate a tree.
9366  */
9367 static int
9368 evalsubshell(union node *n, int flags)
9369 {
9370         struct job *jp;
9371         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9372         int status;
9373
9374         errlinno = lineno = n->nredir.linno;
9375         if (funcline)
9376                 lineno -= funcline - 1;
9377
9378         expredir(n->nredir.redirect);
9379         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9380                 goto nofork;
9381         INT_OFF;
9382         if (backgnd == FORK_FG)
9383                 get_tty_state();
9384         jp = makejob(/*n,*/ 1);
9385         if (forkshell(jp, n, backgnd) == 0) {
9386                 /* child */
9387                 INT_ON;
9388                 flags |= EV_EXIT;
9389                 if (backgnd)
9390                         flags &= ~EV_TESTED;
9391  nofork:
9392                 redirect(n->nredir.redirect, 0);
9393                 evaltreenr(n->nredir.n, flags);
9394                 /* never returns */
9395         }
9396         /* parent */
9397         status = 0;
9398         if (backgnd == FORK_FG)
9399                 status = waitforjob(jp);
9400         INT_ON;
9401         return status;
9402 }
9403
9404 /*
9405  * Compute the names of the files in a redirection list.
9406  */
9407 static void fixredir(union node *, const char *, int);
9408 static void
9409 expredir(union node *n)
9410 {
9411         union node *redir;
9412
9413         for (redir = n; redir; redir = redir->nfile.next) {
9414                 struct arglist fn;
9415
9416                 fn.list = NULL;
9417                 fn.lastp = &fn.list;
9418                 switch (redir->type) {
9419                 case NFROMTO:
9420                 case NFROM:
9421                 case NTO:
9422 #if BASH_REDIR_OUTPUT
9423                 case NTO2:
9424 #endif
9425                 case NCLOBBER:
9426                 case NAPPEND:
9427                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9428                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9429 #if BASH_REDIR_OUTPUT
9430  store_expfname:
9431 #endif
9432 #if 0
9433 // By the design of stack allocator, the loop of this kind:
9434 //      while true; do while true; do break; done </dev/null; done
9435 // will look like a memory leak: ash plans to free expfname's
9436 // of "/dev/null" as soon as it finishes running the loop
9437 // (in this case, never).
9438 // This "fix" is wrong:
9439                         if (redir->nfile.expfname)
9440                                 stunalloc(redir->nfile.expfname);
9441 // It results in corrupted state of stacked allocations.
9442 #endif
9443                         redir->nfile.expfname = fn.list->text;
9444                         break;
9445                 case NFROMFD:
9446                 case NTOFD: /* >& */
9447                         if (redir->ndup.vname) {
9448                                 expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
9449                                 if (fn.list == NULL)
9450                                         ash_msg_and_raise_error("redir error");
9451 #if BASH_REDIR_OUTPUT
9452                                 if (!isdigit_str9(fn.list->text)) {
9453                                         /* >&file, not >&fd */
9454                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9455                                                 ash_msg_and_raise_error("redir error");
9456                                         redir->type = NTO2;
9457                                         goto store_expfname;
9458                                 }
9459 #endif
9460                                 fixredir(redir, fn.list->text, 1);
9461                         }
9462                         break;
9463                 }
9464         }
9465 }
9466
9467 /*
9468  * Evaluate a pipeline.  All the processes in the pipeline are children
9469  * of the process creating the pipeline.  (This differs from some versions
9470  * of the shell, which make the last process in a pipeline the parent
9471  * of all the rest.)
9472  */
9473 static int
9474 evalpipe(union node *n, int flags)
9475 {
9476         struct job *jp;
9477         struct nodelist *lp;
9478         int pipelen;
9479         int prevfd;
9480         int pip[2];
9481         int status = 0;
9482
9483         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9484         pipelen = 0;
9485         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9486                 pipelen++;
9487         flags |= EV_EXIT;
9488         INT_OFF;
9489         if (n->npipe.pipe_backgnd == 0)
9490                 get_tty_state();
9491         jp = makejob(/*n,*/ pipelen);
9492         prevfd = -1;
9493         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9494                 prehash(lp->n);
9495                 pip[1] = -1;
9496                 if (lp->next) {
9497                         if (pipe(pip) < 0) {
9498                                 close(prevfd);
9499                                 ash_msg_and_raise_perror("can't create pipe");
9500                         }
9501                 }
9502                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9503                         /* child */
9504                         INT_ON;
9505                         if (pip[1] >= 0) {
9506                                 close(pip[0]);
9507                         }
9508                         if (prevfd > 0) {
9509                                 dup2(prevfd, 0);
9510                                 close(prevfd);
9511                         }
9512                         if (pip[1] > 1) {
9513                                 dup2(pip[1], 1);
9514                                 close(pip[1]);
9515                         }
9516                         evaltreenr(lp->n, flags);
9517                         /* never returns */
9518                 }
9519                 /* parent */
9520                 if (prevfd >= 0)
9521                         close(prevfd);
9522                 prevfd = pip[0];
9523                 /* Don't want to trigger debugging */
9524                 if (pip[1] != -1)
9525                         close(pip[1]);
9526         }
9527         if (n->npipe.pipe_backgnd == 0) {
9528                 status = waitforjob(jp);
9529                 TRACE(("evalpipe:  job done exit status %d\n", status));
9530         }
9531         INT_ON;
9532
9533         return status;
9534 }
9535
9536 /* setinteractive needs this forward reference */
9537 #if EDITING_HAS_get_exe_name
9538 static const char *get_builtin_name(int i) FAST_FUNC;
9539 #endif
9540
9541 /*
9542  * Controls whether the shell is interactive or not.
9543  */
9544 static void
9545 setinteractive(int on)
9546 {
9547         static smallint is_interactive;
9548
9549         if (++on == is_interactive)
9550                 return;
9551         is_interactive = on;
9552         setsignal(SIGINT);
9553         setsignal(SIGQUIT);
9554         setsignal(SIGTERM);
9555         if (is_interactive > 1) {
9556 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9557                 /* Looks like they want an interactive shell */
9558                 static smallint did_banner;
9559
9560                 if (!did_banner) {
9561                         /* note: ash and hush share this string */
9562                         out1fmt("\n\n%s %s\n"
9563                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9564                                 "\n",
9565                                 bb_banner,
9566                                 "built-in shell (ash)"
9567                         );
9568                         did_banner = 1;
9569                 }
9570 #endif
9571 #if ENABLE_FEATURE_EDITING
9572                 if (!line_input_state) {
9573                         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9574 # if EDITING_HAS_get_exe_name
9575                         line_input_state->get_exe_name = get_builtin_name;
9576 # endif
9577                 }
9578 #endif
9579         }
9580 }
9581
9582 static void
9583 optschanged(void)
9584 {
9585 #if DEBUG
9586         opentrace();
9587 #endif
9588         setinteractive(iflag);
9589         setjobctl(mflag);
9590 #if ENABLE_FEATURE_EDITING_VI
9591         if (line_input_state) {
9592                 if (viflag)
9593                         line_input_state->flags |= VI_MODE;
9594                 else
9595                         line_input_state->flags &= ~VI_MODE;
9596         }
9597 #else
9598         viflag = 0; /* forcibly keep the option off */
9599 #endif
9600 }
9601
9602 struct localvar_list {
9603         struct localvar_list *next;
9604         struct localvar *lv;
9605 };
9606
9607 static struct localvar_list *localvar_stack;
9608
9609 /*
9610  * Called after a function returns.
9611  * Interrupts must be off.
9612  */
9613 static void
9614 poplocalvars(int keep)
9615 {
9616         struct localvar_list *ll;
9617         struct localvar *lvp, *next;
9618         struct var *vp;
9619
9620         INT_OFF;
9621         ll = localvar_stack;
9622         localvar_stack = ll->next;
9623
9624         next = ll->lv;
9625         free(ll);
9626
9627         while ((lvp = next) != NULL) {
9628                 next = lvp->next;
9629                 vp = lvp->vp;
9630                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9631                 if (keep) {
9632                         int bits = VSTRFIXED;
9633
9634                         if (lvp->flags != VUNSET) {
9635                                 if (vp->var_text == lvp->text)
9636                                         bits |= VTEXTFIXED;
9637                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9638                                         free((char*)lvp->text);
9639                         }
9640
9641                         vp->flags &= ~bits;
9642                         vp->flags |= (lvp->flags & bits);
9643
9644                         if ((vp->flags &
9645                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9646                                 unsetvar(vp->var_text);
9647                 } else if (vp == NULL) {        /* $- saved */
9648                         memcpy(optlist, lvp->text, sizeof(optlist));
9649                         free((char*)lvp->text);
9650                         optschanged();
9651                 } else if (lvp->flags == VUNSET) {
9652                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9653                         unsetvar(vp->var_text);
9654                 } else {
9655                         if (vp->var_func)
9656                                 vp->var_func(var_end(lvp->text));
9657                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9658                                 free((char*)vp->var_text);
9659                         vp->flags = lvp->flags;
9660                         vp->var_text = lvp->text;
9661                 }
9662                 free(lvp);
9663         }
9664         INT_ON;
9665 }
9666
9667 /*
9668  * Create a new localvar environment.
9669  */
9670 static struct localvar_list *
9671 pushlocalvars(void)
9672 {
9673         struct localvar_list *ll;
9674
9675         INT_OFF;
9676         ll = ckzalloc(sizeof(*ll));
9677         /*ll->lv = NULL; - zalloc did it */
9678         ll->next = localvar_stack;
9679         localvar_stack = ll;
9680         INT_ON;
9681
9682         return ll->next;
9683 }
9684
9685 static void
9686 unwindlocalvars(struct localvar_list *stop)
9687 {
9688         while (localvar_stack != stop)
9689                 poplocalvars(0);
9690 }
9691
9692 static int
9693 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9694 {
9695         volatile struct shparam saveparam;
9696         struct jmploc *volatile savehandler;
9697         struct jmploc jmploc;
9698         int e;
9699         int savefuncline;
9700
9701         saveparam = shellparam;
9702         savefuncline = funcline;
9703         savehandler = exception_handler;
9704         e = setjmp(jmploc.loc);
9705         if (e) {
9706                 goto funcdone;
9707         }
9708         INT_OFF;
9709         exception_handler = &jmploc;
9710         shellparam.malloced = 0;
9711         func->count++;
9712         funcline = func->n.ndefun.linno;
9713         INT_ON;
9714         shellparam.nparam = argc - 1;
9715         shellparam.p = argv + 1;
9716 #if ENABLE_ASH_GETOPTS
9717         shellparam.optind = 1;
9718         shellparam.optoff = -1;
9719 #endif
9720         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9721  funcdone:
9722         INT_OFF;
9723         funcline = savefuncline;
9724         freefunc(func);
9725         freeparam(&shellparam);
9726         shellparam = saveparam;
9727         exception_handler = savehandler;
9728         INT_ON;
9729         evalskip &= ~SKIPFUNC;
9730         return e;
9731 }
9732
9733 /*
9734  * Make a variable a local variable.  When a variable is made local, it's
9735  * value and flags are saved in a localvar structure.  The saved values
9736  * will be restored when the shell function returns.  We handle the name
9737  * "-" as a special case: it makes changes to "set +-options" local
9738  * (options will be restored on return from the function).
9739  */
9740 static void
9741 mklocal(char *name)
9742 {
9743         struct localvar *lvp;
9744         struct var **vpp;
9745         struct var *vp;
9746         char *eq = strchr(name, '=');
9747
9748         INT_OFF;
9749         /* Cater for duplicate "local". Examples:
9750          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9751          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9752          */
9753         lvp = localvar_stack->lv;
9754         while (lvp) {
9755                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9756                         if (eq)
9757                                 setvareq(name, 0);
9758                         /* else:
9759                          * it's a duplicate "local VAR" declaration, do nothing
9760                          */
9761                         goto ret;
9762                 }
9763                 lvp = lvp->next;
9764         }
9765
9766         lvp = ckzalloc(sizeof(*lvp));
9767         if (LONE_DASH(name)) {
9768                 char *p;
9769                 p = ckmalloc(sizeof(optlist));
9770                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9771                 vp = NULL;
9772         } else {
9773                 vpp = hashvar(name);
9774                 vp = *findvar(vpp, name);
9775                 if (vp == NULL) {
9776                         /* variable did not exist yet */
9777                         if (eq)
9778                                 vp = setvareq(name, VSTRFIXED);
9779                         else
9780                                 vp = setvar(name, NULL, VSTRFIXED);
9781                         lvp->flags = VUNSET;
9782                 } else {
9783                         lvp->text = vp->var_text;
9784                         lvp->flags = vp->flags;
9785                         /* make sure neither "struct var" nor string gets freed
9786                          * during (un)setting:
9787                          */
9788                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9789                         if (eq)
9790                                 setvareq(name, 0);
9791                         else
9792                                 /* "local VAR" unsets VAR: */
9793                                 setvar0(name, NULL);
9794                 }
9795         }
9796         lvp->vp = vp;
9797         lvp->next = localvar_stack->lv;
9798         localvar_stack->lv = lvp;
9799  ret:
9800         INT_ON;
9801 }
9802
9803 /*
9804  * The "local" command.
9805  */
9806 static int FAST_FUNC
9807 localcmd(int argc UNUSED_PARAM, char **argv)
9808 {
9809         char *name;
9810
9811         if (!localvar_stack)
9812                 ash_msg_and_raise_error("not in a function");
9813
9814         argv = argptr;
9815         while ((name = *argv++) != NULL) {
9816                 mklocal(name);
9817         }
9818         return 0;
9819 }
9820
9821 static int FAST_FUNC
9822 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9823 {
9824         return 1;
9825 }
9826
9827 static int FAST_FUNC
9828 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9829 {
9830         return 0;
9831 }
9832
9833 static int FAST_FUNC
9834 execcmd(int argc UNUSED_PARAM, char **argv)
9835 {
9836         optionarg = NULL;
9837         while (nextopt("a:") != '\0')
9838                 /* nextopt() sets optionarg to "-a ARGV0" */;
9839
9840         argv = argptr;
9841         if (argv[0]) {
9842                 char *prog;
9843
9844                 iflag = 0;              /* exit on error */
9845                 mflag = 0;
9846                 optschanged();
9847                 /* We should set up signals for "exec CMD"
9848                  * the same way as for "CMD" without "exec".
9849                  * But optschanged->setinteractive->setsignal
9850                  * still thought we are a root shell. Therefore, for example,
9851                  * SIGQUIT is still set to IGN. Fix it:
9852                  */
9853                 shlvl++;
9854                 setsignal(SIGQUIT);
9855                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9856                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9857                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9858
9859                 prog = argv[0];
9860                 if (optionarg)
9861                         argv[0] = optionarg;
9862                 shellexec(prog, argv, pathval(), 0);
9863                 /* NOTREACHED */
9864         }
9865         return 0;
9866 }
9867
9868 /*
9869  * The return command.
9870  */
9871 static int FAST_FUNC
9872 returncmd(int argc UNUSED_PARAM, char **argv)
9873 {
9874         /*
9875          * If called outside a function, do what ksh does;
9876          * skip the rest of the file.
9877          */
9878         evalskip = SKIPFUNC;
9879         return argv[1] ? number(argv[1]) : exitstatus;
9880 }
9881
9882 /* Forward declarations for builtintab[] */
9883 static int breakcmd(int, char **) FAST_FUNC;
9884 static int dotcmd(int, char **) FAST_FUNC;
9885 static int evalcmd(int, char **, int) FAST_FUNC;
9886 static int exitcmd(int, char **) FAST_FUNC;
9887 static int exportcmd(int, char **) FAST_FUNC;
9888 #if ENABLE_ASH_GETOPTS
9889 static int getoptscmd(int, char **) FAST_FUNC;
9890 #endif
9891 #if ENABLE_ASH_HELP
9892 static int helpcmd(int, char **) FAST_FUNC;
9893 #endif
9894 #if MAX_HISTORY
9895 static int historycmd(int, char **) FAST_FUNC;
9896 #endif
9897 #if ENABLE_FEATURE_SH_MATH
9898 static int letcmd(int, char **) FAST_FUNC;
9899 #endif
9900 static int readcmd(int, char **) FAST_FUNC;
9901 static int setcmd(int, char **) FAST_FUNC;
9902 static int shiftcmd(int, char **) FAST_FUNC;
9903 static int timescmd(int, char **) FAST_FUNC;
9904 static int trapcmd(int, char **) FAST_FUNC;
9905 static int umaskcmd(int, char **) FAST_FUNC;
9906 static int unsetcmd(int, char **) FAST_FUNC;
9907 static int ulimitcmd(int, char **) FAST_FUNC;
9908
9909 #define BUILTIN_NOSPEC          "0"
9910 #define BUILTIN_SPECIAL         "1"
9911 #define BUILTIN_REGULAR         "2"
9912 #define BUILTIN_SPEC_REG        "3"
9913 #define BUILTIN_ASSIGN          "4"
9914 #define BUILTIN_SPEC_ASSG       "5"
9915 #define BUILTIN_REG_ASSG        "6"
9916 #define BUILTIN_SPEC_REG_ASSG   "7"
9917
9918 /* Stubs for calling non-FAST_FUNC's */
9919 #if ENABLE_ASH_ECHO
9920 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9921 #endif
9922 #if ENABLE_ASH_PRINTF
9923 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9924 #endif
9925 #if ENABLE_ASH_TEST || BASH_TEST2
9926 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9927 #endif
9928
9929 /* Keep these in proper order since it is searched via bsearch() */
9930 static const struct builtincmd builtintab[] = {
9931         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9932         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9933 #if ENABLE_ASH_TEST
9934         { BUILTIN_REGULAR       "["       , testcmd    },
9935 #endif
9936 #if BASH_TEST2
9937         { BUILTIN_REGULAR       "[["      , testcmd    },
9938 #endif
9939 #if ENABLE_ASH_ALIAS
9940         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9941 #endif
9942 #if JOBS
9943         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9944 #endif
9945         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9946         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9947         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9948 #if ENABLE_ASH_CMDCMD
9949         { BUILTIN_REGULAR       "command" , commandcmd },
9950 #endif
9951         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9952 #if ENABLE_ASH_ECHO
9953         { BUILTIN_REGULAR       "echo"    , echocmd    },
9954 #endif
9955         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9956         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9957         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9958         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9959         { BUILTIN_REGULAR       "false"   , falsecmd   },
9960 #if JOBS
9961         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9962 #endif
9963 #if ENABLE_ASH_GETOPTS
9964         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9965 #endif
9966         { BUILTIN_REGULAR       "hash"    , hashcmd    },
9967 #if ENABLE_ASH_HELP
9968         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9969 #endif
9970 #if MAX_HISTORY
9971         { BUILTIN_NOSPEC        "history" , historycmd },
9972 #endif
9973 #if JOBS
9974         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9975         { BUILTIN_REGULAR       "kill"    , killcmd    },
9976 #endif
9977 #if ENABLE_FEATURE_SH_MATH
9978         { BUILTIN_NOSPEC        "let"     , letcmd     },
9979 #endif
9980         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9981 #if ENABLE_ASH_PRINTF
9982         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9983 #endif
9984         { BUILTIN_REGULAR       "pwd"     , pwdcmd     },
9985         { BUILTIN_REGULAR       "read"    , readcmd    },
9986         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9987         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9988         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9989         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9990 #if BASH_SOURCE
9991         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9992 #endif
9993 #if ENABLE_ASH_TEST
9994         { BUILTIN_REGULAR       "test"    , testcmd    },
9995 #endif
9996         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9997         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9998         { BUILTIN_REGULAR       "true"    , truecmd    },
9999         { BUILTIN_REGULAR       "type"    , typecmd    },
10000         { BUILTIN_REGULAR       "ulimit"  , ulimitcmd  },
10001         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
10002 #if ENABLE_ASH_ALIAS
10003         { BUILTIN_REGULAR       "unalias" , unaliascmd },
10004 #endif
10005         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
10006         { BUILTIN_REGULAR       "wait"    , waitcmd    },
10007 };
10008
10009 /* Should match the above table! */
10010 #define COMMANDCMD (builtintab + \
10011         /* . : */       2 + \
10012         /* [ */         1 * ENABLE_ASH_TEST + \
10013         /* [[ */        1 * BASH_TEST2 + \
10014         /* alias */     1 * ENABLE_ASH_ALIAS + \
10015         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
10016         /* break cd cddir  */   3)
10017 #define EVALCMD (COMMANDCMD + \
10018         /* command */   1 * ENABLE_ASH_CMDCMD + \
10019         /* continue */  1 + \
10020         /* echo */      1 * ENABLE_ASH_ECHO + \
10021         0)
10022 #define EXECCMD (EVALCMD + \
10023         /* eval */      1)
10024
10025 /*
10026  * Search the table of builtin commands.
10027  */
10028 static int
10029 pstrcmp1(const void *a, const void *b)
10030 {
10031         return strcmp((char*)a, *(char**)b + 1);
10032 }
10033 static struct builtincmd *
10034 find_builtin(const char *name)
10035 {
10036         struct builtincmd *bp;
10037
10038         bp = bsearch(
10039                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
10040                 pstrcmp1
10041         );
10042         return bp;
10043 }
10044
10045 #if EDITING_HAS_get_exe_name
10046 static const char * FAST_FUNC
10047 get_builtin_name(int i)
10048 {
10049         return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL;
10050 }
10051 #endif
10052
10053 /*
10054  * Execute a simple command.
10055  */
10056 static void unwindfiles(struct parsefile *stop);
10057 static int
10058 isassignment(const char *p)
10059 {
10060         const char *q = endofname(p);
10061         if (p == q)
10062                 return 0;
10063         return *q == '=';
10064 }
10065 static int FAST_FUNC
10066 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10067 {
10068         /* Preserve exitstatus of a previous possible redirection
10069          * as POSIX mandates */
10070         return back_exitstatus;
10071 }
10072 static int
10073 evalcommand(union node *cmd, int flags)
10074 {
10075         static const struct builtincmd null_bltin = {
10076                 "\0\0", bltincmd /* why three NULs? */
10077         };
10078         struct localvar_list *localvar_stop;
10079         struct parsefile *file_stop;
10080         struct redirtab *redir_stop;
10081         union node *argp;
10082         struct arglist arglist;
10083         struct arglist varlist;
10084         char **argv;
10085         int argc;
10086         const struct strlist *sp;
10087         struct cmdentry cmdentry;
10088         struct job *jp;
10089         char *lastarg;
10090         const char *path;
10091         int spclbltin;
10092         int status;
10093         char **nargv;
10094         smallint cmd_is_exec;
10095
10096         errlinno = lineno = cmd->ncmd.linno;
10097         if (funcline)
10098                 lineno -= funcline - 1;
10099
10100         /* First expand the arguments. */
10101         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10102         localvar_stop = pushlocalvars();
10103         file_stop = g_parsefile;
10104         back_exitstatus = 0;
10105
10106         cmdentry.cmdtype = CMDBUILTIN;
10107         cmdentry.u.cmd = &null_bltin;
10108         varlist.lastp = &varlist.list;
10109         *varlist.lastp = NULL;
10110         arglist.lastp = &arglist.list;
10111         *arglist.lastp = NULL;
10112
10113         argc = 0;
10114         if (cmd->ncmd.args) {
10115                 struct builtincmd *bcmd;
10116                 smallint pseudovarflag;
10117
10118                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
10119                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
10120
10121                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
10122                         struct strlist **spp;
10123
10124                         spp = arglist.lastp;
10125                         if (pseudovarflag && isassignment(argp->narg.text))
10126                                 expandarg(argp, &arglist, EXP_VARTILDE);
10127                         else
10128                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
10129
10130                         for (sp = *spp; sp; sp = sp->next)
10131                                 argc++;
10132                 }
10133         }
10134
10135         /* Reserve one extra spot at the front for shellexec. */
10136         nargv = stalloc(sizeof(char *) * (argc + 2));
10137         argv = ++nargv;
10138         for (sp = arglist.list; sp; sp = sp->next) {
10139                 TRACE(("evalcommand arg: %s\n", sp->text));
10140                 *nargv++ = sp->text;
10141         }
10142         *nargv = NULL;
10143
10144         lastarg = NULL;
10145         if (iflag && funcline == 0 && argc > 0)
10146                 lastarg = nargv[-1];
10147
10148         expredir(cmd->ncmd.redirect);
10149         redir_stop = pushredir(cmd->ncmd.redirect);
10150         preverrout_fd = 2;
10151         if (BASH_XTRACEFD && xflag) {
10152                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10153                  * we do not emulate this. We only use its value.
10154                  */
10155                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10156                 if (xtracefd && is_number(xtracefd))
10157                         preverrout_fd = atoi(xtracefd);
10158
10159         }
10160         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10161
10162         path = vpath.var_text;
10163         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10164                 struct strlist **spp;
10165                 char *p;
10166
10167                 spp = varlist.lastp;
10168                 expandarg(argp, &varlist, EXP_VARTILDE);
10169
10170                 mklocal((*spp)->text);
10171
10172                 /*
10173                  * Modify the command lookup path, if a PATH= assignment
10174                  * is present
10175                  */
10176                 p = (*spp)->text;
10177                 if (varcmp(p, path) == 0)
10178                         path = p;
10179         }
10180
10181         /* Print the command if xflag is set. */
10182         if (xflag) {
10183                 const char *pfx = "";
10184
10185                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10186
10187                 sp = varlist.list;
10188                 while (sp) {
10189                         char *varval = sp->text;
10190                         char *eq = strchrnul(varval, '=');
10191                         if (*eq)
10192                                 eq++;
10193                         fdprintf(preverrout_fd, "%s%.*s%s",
10194                                 pfx,
10195                                 (int)(eq - varval), varval,
10196                                 maybe_single_quote(eq)
10197                         );
10198                         sp = sp->next;
10199                         pfx = " ";
10200                 }
10201
10202                 sp = arglist.list;
10203                 while (sp) {
10204                         fdprintf(preverrout_fd, "%s%s",
10205                                 pfx,
10206                                 /* always quote if matches reserved word: */
10207                                 findkwd(sp->text)
10208                                 ? single_quote(sp->text)
10209                                 : maybe_single_quote(sp->text)
10210                         );
10211                         sp = sp->next;
10212                         pfx = " ";
10213                 }
10214                 safe_write(preverrout_fd, "\n", 1);
10215         }
10216
10217         cmd_is_exec = 0;
10218         spclbltin = -1;
10219
10220         /* Now locate the command. */
10221         if (argc) {
10222                 int cmd_flag = DO_ERR;
10223 #if ENABLE_ASH_CMDCMD
10224                 const char *oldpath = path + 5;
10225 #endif
10226                 path += 5;
10227                 for (;;) {
10228                         find_command(argv[0], &cmdentry, cmd_flag, path);
10229                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10230                                 flush_stdout_stderr();
10231                                 status = 127;
10232                                 goto bail;
10233                         }
10234
10235                         /* implement bltin and command here */
10236                         if (cmdentry.cmdtype != CMDBUILTIN)
10237                                 break;
10238                         if (spclbltin < 0)
10239                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10240                         if (cmdentry.u.cmd == EXECCMD)
10241                                 cmd_is_exec = 1;
10242 #if ENABLE_ASH_CMDCMD
10243                         if (cmdentry.u.cmd == COMMANDCMD) {
10244                                 path = oldpath;
10245                                 nargv = parse_command_args(argv, &path);
10246                                 if (!nargv)
10247                                         break;
10248                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10249                                  * nargv => "PROG". path is updated if -p.
10250                                  */
10251                                 argc -= nargv - argv;
10252                                 argv = nargv;
10253                                 cmd_flag |= DO_NOFUNC;
10254                         } else
10255 #endif
10256                                 break;
10257                 }
10258         }
10259
10260         if (status) {
10261  bail:
10262                 exitstatus = status;
10263
10264                 /* We have a redirection error. */
10265                 if (spclbltin > 0)
10266                         raise_exception(EXERROR);
10267
10268                 goto out;
10269         }
10270
10271         /* Execute the command. */
10272         switch (cmdentry.cmdtype) {
10273         default: {
10274
10275 #if ENABLE_FEATURE_SH_STANDALONE \
10276  && ENABLE_FEATURE_SH_NOFORK \
10277  && NUM_APPLETS > 1
10278 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10279  *     around run_nofork_applet() call.
10280  * (2) Should this check also be done in forkshell()?
10281  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10282  */
10283                 /* find_command() encodes applet_no as (-2 - applet_no) */
10284                 int applet_no = (- cmdentry.u.index - 2);
10285                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10286                         char **sv_environ;
10287
10288                         INT_OFF;
10289                         sv_environ = environ;
10290                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10291                         /*
10292                          * Run <applet>_main().
10293                          * Signals (^C) can't interrupt here.
10294                          * Otherwise we can mangle stdio or malloc internal state.
10295                          * This makes applets which can run for a long time
10296                          * and/or wait for user input ineligible for NOFORK:
10297                          * for example, "yes" or "rm" (rm -i waits for input).
10298                          */
10299                         status = run_nofork_applet(applet_no, argv);
10300                         environ = sv_environ;
10301                         /*
10302                          * Try enabling NOFORK for "yes" applet.
10303                          * ^C _will_ stop it (write returns EINTR),
10304                          * but this causes stdout FILE to be stuck
10305                          * and needing clearerr(). What if other applets
10306                          * also can get EINTRs? Do we need to switch
10307                          * our signals to SA_RESTART?
10308                          */
10309                         /*clearerr(stdout);*/
10310                         INT_ON;
10311                         break;
10312                 }
10313 #endif
10314                 /* Can we avoid forking? For example, very last command
10315                  * in a script or a subshell does not need forking,
10316                  * we can just exec it.
10317                  */
10318                 if (!(flags & EV_EXIT) || may_have_traps) {
10319                         /* No, forking off a child is necessary */
10320                         INT_OFF;
10321                         get_tty_state();
10322                         jp = makejob(/*cmd,*/ 1);
10323                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10324                                 /* parent */
10325                                 status = waitforjob(jp);
10326                                 INT_ON;
10327                                 TRACE(("forked child exited with %d\n", status));
10328                                 break;
10329                         }
10330                         /* child */
10331                         FORCE_INT_ON;
10332                         /* fall through to exec'ing external program */
10333                 }
10334                 listsetvar(varlist.list, VEXPORT|VSTACK);
10335                 shellexec(argv[0], argv, path, cmdentry.u.index);
10336                 /* NOTREACHED */
10337         } /* default */
10338         case CMDBUILTIN:
10339                 if (spclbltin > 0 || argc == 0) {
10340                         poplocalvars(1);
10341                         if (cmd_is_exec && argc > 1)
10342                                 listsetvar(varlist.list, VEXPORT);
10343                 }
10344
10345                 /* Tight loop with builtins only:
10346                  * "while kill -0 $child; do true; done"
10347                  * will never exit even if $child died, unless we do this
10348                  * to reap the zombie and make kill detect that it's gone: */
10349                 dowait(DOWAIT_NONBLOCK, NULL);
10350
10351                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10352                         if (exception_type == EXERROR && spclbltin <= 0) {
10353                                 FORCE_INT_ON;
10354                                 goto readstatus;
10355                         }
10356  raise:
10357                         longjmp(exception_handler->loc, 1);
10358                 }
10359                 goto readstatus;
10360
10361         case CMDFUNCTION:
10362                 /* See above for the rationale */
10363                 dowait(DOWAIT_NONBLOCK, NULL);
10364                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10365                         goto raise;
10366  readstatus:
10367                 status = exitstatus;
10368                 break;
10369         } /* switch */
10370
10371  out:
10372         if (cmd->ncmd.redirect)
10373                 popredir(/*drop:*/ cmd_is_exec);
10374         unwindredir(redir_stop);
10375         unwindfiles(file_stop);
10376         unwindlocalvars(localvar_stop);
10377         if (lastarg) {
10378                 /* dsl: I think this is intended to be used to support
10379                  * '_' in 'vi' command mode during line editing...
10380                  * However I implemented that within libedit itself.
10381                  */
10382                 setvar0("_", lastarg);
10383         }
10384
10385         return status;
10386 }
10387
10388 static int
10389 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10390 {
10391         char *volatile savecmdname;
10392         struct jmploc *volatile savehandler;
10393         struct jmploc jmploc;
10394         int status;
10395         int i;
10396
10397         savecmdname = commandname;
10398         savehandler = exception_handler;
10399         i = setjmp(jmploc.loc);
10400         if (i)
10401                 goto cmddone;
10402         exception_handler = &jmploc;
10403         commandname = argv[0];
10404         argptr = argv + 1;
10405         optptr = NULL;                  /* initialize nextopt */
10406         if (cmd == EVALCMD)
10407                 status = evalcmd(argc, argv, flags);
10408         else
10409                 status = (*cmd->builtin)(argc, argv);
10410         flush_stdout_stderr();
10411         status |= ferror(stdout);
10412         exitstatus = status;
10413  cmddone:
10414         clearerr(stdout);
10415         commandname = savecmdname;
10416         exception_handler = savehandler;
10417
10418         return i;
10419 }
10420
10421 static int
10422 goodname(const char *p)
10423 {
10424         return endofname(p)[0] == '\0';
10425 }
10426
10427
10428 /*
10429  * Search for a command.  This is called before we fork so that the
10430  * location of the command will be available in the parent as well as
10431  * the child.  The check for "goodname" is an overly conservative
10432  * check that the name will not be subject to expansion.
10433  */
10434 static void
10435 prehash(union node *n)
10436 {
10437         struct cmdentry entry;
10438
10439         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10440                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10441 }
10442
10443
10444 /* ============ Builtin commands
10445  *
10446  * Builtin commands whose functions are closely tied to evaluation
10447  * are implemented here.
10448  */
10449
10450 /*
10451  * Handle break and continue commands.  Break, continue, and return are
10452  * all handled by setting the evalskip flag.  The evaluation routines
10453  * above all check this flag, and if it is set they start skipping
10454  * commands rather than executing them.  The variable skipcount is
10455  * the number of loops to break/continue, or the number of function
10456  * levels to return.  (The latter is always 1.)  It should probably
10457  * be an error to break out of more loops than exist, but it isn't
10458  * in the standard shell so we don't make it one here.
10459  */
10460 static int FAST_FUNC
10461 breakcmd(int argc UNUSED_PARAM, char **argv)
10462 {
10463         int n = argv[1] ? number(argv[1]) : 1;
10464
10465         if (n <= 0)
10466                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10467         if (n > loopnest)
10468                 n = loopnest;
10469         if (n > 0) {
10470                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10471                 skipcount = n;
10472         }
10473         return 0;
10474 }
10475
10476
10477 /*
10478  * This implements the input routines used by the parser.
10479  */
10480
10481 enum {
10482         INPUT_PUSH_FILE = 1,
10483         INPUT_NOFILE_OK = 2,
10484 };
10485
10486 static smallint checkkwd;
10487 /* values of checkkwd variable */
10488 #define CHKALIAS        0x1
10489 #define CHKKWD          0x2
10490 #define CHKNL           0x4
10491 #define CHKEOFMARK      0x8
10492
10493 /*
10494  * Push a string back onto the input at this current parsefile level.
10495  * We handle aliases this way.
10496  */
10497 #if !ENABLE_ASH_ALIAS
10498 #define pushstring(s, ap) pushstring(s)
10499 #endif
10500 static void
10501 pushstring(char *s, struct alias *ap)
10502 {
10503         struct strpush *sp;
10504         int len;
10505
10506         len = strlen(s);
10507         INT_OFF;
10508         if (g_parsefile->strpush) {
10509                 sp = ckzalloc(sizeof(*sp));
10510                 sp->prev = g_parsefile->strpush;
10511         } else {
10512                 sp = &(g_parsefile->basestrpush);
10513         }
10514         g_parsefile->strpush = sp;
10515         sp->prev_string = g_parsefile->next_to_pgetc;
10516         sp->prev_left_in_line = g_parsefile->left_in_line;
10517         sp->unget = g_parsefile->unget;
10518         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10519 #if ENABLE_ASH_ALIAS
10520         sp->ap = ap;
10521         if (ap) {
10522                 ap->flag |= ALIASINUSE;
10523                 sp->string = s;
10524         }
10525 #endif
10526         g_parsefile->next_to_pgetc = s;
10527         g_parsefile->left_in_line = len;
10528         g_parsefile->unget = 0;
10529         INT_ON;
10530 }
10531
10532 static void
10533 popstring(void)
10534 {
10535         struct strpush *sp = g_parsefile->strpush;
10536
10537         INT_OFF;
10538 #if ENABLE_ASH_ALIAS
10539         if (sp->ap) {
10540                 if (g_parsefile->next_to_pgetc[-1] == ' '
10541                  || g_parsefile->next_to_pgetc[-1] == '\t'
10542                 ) {
10543                         checkkwd |= CHKALIAS;
10544                 }
10545                 if (sp->string != sp->ap->val) {
10546                         free(sp->string);
10547                 }
10548                 sp->ap->flag &= ~ALIASINUSE;
10549                 if (sp->ap->flag & ALIASDEAD) {
10550                         unalias(sp->ap->name);
10551                 }
10552         }
10553 #endif
10554         g_parsefile->next_to_pgetc = sp->prev_string;
10555         g_parsefile->left_in_line = sp->prev_left_in_line;
10556         g_parsefile->unget = sp->unget;
10557         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10558         g_parsefile->strpush = sp->prev;
10559         if (sp != &(g_parsefile->basestrpush))
10560                 free(sp);
10561         INT_ON;
10562 }
10563
10564 static int
10565 preadfd(void)
10566 {
10567         int nr;
10568         char *buf = g_parsefile->buf;
10569
10570         g_parsefile->next_to_pgetc = buf;
10571 #if ENABLE_FEATURE_EDITING
10572  retry:
10573         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10574                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10575         else {
10576 # if ENABLE_ASH_IDLE_TIMEOUT
10577                 int timeout = -1;
10578                 const char *tmout_var = lookupvar("TMOUT");
10579                 if (tmout_var) {
10580                         timeout = atoi(tmout_var) * 1000;
10581                         if (timeout <= 0)
10582                                 timeout = -1;
10583                 }
10584                 line_input_state->timeout = timeout;
10585 # endif
10586 # if ENABLE_FEATURE_TAB_COMPLETION
10587                 line_input_state->path_lookup = pathval();
10588 # endif
10589                 reinit_unicode_for_ash();
10590                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10591                 if (nr == 0) {
10592                         /* ^C pressed, "convert" to SIGINT */
10593                         write(STDOUT_FILENO, "^C", 2);
10594                         if (trap[SIGINT]) {
10595                                 buf[0] = '\n';
10596                                 buf[1] = '\0';
10597                                 raise(SIGINT);
10598                                 return 1;
10599                         }
10600                         exitstatus = 128 + SIGINT;
10601                         bb_putchar('\n');
10602                         goto retry;
10603                 }
10604                 if (nr < 0) {
10605                         if (errno == 0) {
10606                                 /* Ctrl+D pressed */
10607                                 nr = 0;
10608                         }
10609 # if ENABLE_ASH_IDLE_TIMEOUT
10610                         else if (errno == EAGAIN && timeout > 0) {
10611                                 puts("\007timed out waiting for input: auto-logout");
10612                                 exitshell();
10613                         }
10614 # endif
10615                 }
10616         }
10617 #else
10618         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10619 #endif
10620
10621 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10622         if (nr < 0) {
10623                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10624                         int flags = fcntl(0, F_GETFL);
10625                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10626                                 flags &= ~O_NONBLOCK;
10627                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10628                                         out2str("sh: turning off NDELAY mode\n");
10629                                         goto retry;
10630                                 }
10631                         }
10632                 }
10633         }
10634 #endif
10635         return nr;
10636 }
10637
10638 /*
10639  * Refill the input buffer and return the next input character:
10640  *
10641  * 1) If a string was pushed back on the input, pop it;
10642  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10643  *    or we are reading from a string so we can't refill the buffer,
10644  *    return EOF.
10645  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10646  * 4) Process input up to the next newline, deleting nul characters.
10647  */
10648 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10649 #define pgetc_debug(...) ((void)0)
10650 static int pgetc(void);
10651 static int
10652 preadbuffer(void)
10653 {
10654         char *q;
10655         int more;
10656
10657         if (g_parsefile->strpush) {
10658 #if ENABLE_ASH_ALIAS
10659                 if (g_parsefile->left_in_line == -1
10660                  && g_parsefile->strpush->ap
10661                  && g_parsefile->next_to_pgetc[-1] != ' '
10662                  && g_parsefile->next_to_pgetc[-1] != '\t'
10663                 ) {
10664                         pgetc_debug("preadbuffer PEOA");
10665                         return PEOA;
10666                 }
10667 #endif
10668                 popstring();
10669                 return pgetc();
10670         }
10671         /* on both branches above g_parsefile->left_in_line < 0.
10672          * "pgetc" needs refilling.
10673          */
10674
10675         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10676          * pungetc() may increment it a few times.
10677          * Assuming it won't increment it to less than -90.
10678          */
10679         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10680                 pgetc_debug("preadbuffer PEOF1");
10681                 /* even in failure keep left_in_line and next_to_pgetc
10682                  * in lock step, for correct multi-layer pungetc.
10683                  * left_in_line was decremented before preadbuffer(),
10684                  * must inc next_to_pgetc: */
10685                 g_parsefile->next_to_pgetc++;
10686                 return PEOF;
10687         }
10688
10689         more = g_parsefile->left_in_buffer;
10690         if (more <= 0) {
10691                 flush_stdout_stderr();
10692  again:
10693                 more = preadfd();
10694                 if (more <= 0) {
10695                         /* don't try reading again */
10696                         g_parsefile->left_in_line = -99;
10697                         pgetc_debug("preadbuffer PEOF2");
10698                         g_parsefile->next_to_pgetc++;
10699                         return PEOF;
10700                 }
10701         }
10702
10703         /* Find out where's the end of line.
10704          * Set g_parsefile->left_in_line
10705          * and g_parsefile->left_in_buffer acordingly.
10706          * NUL chars are deleted.
10707          */
10708         q = g_parsefile->next_to_pgetc;
10709         for (;;) {
10710                 char c;
10711
10712                 more--;
10713
10714                 c = *q;
10715                 if (c == '\0') {
10716                         memmove(q, q + 1, more);
10717                 } else {
10718                         q++;
10719                         if (c == '\n') {
10720                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10721                                 break;
10722                         }
10723                 }
10724
10725                 if (more <= 0) {
10726                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10727                         if (g_parsefile->left_in_line < 0)
10728                                 goto again;
10729                         break;
10730                 }
10731         }
10732         g_parsefile->left_in_buffer = more;
10733
10734         if (vflag) {
10735                 char save = *q;
10736                 *q = '\0';
10737                 out2str(g_parsefile->next_to_pgetc);
10738                 *q = save;
10739         }
10740
10741         pgetc_debug("preadbuffer at %d:%p'%s'",
10742                         g_parsefile->left_in_line,
10743                         g_parsefile->next_to_pgetc,
10744                         g_parsefile->next_to_pgetc);
10745         return (unsigned char)*g_parsefile->next_to_pgetc++;
10746 }
10747
10748 static void
10749 nlprompt(void)
10750 {
10751         g_parsefile->linno++;
10752         setprompt_if(doprompt, 2);
10753 }
10754 static void
10755 nlnoprompt(void)
10756 {
10757         g_parsefile->linno++;
10758         needprompt = doprompt;
10759 }
10760
10761 static int
10762 pgetc(void)
10763 {
10764         int c;
10765
10766         pgetc_debug("pgetc at %d:%p'%s'",
10767                         g_parsefile->left_in_line,
10768                         g_parsefile->next_to_pgetc,
10769                         g_parsefile->next_to_pgetc);
10770         if (g_parsefile->unget)
10771                 return g_parsefile->lastc[--g_parsefile->unget];
10772
10773         if (--g_parsefile->left_in_line >= 0)
10774                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10775         else
10776                 c = preadbuffer();
10777
10778         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10779         g_parsefile->lastc[0] = c;
10780
10781         return c;
10782 }
10783
10784 #if ENABLE_ASH_ALIAS
10785 static int
10786 pgetc_without_PEOA(void)
10787 {
10788         int c;
10789         do {
10790                 pgetc_debug("pgetc at %d:%p'%s'",
10791                                 g_parsefile->left_in_line,
10792                                 g_parsefile->next_to_pgetc,
10793                                 g_parsefile->next_to_pgetc);
10794                 c = pgetc();
10795         } while (c == PEOA);
10796         return c;
10797 }
10798 #else
10799 # define pgetc_without_PEOA() pgetc()
10800 #endif
10801
10802 /*
10803  * Undo a call to pgetc.  Only two characters may be pushed back.
10804  * PEOF may be pushed back.
10805  */
10806 static void
10807 pungetc(void)
10808 {
10809         g_parsefile->unget++;
10810 }
10811
10812 /* This one eats backslash+newline */
10813 static int
10814 pgetc_eatbnl(void)
10815 {
10816         int c;
10817
10818         while ((c = pgetc()) == '\\') {
10819                 if (pgetc() != '\n') {
10820                         pungetc();
10821                         break;
10822                 }
10823
10824                 nlprompt();
10825         }
10826
10827         return c;
10828 }
10829
10830 struct synstack {
10831         smalluint syntax;
10832         uint8_t innerdq   :1;
10833         uint8_t varpushed :1;
10834         uint8_t dblquote  :1;
10835         int varnest;            /* levels of variables expansion */
10836         int dqvarnest;          /* levels of variables expansion within double quotes */
10837         int parenlevel;         /* levels of parens in arithmetic */
10838         struct synstack *prev;
10839         struct synstack *next;
10840 };
10841
10842 static int
10843 pgetc_top(struct synstack *stack)
10844 {
10845         return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
10846 }
10847
10848 static void
10849 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10850 {
10851         memset(next, 0, sizeof(*next));
10852         next->syntax = syntax;
10853         next->next = *stack;
10854         (*stack)->prev = next;
10855         *stack = next;
10856 }
10857
10858 static ALWAYS_INLINE void
10859 synstack_pop(struct synstack **stack)
10860 {
10861         *stack = (*stack)->next;
10862 }
10863
10864 /*
10865  * To handle the "." command, a stack of input files is used.  Pushfile
10866  * adds a new entry to the stack and popfile restores the previous level.
10867  */
10868 static void
10869 pushfile(void)
10870 {
10871         struct parsefile *pf;
10872
10873         pf = ckzalloc(sizeof(*pf));
10874         pf->prev = g_parsefile;
10875         pf->pf_fd = -1;
10876         /*pf->strpush = NULL; - ckzalloc did it */
10877         /*pf->basestrpush.prev = NULL;*/
10878         /*pf->unget = 0;*/
10879         g_parsefile = pf;
10880 }
10881
10882 static void
10883 popfile(void)
10884 {
10885         struct parsefile *pf = g_parsefile;
10886
10887         if (pf == &basepf)
10888                 return;
10889
10890         INT_OFF;
10891         if (pf->pf_fd >= 0)
10892                 close(pf->pf_fd);
10893         free(pf->buf);
10894         while (pf->strpush)
10895                 popstring();
10896         g_parsefile = pf->prev;
10897         free(pf);
10898         INT_ON;
10899 }
10900
10901 static void
10902 unwindfiles(struct parsefile *stop)
10903 {
10904         while (g_parsefile != stop)
10905                 popfile();
10906 }
10907
10908 /*
10909  * Return to top level.
10910  */
10911 static void
10912 popallfiles(void)
10913 {
10914         unwindfiles(&basepf);
10915 }
10916
10917 /*
10918  * Close the file(s) that the shell is reading commands from.  Called
10919  * after a fork is done.
10920  */
10921 static void
10922 closescript(void)
10923 {
10924         popallfiles();
10925         if (g_parsefile->pf_fd > 0) {
10926                 close(g_parsefile->pf_fd);
10927                 g_parsefile->pf_fd = 0;
10928         }
10929 }
10930
10931 /*
10932  * Like setinputfile, but takes an open file descriptor.  Call this with
10933  * interrupts off.
10934  */
10935 static void
10936 setinputfd(int fd, int push)
10937 {
10938         if (push) {
10939                 pushfile();
10940                 g_parsefile->buf = NULL;
10941         }
10942         g_parsefile->pf_fd = fd;
10943         if (g_parsefile->buf == NULL)
10944                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10945         g_parsefile->left_in_buffer = 0;
10946         g_parsefile->left_in_line = 0;
10947         g_parsefile->linno = 1;
10948 }
10949
10950 /*
10951  * Set the input to take input from a file.  If push is set, push the
10952  * old input onto the stack first.
10953  */
10954 static int
10955 setinputfile(const char *fname, int flags)
10956 {
10957         int fd;
10958
10959         INT_OFF;
10960         fd = open(fname, O_RDONLY | O_CLOEXEC);
10961         if (fd < 0) {
10962                 if (flags & INPUT_NOFILE_OK)
10963                         goto out;
10964                 exitstatus = 127;
10965                 ash_msg_and_raise_perror("can't open '%s'", fname);
10966         }
10967         if (fd < 10)
10968                 fd = savefd(fd);
10969         else if (O_CLOEXEC == 0) /* old libc */
10970                 close_on_exec_on(fd);
10971
10972         setinputfd(fd, flags & INPUT_PUSH_FILE);
10973  out:
10974         INT_ON;
10975         return fd;
10976 }
10977
10978 /*
10979  * Like setinputfile, but takes input from a string.
10980  */
10981 static void
10982 setinputstring(char *string)
10983 {
10984         INT_OFF;
10985         pushfile();
10986         g_parsefile->next_to_pgetc = string;
10987         g_parsefile->left_in_line = strlen(string);
10988         g_parsefile->buf = NULL;
10989         g_parsefile->linno = 1;
10990         INT_ON;
10991 }
10992
10993
10994 /*
10995  * Routines to check for mail.
10996  */
10997
10998 #if ENABLE_ASH_MAIL
10999
11000 /* Hash of mtimes of mailboxes */
11001 static unsigned mailtime_hash;
11002 /* Set if MAIL or MAILPATH is changed. */
11003 static smallint mail_var_path_changed;
11004
11005 /*
11006  * Print appropriate message(s) if mail has arrived.
11007  * If mail_var_path_changed is set,
11008  * then the value of MAIL has mail_var_path_changed,
11009  * so we just update the values.
11010  */
11011 static void
11012 chkmail(void)
11013 {
11014         const char *mpath;
11015         char *p;
11016         char *q;
11017         unsigned new_hash;
11018         struct stackmark smark;
11019         struct stat statb;
11020
11021         setstackmark(&smark);
11022         mpath = mpathset() ? mpathval() : mailval();
11023         new_hash = 0;
11024         for (;;) {
11025                 int len;
11026
11027                 len = padvance(&mpath, nullstr);
11028                 if (!len)
11029                         break;
11030                 p = stackblock();
11031                         break;
11032                 if (*p == '\0')
11033                         continue;
11034                 for (q = p; *q; q++)
11035                         continue;
11036 #if DEBUG
11037                 if (q[-1] != '/')
11038                         abort();
11039 #endif
11040                 q[-1] = '\0';                   /* delete trailing '/' */
11041                 if (stat(p, &statb) < 0) {
11042                         continue;
11043                 }
11044                 /* Very simplistic "hash": just a sum of all mtimes */
11045                 new_hash += (unsigned)statb.st_mtime;
11046         }
11047         if (!mail_var_path_changed && mailtime_hash != new_hash) {
11048                 if (mailtime_hash != 0)
11049                         out2str("you have mail\n");
11050                 mailtime_hash = new_hash;
11051         }
11052         mail_var_path_changed = 0;
11053         popstackmark(&smark);
11054 }
11055
11056 static void FAST_FUNC
11057 changemail(const char *val UNUSED_PARAM)
11058 {
11059         mail_var_path_changed = 1;
11060 }
11061
11062 #endif /* ASH_MAIL */
11063
11064
11065 /* ============ ??? */
11066
11067 /*
11068  * Set the shell parameters.
11069  */
11070 static void
11071 setparam(char **argv)
11072 {
11073         char **newparam;
11074         char **ap;
11075         int nparam;
11076
11077         for (nparam = 0; argv[nparam]; nparam++)
11078                 continue;
11079         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11080         while (*argv) {
11081                 *ap++ = ckstrdup(*argv++);
11082         }
11083         *ap = NULL;
11084         freeparam(&shellparam);
11085         shellparam.malloced = 1;
11086         shellparam.nparam = nparam;
11087         shellparam.p = newparam;
11088 #if ENABLE_ASH_GETOPTS
11089         shellparam.optind = 1;
11090         shellparam.optoff = -1;
11091 #endif
11092 }
11093
11094 /*
11095  * Process shell options.  The global variable argptr contains a pointer
11096  * to the argument list; we advance it past the options.
11097  *
11098  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11099  * For a non-interactive shell, an error condition encountered
11100  * by a special built-in ... shall cause the shell to write a diagnostic message
11101  * to standard error and exit as shown in the following table:
11102  * Error                                           Special Built-In
11103  * ...
11104  * Utility syntax error (option or operand error)  Shall exit
11105  * ...
11106  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11107  * we see that bash does not do that (set "finishes" with error code 1 instead,
11108  * and shell continues), and people rely on this behavior!
11109  * Testcase:
11110  * set -o barfoo 2>/dev/null
11111  * echo $?
11112  *
11113  * Oh well. Let's mimic that.
11114  */
11115 static int
11116 plus_minus_o(char *name, int val)
11117 {
11118         int i;
11119
11120         if (name) {
11121                 for (i = 0; i < NOPTS; i++) {
11122                         if (strcmp(name, optnames(i)) == 0) {
11123                                 optlist[i] = val;
11124                                 return 0;
11125                         }
11126                 }
11127                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
11128                 return 1;
11129         }
11130         for (i = 0; i < NOPTS; i++) {
11131                 if (optnames(i)[0] == '\0')
11132                         continue;
11133                 if (val) {
11134                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11135                 } else {
11136                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11137                 }
11138         }
11139         return 0;
11140 }
11141 static void
11142 setoption(int flag, int val)
11143 {
11144         int i;
11145
11146         for (i = 0; i < NOPTS; i++) {
11147                 if (optletters(i) == flag && optnames(i)[0] != '\0') {
11148                         optlist[i] = val;
11149                         return;
11150                 }
11151         }
11152         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11153         /* NOTREACHED */
11154 }
11155 /* If login_sh is not NULL, we are called to parse command line opts,
11156  * not "set -opts"
11157  */
11158 static int
11159 options(int *login_sh)
11160 {
11161         char *p;
11162         int val;
11163         int c;
11164
11165         if (login_sh)
11166                 minusc = NULL;
11167         while ((p = *argptr) != NULL) {
11168                 c = *p++;
11169                 if (c != '-' && c != '+')
11170                         break;
11171                 argptr++;
11172                 val = 0; /* val = 0 if c == '+' */
11173                 if (c == '-') {
11174                         val = 1;
11175                         if (p[0] == '\0' || LONE_DASH(p)) {
11176                                 if (!login_sh) {
11177                                         /* "-" means turn off -x and -v */
11178                                         if (p[0] == '\0')
11179                                                 xflag = vflag = 0;
11180                                         /* "--" means reset params */
11181                                         else if (*argptr == NULL)
11182                                                 setparam(argptr);
11183                                 }
11184                                 break;    /* "-" or "--" terminates options */
11185                         }
11186                 }
11187                 /* first char was + or - */
11188                 while ((c = *p++) != '\0') {
11189                         if (login_sh) {
11190                                 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11191                                 if (c == 'c') {
11192                                         minusc = p; /* command is after shell args */
11193                                         cflag = 1;
11194                                         continue;
11195                                 }
11196                                 if (c == 's') { /* -s, +s */
11197                                         sflag = 1;
11198                                         continue;
11199                                 }
11200                                 if (c == 'i') { /* -i, +i */
11201                                         iflag = 1;
11202                                         continue;
11203                                 }
11204                                 if (c == 'l') {
11205                                         *login_sh = 1; /* -l or +l == --login */
11206                                         continue;
11207                                 }
11208                                 /* bash does not accept +-login, we also won't */
11209                                 if (val && (c == '-')) { /* long options */
11210                                         if (strcmp(p, "login") == 0) {
11211                                                 *login_sh = 1;
11212                                         }
11213                                         break;
11214                                 }
11215                         }
11216                         if (c == 'o') {
11217                                 if (plus_minus_o(*argptr, val)) {
11218                                         /* it already printed err message */
11219                                         return 1; /* error */
11220                                 }
11221                                 if (*argptr)
11222                                         argptr++;
11223                         } else {
11224                                 setoption(c, val);
11225                         }
11226                 }
11227         }
11228         return 0;
11229 }
11230
11231 /*
11232  * The shift builtin command.
11233  */
11234 static int FAST_FUNC
11235 shiftcmd(int argc UNUSED_PARAM, char **argv)
11236 {
11237         int n;
11238         char **ap1, **ap2;
11239
11240         n = 1;
11241         if (argv[1])
11242                 n = number(argv[1]);
11243         if (n > shellparam.nparam)
11244                 return 1;
11245         INT_OFF;
11246         shellparam.nparam -= n;
11247         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11248                 if (shellparam.malloced)
11249                         free(*ap1);
11250         }
11251         ap2 = shellparam.p;
11252         while ((*ap2++ = *ap1++) != NULL)
11253                 continue;
11254 #if ENABLE_ASH_GETOPTS
11255         shellparam.optind = 1;
11256         shellparam.optoff = -1;
11257 #endif
11258         INT_ON;
11259         return 0;
11260 }
11261
11262 /*
11263  * POSIX requires that 'set' (but not export or readonly) output the
11264  * variables in lexicographic order - by the locale's collating order (sigh).
11265  * Maybe we could keep them in an ordered balanced binary tree
11266  * instead of hashed lists.
11267  * For now just roll 'em through qsort for printing...
11268  */
11269 static int
11270 showvars(const char *sep_prefix, int on, int off)
11271 {
11272         const char *sep;
11273         char **ep, **epend;
11274
11275         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11276         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11277
11278         sep = *sep_prefix ? " " : sep_prefix;
11279
11280         for (; ep < epend; ep++) {
11281                 const char *p;
11282                 const char *q;
11283
11284                 p = endofname(*ep);
11285 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11286  * makes "export -p" to have output not suitable for "eval":
11287  * import os
11288  * os.environ["test-test"]="test"
11289  * if os.fork() == 0:
11290  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11291  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11292  */
11293                 q = nullstr;
11294                 if (*p == '=')
11295                         q = single_quote(++p);
11296                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11297         }
11298         return 0;
11299 }
11300
11301 /*
11302  * The set command builtin.
11303  */
11304 static int FAST_FUNC
11305 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11306 {
11307         int retval;
11308
11309         if (!argv[1])
11310                 return showvars(nullstr, 0, VUNSET);
11311
11312         INT_OFF;
11313         retval = options(/*login_sh:*/ NULL);
11314         if (retval == 0) { /* if no parse error... */
11315                 optschanged();
11316                 if (*argptr != NULL) {
11317                         setparam(argptr);
11318                 }
11319         }
11320         INT_ON;
11321         return retval;
11322 }
11323
11324 #if ENABLE_ASH_RANDOM_SUPPORT
11325 static void FAST_FUNC
11326 change_random(const char *value)
11327 {
11328         uint32_t t;
11329
11330         if (value == NULL) {
11331                 /* "get", generate */
11332                 t = next_random(&random_gen);
11333                 /* set without recursion */
11334                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11335                 vrandom.flags &= ~VNOFUNC;
11336         } else {
11337                 /* set/reset */
11338                 t = strtoul(value, NULL, 10);
11339                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11340         }
11341 }
11342 #endif
11343
11344 #if BASH_EPOCH_VARS
11345 static void FAST_FUNC
11346 change_epoch(struct var *vepoch, const char *fmt)
11347 {
11348         struct timeval tv;
11349         char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3];
11350
11351         gettimeofday(&tv, NULL);
11352         sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec);
11353         setvar(vepoch->var_text, buffer, VNOFUNC);
11354         vepoch->flags &= ~VNOFUNC;
11355 }
11356
11357 static void FAST_FUNC
11358 change_seconds(const char *value UNUSED_PARAM)
11359 {
11360         change_epoch(&vepochs, "%lu");
11361 }
11362
11363 static void FAST_FUNC
11364 change_realtime(const char *value UNUSED_PARAM)
11365 {
11366         change_epoch(&vepochr, "%lu.%06u");
11367 }
11368 #endif
11369
11370 #if ENABLE_ASH_GETOPTS
11371 static int
11372 getopts(char *optstr, char *optvar, char **optfirst)
11373 {
11374         char *p, *q;
11375         char c = '?';
11376         int done = 0;
11377         char sbuf[2];
11378         char **optnext;
11379         int ind = shellparam.optind;
11380         int off = shellparam.optoff;
11381
11382         sbuf[1] = '\0';
11383
11384         shellparam.optind = -1;
11385         optnext = optfirst + ind - 1;
11386
11387         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11388                 p = NULL;
11389         else
11390                 p = optnext[-1] + off;
11391         if (p == NULL || *p == '\0') {
11392                 /* Current word is done, advance */
11393                 p = *optnext;
11394                 if (p == NULL || *p != '-' || *++p == '\0') {
11395  atend:
11396                         unsetvar("OPTARG");
11397                         p = NULL;
11398                         done = 1;
11399                         goto out;
11400                 }
11401                 optnext++;
11402                 if (LONE_DASH(p))        /* check for "--" */
11403                         goto atend;
11404         }
11405
11406         c = *p++;
11407         for (q = optstr; *q != c;) {
11408                 if (*q == '\0') {
11409                         /* OPTERR is a bashism */
11410                         const char *cp = lookupvar("OPTERR");
11411                         if ((cp && LONE_CHAR(cp, '0'))
11412                          || (optstr[0] == ':')
11413                         ) {
11414                                 sbuf[0] = c;
11415                                 /*sbuf[1] = '\0'; - already is */
11416                                 setvar0("OPTARG", sbuf);
11417                         } else {
11418                                 fprintf(stderr, "Illegal option -%c\n", c);
11419                                 unsetvar("OPTARG");
11420                         }
11421                         c = '?';
11422                         goto out;
11423                 }
11424                 if (*++q == ':')
11425                         q++;
11426         }
11427
11428         if (*++q == ':') {
11429                 if (*p == '\0' && (p = *optnext) == NULL) {
11430                         /* OPTERR is a bashism */
11431                         const char *cp = lookupvar("OPTERR");
11432                         if ((cp && LONE_CHAR(cp, '0'))
11433                          || (optstr[0] == ':')
11434                         ) {
11435                                 sbuf[0] = c;
11436                                 /*sbuf[1] = '\0'; - already is */
11437                                 setvar0("OPTARG", sbuf);
11438                                 c = ':';
11439                         } else {
11440                                 fprintf(stderr, "No arg for -%c option\n", c);
11441                                 unsetvar("OPTARG");
11442                                 c = '?';
11443                         }
11444                         goto out;
11445                 }
11446
11447                 if (p == *optnext)
11448                         optnext++;
11449                 setvar0("OPTARG", p);
11450                 p = NULL;
11451         } else
11452                 setvar0("OPTARG", nullstr);
11453  out:
11454         ind = optnext - optfirst + 1;
11455         setvar("OPTIND", itoa(ind), VNOFUNC);
11456         sbuf[0] = c;
11457         /*sbuf[1] = '\0'; - already is */
11458         setvar0(optvar, sbuf);
11459
11460         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11461         shellparam.optind = ind;
11462
11463         return done;
11464 }
11465
11466 /*
11467  * The getopts builtin.  Shellparam.optnext points to the next argument
11468  * to be processed.  Shellparam.optptr points to the next character to
11469  * be processed in the current argument.  If shellparam.optnext is NULL,
11470  * then it's the first time getopts has been called.
11471  */
11472 static int FAST_FUNC
11473 getoptscmd(int argc, char **argv)
11474 {
11475         char **optbase;
11476
11477         if (argc < 3)
11478                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11479         if (argc == 3) {
11480                 optbase = shellparam.p;
11481                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11482                         shellparam.optind = 1;
11483                         shellparam.optoff = -1;
11484                 }
11485         } else {
11486                 optbase = &argv[3];
11487                 if ((unsigned)shellparam.optind > argc - 2) {
11488                         shellparam.optind = 1;
11489                         shellparam.optoff = -1;
11490                 }
11491         }
11492
11493         return getopts(argv[1], argv[2], optbase);
11494 }
11495 #endif /* ASH_GETOPTS */
11496
11497
11498 /* ============ Shell parser */
11499
11500 struct heredoc {
11501         struct heredoc *next;   /* next here document in list */
11502         union node *here;       /* redirection node */
11503         char *eofmark;          /* string indicating end of input */
11504         smallint striptabs;     /* if set, strip leading tabs */
11505 };
11506
11507 static smallint tokpushback;           /* last token pushed back */
11508 static smallint quoteflag;             /* set if (part of) last token was quoted */
11509 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11510 static struct heredoc *heredoclist;    /* list of here documents to read */
11511 static char *wordtext;                 /* text of last word returned by readtoken */
11512 static struct nodelist *backquotelist;
11513 static union node *redirnode;
11514 static struct heredoc *heredoc;
11515
11516 static const char *
11517 tokname(char *buf, int tok)
11518 {
11519         if (tok < TSEMI)
11520                 return tokname_array[tok];
11521         sprintf(buf, "\"%s\"", tokname_array[tok]);
11522         return buf;
11523 }
11524
11525 /* raise_error_unexpected_syntax:
11526  * Called when an unexpected token is read during the parse.  The argument
11527  * is the token that is expected, or -1 if more than one type of token can
11528  * occur at this point.
11529  */
11530 static void raise_error_unexpected_syntax(int) NORETURN;
11531 static void
11532 raise_error_unexpected_syntax(int token)
11533 {
11534         char msg[64];
11535         char buf[16];
11536         int l;
11537
11538         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11539         if (token >= 0)
11540                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11541         raise_error_syntax(msg);
11542         /* NOTREACHED */
11543 }
11544
11545 /* parsing is heavily cross-recursive, need these forward decls */
11546 static union node *andor(void);
11547 static union node *pipeline(void);
11548 static union node *parse_command(void);
11549 static void parseheredoc(void);
11550 static int peektoken(void);
11551 static int readtoken(void);
11552
11553 static union node *
11554 list(int nlflag)
11555 {
11556         union node *n1, *n2, *n3;
11557         int tok;
11558
11559         n1 = NULL;
11560         for (;;) {
11561                 switch (peektoken()) {
11562                 case TNL:
11563                         if (!(nlflag & 1))
11564                                 break;
11565                         parseheredoc();
11566                         return n1;
11567
11568                 case TEOF:
11569                         if (!n1 && (nlflag & 1))
11570                                 n1 = NODE_EOF;
11571                         parseheredoc();
11572                         return n1;
11573                 }
11574
11575                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11576                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11577                         return n1;
11578                 nlflag |= 2;
11579
11580                 n2 = andor();
11581                 tok = readtoken();
11582                 if (tok == TBACKGND) {
11583                         if (n2->type == NPIPE) {
11584                                 n2->npipe.pipe_backgnd = 1;
11585                         } else {
11586                                 if (n2->type != NREDIR) {
11587                                         n3 = stzalloc(sizeof(struct nredir));
11588                                         n3->nredir.n = n2;
11589                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11590                                         n2 = n3;
11591                                 }
11592                                 n2->type = NBACKGND;
11593                         }
11594                 }
11595                 if (n1 == NULL) {
11596                         n1 = n2;
11597                 } else {
11598                         n3 = stzalloc(sizeof(struct nbinary));
11599                         n3->type = NSEMI;
11600                         n3->nbinary.ch1 = n1;
11601                         n3->nbinary.ch2 = n2;
11602                         n1 = n3;
11603                 }
11604                 switch (tok) {
11605                 case TNL:
11606                 case TEOF:
11607                         tokpushback = 1;
11608                         /* fall through */
11609                 case TBACKGND:
11610                 case TSEMI:
11611                         break;
11612                 default:
11613                         if ((nlflag & 1))
11614                                 raise_error_unexpected_syntax(-1);
11615                         tokpushback = 1;
11616                         return n1;
11617                 }
11618         }
11619 }
11620
11621 static union node *
11622 andor(void)
11623 {
11624         union node *n1, *n2, *n3;
11625         int t;
11626
11627         n1 = pipeline();
11628         for (;;) {
11629                 t = readtoken();
11630                 if (t == TAND) {
11631                         t = NAND;
11632                 } else if (t == TOR) {
11633                         t = NOR;
11634                 } else {
11635                         tokpushback = 1;
11636                         return n1;
11637                 }
11638                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11639                 n2 = pipeline();
11640                 n3 = stzalloc(sizeof(struct nbinary));
11641                 n3->type = t;
11642                 n3->nbinary.ch1 = n1;
11643                 n3->nbinary.ch2 = n2;
11644                 n1 = n3;
11645         }
11646 }
11647
11648 static union node *
11649 pipeline(void)
11650 {
11651         union node *n1, *n2, *pipenode;
11652         struct nodelist *lp, *prev;
11653         int negate;
11654
11655         negate = 0;
11656         TRACE(("pipeline: entered\n"));
11657         if (readtoken() == TNOT) {
11658                 negate = !negate;
11659                 checkkwd = CHKKWD | CHKALIAS;
11660         } else
11661                 tokpushback = 1;
11662         n1 = parse_command();
11663         if (readtoken() == TPIPE) {
11664                 pipenode = stzalloc(sizeof(struct npipe));
11665                 pipenode->type = NPIPE;
11666                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11667                 lp = stzalloc(sizeof(struct nodelist));
11668                 pipenode->npipe.cmdlist = lp;
11669                 lp->n = n1;
11670                 do {
11671                         prev = lp;
11672                         lp = stzalloc(sizeof(struct nodelist));
11673                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11674                         lp->n = parse_command();
11675                         prev->next = lp;
11676                 } while (readtoken() == TPIPE);
11677                 lp->next = NULL;
11678                 n1 = pipenode;
11679         }
11680         tokpushback = 1;
11681         if (negate) {
11682                 n2 = stzalloc(sizeof(struct nnot));
11683                 n2->type = NNOT;
11684                 n2->nnot.com = n1;
11685                 return n2;
11686         }
11687         return n1;
11688 }
11689
11690 static union node *
11691 makename(void)
11692 {
11693         union node *n;
11694
11695         n = stzalloc(sizeof(struct narg));
11696         n->type = NARG;
11697         /*n->narg.next = NULL; - stzalloc did it */
11698         n->narg.text = wordtext;
11699         n->narg.backquote = backquotelist;
11700         return n;
11701 }
11702
11703 static void
11704 fixredir(union node *n, const char *text, int err)
11705 {
11706         int fd;
11707
11708         TRACE(("Fix redir %s %d\n", text, err));
11709         if (!err)
11710                 n->ndup.vname = NULL;
11711
11712         fd = bb_strtou(text, NULL, 10);
11713         if (!errno && fd >= 0)
11714                 n->ndup.dupfd = fd;
11715         else if (LONE_DASH(text))
11716                 n->ndup.dupfd = -1;
11717         else {
11718                 if (err)
11719                         raise_error_syntax("bad fd number");
11720                 n->ndup.vname = makename();
11721         }
11722 }
11723
11724 static void
11725 parsefname(void)
11726 {
11727         union node *n = redirnode;
11728
11729         if (n->type == NHERE)
11730                 checkkwd = CHKEOFMARK;
11731         if (readtoken() != TWORD)
11732                 raise_error_unexpected_syntax(-1);
11733         if (n->type == NHERE) {
11734                 struct heredoc *here = heredoc;
11735                 struct heredoc *p;
11736
11737                 if (quoteflag == 0)
11738                         n->type = NXHERE;
11739                 TRACE(("Here document %d\n", n->type));
11740                 rmescapes(wordtext, 0, NULL);
11741                 here->eofmark = wordtext;
11742                 here->next = NULL;
11743                 if (heredoclist == NULL)
11744                         heredoclist = here;
11745                 else {
11746                         for (p = heredoclist; p->next; p = p->next)
11747                                 continue;
11748                         p->next = here;
11749                 }
11750         } else if (n->type == NTOFD || n->type == NFROMFD) {
11751                 fixredir(n, wordtext, 0);
11752         } else {
11753                 n->nfile.fname = makename();
11754         }
11755 }
11756
11757 static union node *
11758 simplecmd(void)
11759 {
11760         union node *args, **app;
11761         union node *n = NULL;
11762         union node *vars, **vpp;
11763         union node **rpp, *redir;
11764         int savecheckkwd;
11765         int savelinno;
11766 #if BASH_TEST2
11767         smallint double_brackets_flag = 0;
11768 #endif
11769         IF_BASH_FUNCTION(smallint function_flag = 0;)
11770
11771         args = NULL;
11772         app = &args;
11773         vars = NULL;
11774         vpp = &vars;
11775         redir = NULL;
11776         rpp = &redir;
11777
11778         savecheckkwd = CHKALIAS;
11779         savelinno = g_parsefile->linno;
11780         for (;;) {
11781                 int t;
11782                 checkkwd = savecheckkwd;
11783                 t = readtoken();
11784                 switch (t) {
11785 #if BASH_FUNCTION
11786                 case TFUNCTION:
11787                         if (peektoken() != TWORD)
11788                                 raise_error_unexpected_syntax(TWORD);
11789                         function_flag = 1;
11790                         break;
11791 #endif
11792 #if BASH_TEST2
11793                 case TAND: /* "&&" */
11794                 case TOR: /* "||" */
11795                         if (!double_brackets_flag) {
11796                                 tokpushback = 1;
11797                                 goto out;
11798                         }
11799                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11800 #endif
11801                 case TWORD:
11802                         n = stzalloc(sizeof(struct narg));
11803                         n->type = NARG;
11804                         /*n->narg.next = NULL; - stzalloc did it */
11805                         n->narg.text = wordtext;
11806 #if BASH_TEST2
11807                         if (strcmp("[[", wordtext) == 0)
11808                                 double_brackets_flag = 1;
11809                         else if (strcmp("]]", wordtext) == 0)
11810                                 double_brackets_flag = 0;
11811 #endif
11812                         n->narg.backquote = backquotelist;
11813                         if (savecheckkwd && isassignment(wordtext)) {
11814                                 *vpp = n;
11815                                 vpp = &n->narg.next;
11816                         } else {
11817                                 *app = n;
11818                                 app = &n->narg.next;
11819                                 savecheckkwd = 0;
11820                         }
11821 #if BASH_FUNCTION
11822                         if (function_flag) {
11823                                 checkkwd = CHKNL | CHKKWD;
11824                                 switch (peektoken()) {
11825                                 case TBEGIN:
11826                                 case TIF:
11827                                 case TCASE:
11828                                 case TUNTIL:
11829                                 case TWHILE:
11830                                 case TFOR:
11831                                         goto do_func;
11832                                 case TLP:
11833                                         function_flag = 0;
11834                                         break;
11835 # if BASH_TEST2
11836                                 case TWORD:
11837                                         if (strcmp("[[", wordtext) == 0)
11838                                                 goto do_func;
11839                                         /* fall through */
11840 # endif
11841                                 default:
11842                                         raise_error_unexpected_syntax(-1);
11843                                 }
11844                         }
11845 #endif
11846                         break;
11847                 case TREDIR:
11848                         *rpp = n = redirnode;
11849                         rpp = &n->nfile.next;
11850                         parsefname();   /* read name of redirection file */
11851                         break;
11852                 case TLP:
11853  IF_BASH_FUNCTION(do_func:)
11854                         if (args && app == &args->narg.next
11855                          && !vars && !redir
11856                         ) {
11857                                 struct builtincmd *bcmd;
11858                                 const char *name;
11859
11860                                 /* We have a function */
11861                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11862                                         raise_error_unexpected_syntax(TRP);
11863                                 name = n->narg.text;
11864                                 if (!goodname(name)
11865                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11866                                 ) {
11867                                         raise_error_syntax("bad function name");
11868                                 }
11869                                 n->type = NDEFUN;
11870                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11871                                 n->ndefun.text = n->narg.text;
11872                                 n->ndefun.linno = g_parsefile->linno;
11873                                 n->ndefun.body = parse_command();
11874                                 return n;
11875                         }
11876                         IF_BASH_FUNCTION(function_flag = 0;)
11877                         /* fall through */
11878                 default:
11879                         tokpushback = 1;
11880                         goto out;
11881                 }
11882         }
11883  out:
11884         *app = NULL;
11885         *vpp = NULL;
11886         *rpp = NULL;
11887         n = stzalloc(sizeof(struct ncmd));
11888         if (NCMD != 0)
11889                 n->type = NCMD;
11890         n->ncmd.linno = savelinno;
11891         n->ncmd.args = args;
11892         n->ncmd.assign = vars;
11893         n->ncmd.redirect = redir;
11894         return n;
11895 }
11896
11897 static union node *
11898 parse_command(void)
11899 {
11900         union node *n1, *n2;
11901         union node *ap, **app;
11902         union node *cp, **cpp;
11903         union node *redir, **rpp;
11904         union node **rpp2;
11905         int t;
11906         int savelinno;
11907
11908         redir = NULL;
11909         rpp2 = &redir;
11910
11911         savelinno = g_parsefile->linno;
11912
11913         switch (readtoken()) {
11914         default:
11915                 raise_error_unexpected_syntax(-1);
11916                 /* NOTREACHED */
11917         case TIF:
11918                 n1 = stzalloc(sizeof(struct nif));
11919                 n1->type = NIF;
11920                 n1->nif.test = list(0);
11921                 if (readtoken() != TTHEN)
11922                         raise_error_unexpected_syntax(TTHEN);
11923                 n1->nif.ifpart = list(0);
11924                 n2 = n1;
11925                 while (readtoken() == TELIF) {
11926                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11927                         n2 = n2->nif.elsepart;
11928                         n2->type = NIF;
11929                         n2->nif.test = list(0);
11930                         if (readtoken() != TTHEN)
11931                                 raise_error_unexpected_syntax(TTHEN);
11932                         n2->nif.ifpart = list(0);
11933                 }
11934                 if (lasttoken == TELSE)
11935                         n2->nif.elsepart = list(0);
11936                 else {
11937                         n2->nif.elsepart = NULL;
11938                         tokpushback = 1;
11939                 }
11940                 t = TFI;
11941                 break;
11942         case TWHILE:
11943         case TUNTIL: {
11944                 int got;
11945                 n1 = stzalloc(sizeof(struct nbinary));
11946                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11947                 n1->nbinary.ch1 = list(0);
11948                 got = readtoken();
11949                 if (got != TDO) {
11950                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11951                                         got == TWORD ? wordtext : ""));
11952                         raise_error_unexpected_syntax(TDO);
11953                 }
11954                 n1->nbinary.ch2 = list(0);
11955                 t = TDONE;
11956                 break;
11957         }
11958         case TFOR:
11959                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11960                         raise_error_syntax("bad for loop variable");
11961                 n1 = stzalloc(sizeof(struct nfor));
11962                 n1->type = NFOR;
11963                 n1->nfor.linno = savelinno;
11964                 n1->nfor.var = wordtext;
11965                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11966                 if (readtoken() == TIN) {
11967                         app = &ap;
11968                         while (readtoken() == TWORD) {
11969                                 n2 = stzalloc(sizeof(struct narg));
11970                                 n2->type = NARG;
11971                                 /*n2->narg.next = NULL; - stzalloc did it */
11972                                 n2->narg.text = wordtext;
11973                                 n2->narg.backquote = backquotelist;
11974                                 *app = n2;
11975                                 app = &n2->narg.next;
11976                         }
11977                         *app = NULL;
11978                         n1->nfor.args = ap;
11979                         if (lasttoken != TNL && lasttoken != TSEMI)
11980                                 raise_error_unexpected_syntax(-1);
11981                 } else {
11982                         n2 = stzalloc(sizeof(struct narg));
11983                         n2->type = NARG;
11984                         /*n2->narg.next = NULL; - stzalloc did it */
11985                         n2->narg.text = (char *)dolatstr;
11986                         /*n2->narg.backquote = NULL;*/
11987                         n1->nfor.args = n2;
11988                         /*
11989                          * Newline or semicolon here is optional (but note
11990                          * that the original Bourne shell only allowed NL).
11991                          */
11992                         if (lasttoken != TSEMI)
11993                                 tokpushback = 1;
11994                 }
11995                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11996                 if (readtoken() != TDO)
11997                         raise_error_unexpected_syntax(TDO);
11998                 n1->nfor.body = list(0);
11999                 t = TDONE;
12000                 break;
12001         case TCASE:
12002                 n1 = stzalloc(sizeof(struct ncase));
12003                 n1->type = NCASE;
12004                 n1->ncase.linno = savelinno;
12005                 if (readtoken() != TWORD)
12006                         raise_error_unexpected_syntax(TWORD);
12007                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
12008                 n2->type = NARG;
12009                 /*n2->narg.next = NULL; - stzalloc did it */
12010                 n2->narg.text = wordtext;
12011                 n2->narg.backquote = backquotelist;
12012                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
12013                 if (readtoken() != TIN)
12014                         raise_error_unexpected_syntax(TIN);
12015                 cpp = &n1->ncase.cases;
12016  next_case:
12017                 checkkwd = CHKNL | CHKKWD;
12018                 t = readtoken();
12019                 while (t != TESAC) {
12020                         if (lasttoken == TLP)
12021                                 readtoken();
12022                         *cpp = cp = stzalloc(sizeof(struct nclist));
12023                         cp->type = NCLIST;
12024                         app = &cp->nclist.pattern;
12025                         for (;;) {
12026                                 *app = ap = stzalloc(sizeof(struct narg));
12027                                 ap->type = NARG;
12028                                 /*ap->narg.next = NULL; - stzalloc did it */
12029                                 ap->narg.text = wordtext;
12030                                 ap->narg.backquote = backquotelist;
12031                                 if (readtoken() != TPIPE)
12032                                         break;
12033                                 app = &ap->narg.next;
12034                                 readtoken();
12035                         }
12036                         //ap->narg.next = NULL;
12037                         if (lasttoken != TRP)
12038                                 raise_error_unexpected_syntax(TRP);
12039                         cp->nclist.body = list(2);
12040
12041                         cpp = &cp->nclist.next;
12042
12043                         checkkwd = CHKNL | CHKKWD;
12044                         t = readtoken();
12045                         if (t != TESAC) {
12046                                 if (t != TENDCASE)
12047                                         raise_error_unexpected_syntax(TENDCASE);
12048                                 goto next_case;
12049                         }
12050                 }
12051                 *cpp = NULL;
12052                 goto redir;
12053         case TLP:
12054                 n1 = stzalloc(sizeof(struct nredir));
12055                 n1->type = NSUBSHELL;
12056                 n1->nredir.linno = savelinno;
12057                 n1->nredir.n = list(0);
12058                 /*n1->nredir.redirect = NULL; - stzalloc did it */
12059                 t = TRP;
12060                 break;
12061         case TBEGIN:
12062                 n1 = list(0);
12063                 t = TEND;
12064                 break;
12065         IF_BASH_FUNCTION(case TFUNCTION:)
12066         case TWORD:
12067         case TREDIR:
12068                 tokpushback = 1;
12069                 return simplecmd();
12070         }
12071
12072         if (readtoken() != t)
12073                 raise_error_unexpected_syntax(t);
12074
12075  redir:
12076         /* Now check for redirection which may follow command */
12077         checkkwd = CHKKWD | CHKALIAS;
12078         rpp = rpp2;
12079         while (readtoken() == TREDIR) {
12080                 *rpp = n2 = redirnode;
12081                 rpp = &n2->nfile.next;
12082                 parsefname();
12083         }
12084         tokpushback = 1;
12085         *rpp = NULL;
12086         if (redir) {
12087                 if (n1->type != NSUBSHELL) {
12088                         n2 = stzalloc(sizeof(struct nredir));
12089                         n2->type = NREDIR;
12090                         n2->nredir.linno = savelinno;
12091                         n2->nredir.n = n1;
12092                         n1 = n2;
12093                 }
12094                 n1->nredir.redirect = redir;
12095         }
12096         return n1;
12097 }
12098
12099 #if BASH_DOLLAR_SQUOTE
12100 static int
12101 decode_dollar_squote(void)
12102 {
12103         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12104         int c, cnt;
12105         char *p;
12106         char buf[4];
12107
12108         c = pgetc();
12109         p = strchr(C_escapes, c);
12110         if (p) {
12111                 buf[0] = c;
12112                 p = buf;
12113                 cnt = 3;
12114                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12115                         do {
12116                                 c = pgetc();
12117                                 *++p = c;
12118                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
12119                         pungetc();
12120                 } else if (c == 'x') { /* \xHH */
12121                         do {
12122                                 c = pgetc();
12123                                 *++p = c;
12124                         } while (isxdigit(c) && --cnt);
12125                         pungetc();
12126                         if (cnt == 3) { /* \x but next char is "bad" */
12127                                 c = 'x';
12128                                 goto unrecognized;
12129                         }
12130                 } else { /* simple seq like \\ or \t */
12131                         p++;
12132                 }
12133                 *p = '\0';
12134                 p = buf;
12135                 c = bb_process_escape_sequence((void*)&p);
12136         } else { /* unrecognized "\z": print both chars unless ' or " */
12137                 if (c != '\'' && c != '"') {
12138  unrecognized:
12139                         c |= 0x100; /* "please encode \, then me" */
12140                 }
12141         }
12142         return c;
12143 }
12144 #endif
12145
12146 /* Used by expandstr to get here-doc like behaviour. */
12147 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12148
12149 static ALWAYS_INLINE int
12150 realeofmark(const char *eofmark)
12151 {
12152         return eofmark && eofmark != FAKEEOFMARK;
12153 }
12154
12155 /*
12156  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12157  * is not NULL, read a here document.  In the latter case, eofmark is the
12158  * word which marks the end of the document and striptabs is true if
12159  * leading tabs should be stripped from the document.  The argument c
12160  * is the first character of the input token or document.
12161  *
12162  * Because C does not have internal subroutines, I have simulated them
12163  * using goto's to implement the subroutine linkage.  The following macros
12164  * will run code that appears at the end of readtoken1.
12165  */
12166 #define CHECKEND()      {goto checkend; checkend_return:;}
12167 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12168 #define PARSESUB()      {goto parsesub; parsesub_return:;}
12169 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
12170 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
12171 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
12172 static int
12173 readtoken1(int c, int syntax, char *eofmark, int striptabs)
12174 {
12175         /* NB: syntax parameter fits into smallint */
12176         /* c parameter is an unsigned char or PEOF or PEOA */
12177         char *out;
12178         size_t len;
12179         struct nodelist *bqlist;
12180         smallint quotef;
12181         smallint oldstyle;
12182         smallint pssyntax;   /* we are expanding a prompt string */
12183         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12184         /* syntax stack */
12185         struct synstack synbase = { };
12186         struct synstack *synstack = &synbase;
12187
12188 #if ENABLE_ASH_EXPAND_PRMT
12189         pssyntax = (syntax == PSSYNTAX);
12190         if (pssyntax)
12191                 syntax = DQSYNTAX;
12192 #else
12193         pssyntax = 0; /* constant */
12194 #endif
12195         synstack->syntax = syntax;
12196
12197         if (syntax == DQSYNTAX)
12198                 synstack->dblquote = 1;
12199         quotef = 0;
12200         bqlist = NULL;
12201
12202         STARTSTACKSTR(out);
12203  loop:
12204         /* For each line, until end of word */
12205         CHECKEND();     /* set c to PEOF if at end of here document */
12206         for (;;) {      /* until end of line or end of word */
12207                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12208                 switch (SIT(c, synstack->syntax)) {
12209                 case CNL:       /* '\n' */
12210                         if (synstack->syntax == BASESYNTAX
12211                          && !synstack->varnest
12212                         ) {
12213                                 goto endword;   /* exit outer loop */
12214                         }
12215                         USTPUTC(c, out);
12216                         nlprompt();
12217                         c = pgetc_top(synstack);
12218                         goto loop;              /* continue outer loop */
12219                 case CWORD:
12220                         USTPUTC(c, out);
12221                         break;
12222                 case CCTL:
12223 #if BASH_DOLLAR_SQUOTE
12224                         if (c == '\\' && bash_dollar_squote) {
12225                                 c = decode_dollar_squote();
12226                                 if (c == '\0') {
12227                                         /* skip $'\000', $'\x00' (like bash) */
12228                                         break;
12229                                 }
12230                                 if (c & 0x100) {
12231                                         /* Unknown escape. Encode as '\z' */
12232                                         c = (unsigned char)c;
12233                                         if (eofmark == NULL || synstack->dblquote)
12234                                                 USTPUTC(CTLESC, out);
12235                                         USTPUTC('\\', out);
12236                                 }
12237                         }
12238 #endif
12239                         if (!eofmark || synstack->dblquote || synstack->varnest)
12240                                 USTPUTC(CTLESC, out);
12241                         USTPUTC(c, out);
12242                         break;
12243                 case CBACK:     /* backslash */
12244                         c = pgetc_without_PEOA();
12245                         if (c == PEOF) {
12246                                 USTPUTC(CTLESC, out);
12247                                 USTPUTC('\\', out);
12248                                 pungetc();
12249                         } else {
12250                                 if (pssyntax && c == '$') {
12251                                         USTPUTC(CTLESC, out);
12252                                         USTPUTC('\\', out);
12253                                 }
12254                                 /* Backslash is retained if we are in "str"
12255                                  * and next char isn't dquote-special.
12256                                  */
12257                                 if (synstack->dblquote
12258                                  && c != '\\'
12259                                  && c != '`'
12260                                  && c != '$'
12261                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12262                                  && (c != '}' || !synstack->varnest)
12263                                 ) {
12264                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12265                                         USTPUTC('\\', out);
12266                                 }
12267                                 USTPUTC(CTLESC, out);
12268                                 USTPUTC(c, out);
12269                                 quotef = 1;
12270                         }
12271                         break;
12272                 case CSQUOTE:
12273                         synstack->syntax = SQSYNTAX;
12274  quotemark:
12275                         if (eofmark == NULL) {
12276                                 USTPUTC(CTLQUOTEMARK, out);
12277                         }
12278                         break;
12279                 case CDQUOTE:
12280                         synstack->syntax = DQSYNTAX;
12281                         synstack->dblquote = 1;
12282  toggledq:
12283                         if (synstack->varnest)
12284                                 synstack->innerdq ^= 1;
12285                         goto quotemark;
12286                 case CENDQUOTE:
12287                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12288                         if (eofmark != NULL && synstack->varnest == 0) {
12289                                 USTPUTC(c, out);
12290                                 break;
12291                         }
12292
12293                         if (synstack->dqvarnest == 0) {
12294                                 synstack->syntax = BASESYNTAX;
12295                                 synstack->dblquote = 0;
12296                         }
12297
12298                         quotef = 1;
12299
12300                         if (c == '"')
12301                                 goto toggledq;
12302
12303                         goto quotemark;
12304                 case CVAR:      /* '$' */
12305                         PARSESUB();             /* parse substitution */
12306                         break;
12307                 case CENDVAR:   /* '}' */
12308                         if (!synstack->innerdq && synstack->varnest > 0) {
12309                                 if (!--synstack->varnest && synstack->varpushed)
12310                                         synstack_pop(&synstack);
12311                                 else if (synstack->dqvarnest > 0)
12312                                         synstack->dqvarnest--;
12313                                 c = CTLENDVAR;
12314                         }
12315                         USTPUTC(c, out);
12316                         break;
12317 #if ENABLE_FEATURE_SH_MATH
12318                 case CLP:       /* '(' in arithmetic */
12319                         synstack->parenlevel++;
12320                         USTPUTC(c, out);
12321                         break;
12322                 case CRP:       /* ')' in arithmetic */
12323                         if (synstack->parenlevel > 0) {
12324                                 synstack->parenlevel--;
12325                         } else {
12326                                 if (pgetc_eatbnl() == ')') {
12327                                         c = CTLENDARI;
12328                                         synstack_pop(&synstack);
12329                                 } else {
12330                                         /*
12331                                          * unbalanced parens
12332                                          * (don't 2nd guess - no error)
12333                                          */
12334                                         pungetc();
12335                                 }
12336                         }
12337                         USTPUTC(c, out);
12338                         break;
12339 #endif
12340                 case CBQUOTE:   /* '`' */
12341                         if (checkkwd & CHKEOFMARK) {
12342                                 quotef = 1;
12343                                 USTPUTC('`', out);
12344                                 break;
12345                         }
12346
12347                         PARSEBACKQOLD();
12348                         break;
12349                 case CENDFILE:
12350                         goto endword;           /* exit outer loop */
12351                 case CIGN:
12352                         break;
12353                 default:
12354                         if (synstack->varnest == 0) {
12355 #if BASH_REDIR_OUTPUT
12356                                 if (c == '&') {
12357 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12358                                         if (pgetc() == '>')
12359                                                 c = 0x100 + '>'; /* flag &> */
12360                                         pungetc();
12361                                 }
12362 #endif
12363                                 goto endword;   /* exit outer loop */
12364                         }
12365                         IF_ASH_ALIAS(if (c != PEOA))
12366                                 USTPUTC(c, out);
12367                 }
12368                 c = pgetc_top(synstack);
12369         } /* for (;;) */
12370  endword:
12371
12372 #if ENABLE_FEATURE_SH_MATH
12373         if (synstack->syntax == ARISYNTAX)
12374                 raise_error_syntax("missing '))'");
12375 #endif
12376         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12377                 raise_error_syntax("unterminated quoted string");
12378         if (synstack->varnest != 0) {
12379                 /* { */
12380                 raise_error_syntax("missing '}'");
12381         }
12382         USTPUTC('\0', out);
12383         len = out - (char *)stackblock();
12384         out = stackblock();
12385         if (eofmark == NULL) {
12386                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12387                  && quotef == 0
12388                 ) {
12389                         if (isdigit_str9(out)) {
12390                                 PARSEREDIR(); /* passed as params: out, c */
12391                                 lasttoken = TREDIR;
12392                                 return lasttoken;
12393                         }
12394                         /* else: non-number X seen, interpret it
12395                          * as "NNNX>file" = "NNNX >file" */
12396                 }
12397                 pungetc();
12398         }
12399         quoteflag = quotef;
12400         backquotelist = bqlist;
12401         grabstackblock(len);
12402         wordtext = out;
12403         lasttoken = TWORD;
12404         return lasttoken;
12405 /* end of readtoken routine */
12406
12407 /*
12408  * Check to see whether we are at the end of the here document.  When this
12409  * is called, c is set to the first character of the next input line.  If
12410  * we are at the end of the here document, this routine sets the c to PEOF.
12411  */
12412 checkend: {
12413         if (realeofmark(eofmark)) {
12414                 int markloc;
12415                 char *p;
12416
12417 #if ENABLE_ASH_ALIAS
12418                 if (c == PEOA)
12419                         c = pgetc_without_PEOA();
12420 #endif
12421                 if (striptabs) {
12422                         while (c == '\t') {
12423                                 c = pgetc_without_PEOA();
12424                         }
12425                 }
12426
12427                 markloc = out - (char *)stackblock();
12428                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12429                         if (c != *p)
12430                                 goto more_heredoc;
12431                         /* FIXME: fails for backslash-newlined terminator:
12432                          * cat <<EOF
12433                          * ...
12434                          * EO\
12435                          * F
12436                          * (see heredoc_bkslash_newline2.tests)
12437                          */
12438                         c = pgetc_without_PEOA();
12439                 }
12440
12441                 if (c == '\n' || c == PEOF) {
12442                         c = PEOF;
12443                         g_parsefile->linno++;
12444                         needprompt = doprompt;
12445                 } else {
12446                         int len_here;
12447
12448  more_heredoc:
12449                         p = (char *)stackblock() + markloc + 1;
12450                         len_here = out - p;
12451
12452                         if (len_here) {
12453                                 len_here -= (c >= PEOF);
12454                                 c = p[-1];
12455
12456                                 if (len_here) {
12457                                         char *str;
12458
12459                                         str = alloca(len_here + 1);
12460                                         *(char *)mempcpy(str, p, len_here) = '\0';
12461
12462                                         pushstring(str, NULL);
12463                                 }
12464                         }
12465                 }
12466
12467                 STADJUST((char *)stackblock() + markloc - out, out);
12468         }
12469         goto checkend_return;
12470 }
12471
12472 /*
12473  * Parse a redirection operator.  The variable "out" points to a string
12474  * specifying the fd to be redirected.  The variable "c" contains the
12475  * first character of the redirection operator.
12476  */
12477 parseredir: {
12478         /* out is already checked to be a valid number or "" */
12479         int fd = (*out == '\0' ? -1 : atoi(out));
12480         union node *np;
12481
12482         np = stzalloc(sizeof(struct nfile));
12483         if (c == '>') {
12484                 np->nfile.fd = 1;
12485                 c = pgetc_eatbnl();
12486                 if (c == '>')
12487                         np->type = NAPPEND;
12488                 else if (c == '|')
12489                         np->type = NCLOBBER;
12490                 else if (c == '&')
12491                         np->type = NTOFD;
12492                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12493                 else {
12494                         np->type = NTO;
12495                         pungetc();
12496                 }
12497         }
12498 #if BASH_REDIR_OUTPUT
12499         else if (c == 0x100 + '>') { /* this flags &> redirection */
12500                 np->nfile.fd = 1;
12501                 pgetc(); /* this is '>', no need to check */
12502                 np->type = NTO2;
12503         }
12504 #endif
12505         else { /* c == '<' */
12506                 /*np->nfile.fd = 0; - stzalloc did it */
12507                 c = pgetc_eatbnl();
12508                 switch (c) {
12509                 case '<':
12510                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12511                                 np = stzalloc(sizeof(struct nhere));
12512                                 /*np->nfile.fd = 0; - stzalloc did it */
12513                         }
12514                         np->type = NHERE;
12515                         heredoc = stzalloc(sizeof(struct heredoc));
12516                         heredoc->here = np;
12517                         c = pgetc_eatbnl();
12518                         if (c == '-') {
12519                                 heredoc->striptabs = 1;
12520                         } else {
12521                                 /*heredoc->striptabs = 0; - stzalloc did it */
12522                                 pungetc();
12523                         }
12524                         break;
12525
12526                 case '&':
12527                         np->type = NFROMFD;
12528                         break;
12529
12530                 case '>':
12531                         np->type = NFROMTO;
12532                         break;
12533
12534                 default:
12535                         np->type = NFROM;
12536                         pungetc();
12537                         break;
12538                 }
12539         }
12540         if (fd >= 0)
12541                 np->nfile.fd = fd;
12542         redirnode = np;
12543         goto parseredir_return;
12544 }
12545
12546 /*
12547  * Parse a substitution.  At this point, we have read the dollar sign
12548  * and nothing else.
12549  */
12550
12551 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12552  * (assuming ascii char codes, as the original implementation did) */
12553 #define is_special(c) \
12554         (((unsigned)(c) - 33 < 32) \
12555                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12556 parsesub: {
12557         unsigned char subtype;
12558         int typeloc;
12559
12560         c = pgetc_eatbnl();
12561         if ((checkkwd & CHKEOFMARK)
12562          || c > 255 /* PEOA or PEOF */
12563          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12564         ) {
12565 #if BASH_DOLLAR_SQUOTE
12566                 if (synstack->syntax != DQSYNTAX && c == '\'')
12567                         bash_dollar_squote = 1;
12568                 else
12569 #endif
12570                         USTPUTC('$', out);
12571                 pungetc();
12572         } else if (c == '(') {
12573                 /* $(command) or $((arith)) */
12574                 if (pgetc_eatbnl() == '(') {
12575 #if ENABLE_FEATURE_SH_MATH
12576                         PARSEARITH();
12577 #else
12578                         raise_error_syntax("support for $((arith)) is disabled");
12579 #endif
12580                 } else {
12581                         pungetc();
12582                         PARSEBACKQNEW();
12583                 }
12584         } else {
12585                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12586                 smalluint newsyn = synstack->syntax;
12587
12588                 USTPUTC(CTLVAR, out);
12589                 typeloc = out - (char *)stackblock();
12590                 STADJUST(1, out);
12591                 subtype = VSNORMAL;
12592                 if (c == '{') {
12593                         c = pgetc_eatbnl();
12594                         subtype = 0;
12595                 }
12596  varname:
12597                 if (is_name(c)) {
12598                         /* $[{[#]]NAME[}] */
12599                         do {
12600                                 STPUTC(c, out);
12601                                 c = pgetc_eatbnl();
12602                         } while (is_in_name(c));
12603                 } else if (isdigit(c)) {
12604                         /* $[{[#]]NUM[}] */
12605                         do {
12606                                 STPUTC(c, out);
12607                                 c = pgetc_eatbnl();
12608                         } while (!subtype && isdigit(c));
12609                 } else if (c != '}') {
12610                         /* $[{[#]]<specialchar>[}] */
12611                         int cc = c;
12612
12613                         c = pgetc_eatbnl();
12614                         if (!subtype && cc == '#') {
12615                                 subtype = VSLENGTH;
12616                                 if (c == '_' || isalnum(c))
12617                                         goto varname;
12618                                 cc = c;
12619                                 c = pgetc_eatbnl();
12620                                 if (cc == '}' || c != '}') {
12621                                         pungetc();
12622                                         subtype = 0;
12623                                         c = cc;
12624                                         cc = '#';
12625                                 }
12626                         }
12627
12628                         if (!is_special(cc)) {
12629                                 if (subtype == VSLENGTH)
12630                                         subtype = 0;
12631                                 goto badsub;
12632                         }
12633
12634                         USTPUTC(cc, out);
12635                 } else
12636                         goto badsub;
12637
12638                 if (c != '}' && subtype == VSLENGTH) {
12639                         /* ${#VAR didn't end with } */
12640                         goto badsub;
12641                 }
12642
12643                 if (subtype == 0) {
12644                         static const char types[] ALIGN1 = "}-+?=";
12645                         /* ${VAR...} but not $VAR or ${#VAR} */
12646                         /* c == first char after VAR */
12647                         int cc = c;
12648
12649                         switch (c) {
12650                         case ':':
12651                                 c = pgetc_eatbnl();
12652 #if BASH_SUBSTR
12653                                 /* This check is only needed to not misinterpret
12654                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12655                                  * constructs.
12656                                  */
12657                                 if (!strchr(types, c)) {
12658                                         subtype = VSSUBSTR;
12659                                         pungetc();
12660                                         break; /* "goto badsub" is bigger (!) */
12661                                 }
12662 #endif
12663                                 subtype = VSNUL;
12664                                 /*FALLTHROUGH*/
12665                         default: {
12666                                 const char *p = strchr(types, c);
12667                                 if (p == NULL)
12668                                         break;
12669                                 subtype |= p - types + VSNORMAL;
12670                                 break;
12671                         }
12672                         case '%':
12673                         case '#':
12674                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12675                                 c = pgetc_eatbnl();
12676                                 if (c == cc)
12677                                         subtype++;
12678                                 else
12679                                         pungetc();
12680
12681                                 newsyn = BASESYNTAX;
12682                                 break;
12683 #if BASH_PATTERN_SUBST
12684                         case '/':
12685                                 /* ${v/[/]pattern/repl} */
12686 //TODO: encode pattern and repl separately.
12687 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12688 // are broken (should print "ONE")
12689                                 subtype = VSREPLACE;
12690                                 newsyn = BASESYNTAX;
12691                                 c = pgetc_eatbnl();
12692                                 if (c != '/')
12693                                         goto badsub;
12694                                 subtype++; /* VSREPLACEALL */
12695                                 break;
12696 #endif
12697                         }
12698                 } else {
12699  badsub:
12700                         pungetc();
12701                 }
12702
12703                 if (newsyn == ARISYNTAX)
12704                         newsyn = DQSYNTAX;
12705
12706                 if ((newsyn != synstack->syntax || synstack->innerdq)
12707                  && subtype != VSNORMAL
12708                 ) {
12709                         synstack_push(&synstack,
12710                                 synstack->prev ?: alloca(sizeof(*synstack)),
12711                                 newsyn);
12712
12713                         synstack->varpushed = 1;
12714                         synstack->dblquote = newsyn != BASESYNTAX;
12715                 }
12716
12717                 ((unsigned char *)stackblock())[typeloc] = subtype;
12718                 if (subtype != VSNORMAL) {
12719                         synstack->varnest++;
12720                         if (synstack->dblquote)
12721                                 synstack->dqvarnest++;
12722                 }
12723                 STPUTC('=', out);
12724         }
12725         goto parsesub_return;
12726 }
12727
12728 /*
12729  * Called to parse command substitutions.  Newstyle is set if the command
12730  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12731  * list of commands (passed by reference), and savelen is the number of
12732  * characters on the top of the stack which must be preserved.
12733  */
12734 parsebackq: {
12735         struct nodelist **nlpp;
12736         union node *n;
12737         char *str;
12738         size_t savelen;
12739         struct heredoc *saveheredoclist;
12740         smallint saveprompt = 0;
12741
12742         str = NULL;
12743         savelen = out - (char *)stackblock();
12744         if (savelen > 0) {
12745                 /*
12746                  * FIXME: this can allocate very large block on stack and SEGV.
12747                  * Example:
12748                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12749                  * allocates 100kb for every command subst. With about
12750                  * a hundred command substitutions stack overflows.
12751                  * With larger prepended string, SEGV happens sooner.
12752                  */
12753                 str = alloca(savelen);
12754                 memcpy(str, stackblock(), savelen);
12755         }
12756
12757         if (oldstyle) {
12758                 /* We must read until the closing backquote, giving special
12759                  * treatment to some slashes, and then push the string and
12760                  * reread it as input, interpreting it normally.
12761                  */
12762                 char *pout;
12763                 size_t psavelen;
12764                 char *pstr;
12765
12766                 STARTSTACKSTR(pout);
12767                 for (;;) {
12768                         int pc;
12769
12770                         setprompt_if(needprompt, 2);
12771                         pc = pgetc_eatbnl();
12772                         switch (pc) {
12773                         case '`':
12774                                 goto done;
12775
12776                         case '\\':
12777                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12778                                 if (pc != '\\' && pc != '`' && pc != '$'
12779                                  && (!synstack->dblquote || pc != '"')
12780                                 ) {
12781                                         STPUTC('\\', pout);
12782                                 }
12783                                 if (pc <= 255 /* not PEOA or PEOF */) {
12784                                         break;
12785                                 }
12786                                 /* fall through */
12787
12788                         case PEOF:
12789                         IF_ASH_ALIAS(case PEOA:)
12790                                 raise_error_syntax("EOF in backquote substitution");
12791
12792                         case '\n':
12793                                 nlnoprompt();
12794                                 break;
12795
12796                         default:
12797                                 break;
12798                         }
12799                         STPUTC(pc, pout);
12800                 }
12801  done:
12802                 STPUTC('\0', pout);
12803                 psavelen = pout - (char *)stackblock();
12804                 if (psavelen > 0) {
12805                         pstr = grabstackstr(pout);
12806                         setinputstring(pstr);
12807                 }
12808         }
12809         nlpp = &bqlist;
12810         while (*nlpp)
12811                 nlpp = &(*nlpp)->next;
12812         *nlpp = stzalloc(sizeof(**nlpp));
12813         /* (*nlpp)->next = NULL; - stzalloc did it */
12814
12815         saveheredoclist = heredoclist;
12816         heredoclist = NULL;
12817
12818         if (oldstyle) {
12819                 saveprompt = doprompt;
12820                 doprompt = 0;
12821         }
12822
12823         n = list(2);
12824
12825         if (oldstyle)
12826                 doprompt = saveprompt;
12827         else {
12828                 if (readtoken() != TRP)
12829                         raise_error_unexpected_syntax(TRP);
12830                 setinputstring(nullstr);
12831                 parseheredoc();
12832         }
12833
12834         heredoclist = saveheredoclist;
12835
12836         (*nlpp)->n = n;
12837         /* Start reading from old file again. */
12838         popfile();
12839         /* Ignore any pushed back tokens left from the backquote parsing. */
12840         if (oldstyle)
12841                 tokpushback = 0;
12842         out = growstackto(savelen + 1);
12843         if (str) {
12844                 memcpy(out, str, savelen);
12845                 STADJUST(savelen, out);
12846         }
12847         USTPUTC(CTLBACKQ, out);
12848         if (oldstyle)
12849                 goto parsebackq_oldreturn;
12850         goto parsebackq_newreturn;
12851 }
12852
12853 #if ENABLE_FEATURE_SH_MATH
12854 /*
12855  * Parse an arithmetic expansion (indicate start of one and set state)
12856  */
12857 parsearith: {
12858
12859         synstack_push(&synstack,
12860                         synstack->prev ?: alloca(sizeof(*synstack)),
12861                         ARISYNTAX);
12862         synstack->dblquote = 1;
12863         USTPUTC(CTLARI, out);
12864         goto parsearith_return;
12865 }
12866 #endif
12867 } /* end of readtoken */
12868
12869 /*
12870  * Read the next input token.
12871  * If the token is a word, we set backquotelist to the list of cmds in
12872  *      backquotes.  We set quoteflag to true if any part of the word was
12873  *      quoted.
12874  * If the token is TREDIR, then we set redirnode to a structure containing
12875  *      the redirection.
12876  *
12877  * [Change comment:  here documents and internal procedures]
12878  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12879  *  word parsing code into a separate routine.  In this case, readtoken
12880  *  doesn't need to have any internal procedures, but parseword does.
12881  *  We could also make parseoperator in essence the main routine, and
12882  *  have parseword (readtoken1?) handle both words and redirection.]
12883  */
12884 #define NEW_xxreadtoken
12885 #ifdef NEW_xxreadtoken
12886 /* singles must be first! */
12887 static const char xxreadtoken_chars[7] ALIGN1 = {
12888         '\n', '(', ')', /* singles */
12889         '&', '|', ';',  /* doubles */
12890         0
12891 };
12892
12893 #define xxreadtoken_singles 3
12894 #define xxreadtoken_doubles 3
12895
12896 static const char xxreadtoken_tokens[] ALIGN1 = {
12897         TNL, TLP, TRP,          /* only single occurrence allowed */
12898         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12899         TEOF,                   /* corresponds to trailing nul */
12900         TAND, TOR, TENDCASE     /* if double occurrence */
12901 };
12902
12903 static int
12904 xxreadtoken(void)
12905 {
12906         int c;
12907
12908         if (tokpushback) {
12909                 tokpushback = 0;
12910                 return lasttoken;
12911         }
12912         setprompt_if(needprompt, 2);
12913         for (;;) {                      /* until token or start of word found */
12914                 c = pgetc_eatbnl();
12915                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12916                         continue;
12917
12918                 if (c == '#') {
12919                         while ((c = pgetc()) != '\n' && c != PEOF)
12920                                 continue;
12921                         pungetc();
12922                 } else if (c == '\\') {
12923                         break; /* return readtoken1(...) */
12924                 } else {
12925                         const char *p;
12926
12927                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12928                         if (c != PEOF) {
12929                                 if (c == '\n') {
12930                                         nlnoprompt();
12931                                 }
12932
12933                                 p = strchr(xxreadtoken_chars, c);
12934                                 if (p == NULL)
12935                                         break; /* return readtoken1(...) */
12936
12937                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12938                                         int cc = pgetc_eatbnl();
12939                                         if (cc == c) {    /* double occurrence? */
12940                                                 p += xxreadtoken_doubles + 1;
12941                                         } else {
12942                                                 pungetc();
12943 #if BASH_REDIR_OUTPUT
12944                                                 if (c == '&' && cc == '>') /* &> */
12945                                                         break; /* return readtoken1(...) */
12946 #endif
12947                                         }
12948                                 }
12949                         }
12950                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12951                         return lasttoken;
12952                 }
12953         } /* for (;;) */
12954
12955         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12956 }
12957 #else /* old xxreadtoken */
12958 #define RETURN(token)   return lasttoken = token
12959 static int
12960 xxreadtoken(void)
12961 {
12962         int c;
12963
12964         if (tokpushback) {
12965                 tokpushback = 0;
12966                 return lasttoken;
12967         }
12968         setprompt_if(needprompt, 2);
12969         for (;;) {      /* until token or start of word found */
12970                 c = pgetc_eatbnl();
12971                 switch (c) {
12972                 case ' ': case '\t':
12973                 IF_ASH_ALIAS(case PEOA:)
12974                         continue;
12975                 case '#':
12976                         while ((c = pgetc()) != '\n' && c != PEOF)
12977                                 continue;
12978                         pungetc();
12979                         continue;
12980                 case '\n':
12981                         nlnoprompt();
12982                         RETURN(TNL);
12983                 case PEOF:
12984                         RETURN(TEOF);
12985                 case '&':
12986                         if (pgetc_eatbnl() == '&')
12987                                 RETURN(TAND);
12988                         pungetc();
12989                         RETURN(TBACKGND);
12990                 case '|':
12991                         if (pgetc_eatbnl() == '|')
12992                                 RETURN(TOR);
12993                         pungetc();
12994                         RETURN(TPIPE);
12995                 case ';':
12996                         if (pgetc_eatbnl() == ';')
12997                                 RETURN(TENDCASE);
12998                         pungetc();
12999                         RETURN(TSEMI);
13000                 case '(':
13001                         RETURN(TLP);
13002                 case ')':
13003                         RETURN(TRP);
13004                 }
13005                 break;
13006         }
13007         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
13008 #undef RETURN
13009 }
13010 #endif /* old xxreadtoken */
13011
13012 static int
13013 readtoken(void)
13014 {
13015         int t;
13016         int kwd = checkkwd;
13017 #if DEBUG
13018         smallint alreadyseen = tokpushback;
13019 #endif
13020
13021 #if ENABLE_ASH_ALIAS
13022  top:
13023 #endif
13024
13025         t = xxreadtoken();
13026
13027         /*
13028          * eat newlines
13029          */
13030         if (kwd & CHKNL) {
13031                 while (t == TNL) {
13032                         parseheredoc();
13033                         t = xxreadtoken();
13034                 }
13035         }
13036
13037         if (t != TWORD || quoteflag) {
13038                 goto out;
13039         }
13040
13041         /*
13042          * check for keywords
13043          */
13044         if (kwd & CHKKWD) {
13045                 const char *const *pp;
13046
13047                 pp = findkwd(wordtext);
13048                 if (pp) {
13049                         lasttoken = t = pp - tokname_array;
13050                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13051                         goto out;
13052                 }
13053         }
13054
13055         if (checkkwd & CHKALIAS) {
13056 #if ENABLE_ASH_ALIAS
13057                 struct alias *ap;
13058                 ap = lookupalias(wordtext, 1);
13059                 if (ap != NULL) {
13060                         if (*ap->val) {
13061                                 pushstring(ap->val, ap);
13062                         }
13063                         goto top;
13064                 }
13065 #endif
13066         }
13067  out:
13068         checkkwd = 0;
13069 #if DEBUG
13070         if (!alreadyseen)
13071                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13072         else
13073                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13074 #endif
13075         return t;
13076 }
13077
13078 static int
13079 peektoken(void)
13080 {
13081         int t;
13082
13083         t = readtoken();
13084         tokpushback = 1;
13085         return t;
13086 }
13087
13088 /*
13089  * Read and parse a command.  Returns NODE_EOF on end of file.
13090  * (NULL is a valid parse tree indicating a blank line.)
13091  */
13092 static union node *
13093 parsecmd(int interact)
13094 {
13095         tokpushback = 0;
13096         checkkwd = 0;
13097         heredoclist = 0;
13098         doprompt = interact;
13099         setprompt_if(doprompt, doprompt);
13100         needprompt = 0;
13101         return list(1);
13102 }
13103
13104 /*
13105  * Input any here documents.
13106  */
13107 static void
13108 parseheredoc(void)
13109 {
13110         struct heredoc *here;
13111         union node *n;
13112
13113         here = heredoclist;
13114         heredoclist = NULL;
13115
13116         while (here) {
13117                 tokpushback = 0;
13118                 setprompt_if(needprompt, 2);
13119                 if (here->here->type == NHERE)
13120                         readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13121                 else
13122                         readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13123                 n = stzalloc(sizeof(struct narg));
13124                 n->narg.type = NARG;
13125                 /*n->narg.next = NULL; - stzalloc did it */
13126                 n->narg.text = wordtext;
13127                 n->narg.backquote = backquotelist;
13128                 here->here->nhere.doc = n;
13129                 here = here->next;
13130         }
13131 }
13132
13133
13134 static const char *
13135 expandstr(const char *ps, int syntax_type)
13136 {
13137         union node n;
13138         int saveprompt;
13139         struct parsefile *file_stop = g_parsefile;
13140         volatile int saveint;
13141         struct jmploc *volatile savehandler = exception_handler;
13142         struct jmploc jmploc;
13143         const char *volatile result;
13144         int err;
13145
13146         /* XXX Fix (char *) cast. */
13147         setinputstring((char *)ps);
13148
13149         saveprompt = doprompt;
13150         doprompt = 0;
13151         result = ps;
13152
13153         SAVE_INT(saveint);
13154         err = setjmp(jmploc.loc);
13155         if (err)
13156                 goto out;
13157
13158         /* readtoken1() might die horribly.
13159          * Try a prompt with syntactically wrong command:
13160          * PS1='$(date "+%H:%M:%S) > '
13161          */
13162         exception_handler = &jmploc;
13163         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13164
13165         n.narg.type = NARG;
13166         n.narg.next = NULL;
13167         n.narg.text = wordtext;
13168         n.narg.backquote = backquotelist;
13169
13170         /* expandarg() might fail too:
13171          * PS1='$((123+))'
13172          */
13173         expandarg(&n, NULL, EXP_QUOTED);
13174         result = stackblock();
13175
13176 out:
13177         exception_handler = savehandler;
13178         if (err && exception_type != EXERROR)
13179                 longjmp(exception_handler->loc, 1);
13180         RESTORE_INT(saveint);
13181
13182         doprompt = saveprompt;
13183         /* Try: PS1='`xxx(`' */
13184         unwindfiles(file_stop);
13185
13186         return result;
13187 }
13188
13189 static inline int
13190 parser_eof(void)
13191 {
13192         return tokpushback && lasttoken == TEOF;
13193 }
13194
13195 /*
13196  * Execute a command or commands contained in a string.
13197  */
13198 static int
13199 evalstring(char *s, int flags)
13200 {
13201         struct jmploc *volatile savehandler;
13202         struct jmploc jmploc;
13203         int ex;
13204
13205         union node *n;
13206         struct stackmark smark;
13207         int status;
13208
13209         s = sstrdup(s);
13210         setinputstring(s);
13211         setstackmark(&smark);
13212
13213         status = 0;
13214         /* On exception inside execution loop, we must popfile().
13215          * Try interactively:
13216          *      readonly a=a
13217          *      command eval "a=b"  # throws "is read only" error
13218          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13219          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13220          */
13221         savehandler = exception_handler;
13222         ex = setjmp(jmploc.loc);
13223         if (ex)
13224                 goto out;
13225         exception_handler = &jmploc;
13226
13227         while ((n = parsecmd(0)) != NODE_EOF) {
13228                 int i;
13229
13230                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13231                 if (n)
13232                         status = i;
13233                 popstackmark(&smark);
13234                 if (evalskip)
13235                         break;
13236         }
13237  out:
13238         popstackmark(&smark);
13239         popfile();
13240         stunalloc(s);
13241
13242         exception_handler = savehandler;
13243         if (ex)
13244                 longjmp(exception_handler->loc, ex);
13245
13246         return status;
13247 }
13248
13249 /*
13250  * The eval command.
13251  */
13252 static int FAST_FUNC
13253 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13254 {
13255         char *p;
13256         char *concat;
13257
13258         if (argv[1]) {
13259                 p = argv[1];
13260                 argv += 2;
13261                 if (argv[0]) {
13262                         STARTSTACKSTR(concat);
13263                         for (;;) {
13264                                 concat = stack_putstr(p, concat);
13265                                 p = *argv++;
13266                                 if (p == NULL)
13267                                         break;
13268                                 STPUTC(' ', concat);
13269                         }
13270                         STPUTC('\0', concat);
13271                         p = grabstackstr(concat);
13272                 }
13273                 return evalstring(p, flags & EV_TESTED);
13274         }
13275         return 0;
13276 }
13277
13278 /*
13279  * Read and execute commands.
13280  * "Top" is nonzero for the top level command loop;
13281  * it turns on prompting if the shell is interactive.
13282  */
13283 static int
13284 cmdloop(int top)
13285 {
13286         union node *n;
13287         struct stackmark smark;
13288         int inter;
13289         int status = 0;
13290         int numeof = 0;
13291
13292         TRACE(("cmdloop(%d) called\n", top));
13293         for (;;) {
13294                 int skip;
13295
13296                 setstackmark(&smark);
13297 #if JOBS
13298                 if (doing_jobctl)
13299                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13300 #endif
13301                 inter = 0;
13302                 if (iflag && top) {
13303                         inter++;
13304                         chkmail();
13305                 }
13306                 n = parsecmd(inter);
13307 #if DEBUG
13308                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13309                         showtree(n);
13310 #endif
13311                 if (n == NODE_EOF) {
13312                         if (!top || numeof >= 50)
13313                                 break;
13314                         if (!stoppedjobs()) {
13315                                 if (!Iflag) {
13316                                         if (iflag) {
13317                                                 newline_and_flush(stderr);
13318                                         }
13319                                         break;
13320                                 }
13321                                 out2str("\nUse \"exit\" to leave shell.\n");
13322                         }
13323                         numeof++;
13324                 } else if (nflag == 0) {
13325                         int i;
13326
13327                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13328                         job_warning >>= 1;
13329                         numeof = 0;
13330                         i = evaltree(n, 0);
13331                         if (n)
13332                                 status = i;
13333                 }
13334                 popstackmark(&smark);
13335                 skip = evalskip;
13336
13337                 if (skip) {
13338                         evalskip &= ~SKIPFUNC;
13339                         break;
13340                 }
13341         }
13342         return status;
13343 }
13344
13345 /*
13346  * Take commands from a file.  To be compatible we should do a path
13347  * search for the file, which is necessary to find sub-commands.
13348  */
13349 static char *
13350 find_dot_file(char *basename)
13351 {
13352         char *fullname;
13353         const char *path = pathval();
13354         struct stat statb;
13355         int len;
13356
13357         /* don't try this for absolute or relative paths */
13358         if (strchr(basename, '/'))
13359                 return basename;
13360
13361         while ((len = padvance(&path, basename)) >= 0) {
13362                 fullname = stackblock();
13363                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13364                         /* This will be freed by the caller. */
13365                         return stalloc(len);
13366                 }
13367         }
13368         /* not found in PATH */
13369
13370 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13371         return basename;
13372 #else
13373         ash_msg_and_raise_error("%s: not found", basename);
13374         /* NOTREACHED */
13375 #endif
13376 }
13377
13378 static int FAST_FUNC
13379 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13380 {
13381         /* "false; . empty_file; echo $?" should print 0, not 1: */
13382         int status = 0;
13383         char *fullname;
13384         char **argv;
13385         char *args_need_save;
13386         volatile struct shparam saveparam;
13387
13388 //???
13389 //      struct strlist *sp;
13390 //      for (sp = cmdenviron; sp; sp = sp->next)
13391 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13392
13393         nextopt(nullstr); /* handle possible "--" */
13394         argv = argptr;
13395
13396         if (!argv[0]) {
13397                 /* bash says: "bash: .: filename argument required" */
13398                 return 2; /* bash compat */
13399         }
13400
13401         /* This aborts if file isn't found, which is POSIXly correct.
13402          * bash returns exitcode 1 instead.
13403          */
13404         fullname = find_dot_file(argv[0]);
13405         argv++;
13406         args_need_save = argv[0];
13407         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13408                 int argc;
13409                 saveparam = shellparam;
13410                 shellparam.malloced = 0;
13411                 argc = 1;
13412                 while (argv[argc])
13413                         argc++;
13414                 shellparam.nparam = argc;
13415                 shellparam.p = argv;
13416         };
13417
13418         /* This aborts if file can't be opened, which is POSIXly correct.
13419          * bash returns exitcode 1 instead.
13420          */
13421         setinputfile(fullname, INPUT_PUSH_FILE);
13422         commandname = fullname;
13423         status = cmdloop(0);
13424         popfile();
13425
13426         if (args_need_save) {
13427                 freeparam(&shellparam);
13428                 shellparam = saveparam;
13429         };
13430
13431         return status;
13432 }
13433
13434 static int FAST_FUNC
13435 exitcmd(int argc UNUSED_PARAM, char **argv)
13436 {
13437         if (stoppedjobs())
13438                 return 0;
13439
13440         if (argv[1])
13441                 savestatus = number(argv[1]);
13442
13443         raise_exception(EXEXIT);
13444         /* NOTREACHED */
13445 }
13446
13447 /*
13448  * Read a file containing shell functions.
13449  */
13450 static void
13451 readcmdfile(char *name)
13452 {
13453         setinputfile(name, INPUT_PUSH_FILE);
13454         cmdloop(0);
13455         popfile();
13456 }
13457
13458
13459 /* ============ find_command inplementation */
13460
13461 /*
13462  * Resolve a command name.  If you change this routine, you may have to
13463  * change the shellexec routine as well.
13464  */
13465 static void
13466 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13467 {
13468         struct tblentry *cmdp;
13469         int idx;
13470         int prev;
13471         char *fullname;
13472         struct stat statb;
13473         int e;
13474         int updatetbl;
13475         struct builtincmd *bcmd;
13476         int len;
13477
13478         /* If name contains a slash, don't use PATH or hash table */
13479         if (strchr(name, '/') != NULL) {
13480                 entry->u.index = -1;
13481                 if (act & DO_ABS) {
13482                         while (stat(name, &statb) < 0) {
13483 #ifdef SYSV
13484                                 if (errno == EINTR)
13485                                         continue;
13486 #endif
13487                                 entry->cmdtype = CMDUNKNOWN;
13488                                 return;
13489                         }
13490                 }
13491                 entry->cmdtype = CMDNORMAL;
13492                 return;
13493         }
13494
13495 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13496
13497         updatetbl = (path == pathval());
13498         if (!updatetbl) {
13499                 act |= DO_ALTPATH;
13500                 if (strstr(path, "%builtin") != NULL)
13501                         act |= DO_ALTBLTIN;
13502         }
13503
13504         /* If name is in the table, check answer will be ok */
13505         cmdp = cmdlookup(name, 0);
13506         if (cmdp != NULL) {
13507                 int bit;
13508
13509                 switch (cmdp->cmdtype) {
13510                 default:
13511 #if DEBUG
13512                         abort();
13513 #endif
13514                 case CMDNORMAL:
13515                         bit = DO_ALTPATH;
13516                         break;
13517                 case CMDFUNCTION:
13518                         bit = DO_NOFUNC;
13519                         break;
13520                 case CMDBUILTIN:
13521                         bit = DO_ALTBLTIN;
13522                         break;
13523                 }
13524                 if (act & bit) {
13525                         updatetbl = 0;
13526                         cmdp = NULL;
13527                 } else if (cmdp->rehash == 0)
13528                         /* if not invalidated by cd, we're done */
13529                         goto success;
13530         }
13531
13532         /* If %builtin not in path, check for builtin next */
13533         bcmd = find_builtin(name);
13534         if (bcmd) {
13535                 if (IS_BUILTIN_REGULAR(bcmd))
13536                         goto builtin_success;
13537                 if (act & DO_ALTPATH) {
13538                         if (!(act & DO_ALTBLTIN))
13539                                 goto builtin_success;
13540                 } else if (builtinloc <= 0) {
13541                         goto builtin_success;
13542                 }
13543         }
13544
13545 #if ENABLE_FEATURE_SH_STANDALONE
13546         {
13547                 int applet_no = find_applet_by_name(name);
13548                 if (applet_no >= 0) {
13549                         entry->cmdtype = CMDNORMAL;
13550                         entry->u.index = -2 - applet_no;
13551                         return;
13552                 }
13553         }
13554 #endif
13555
13556         /* We have to search path. */
13557         prev = -1;              /* where to start */
13558         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13559                 if (cmdp->cmdtype == CMDBUILTIN)
13560                         prev = builtinloc;
13561                 else
13562                         prev = cmdp->param.index;
13563         }
13564
13565         e = ENOENT;
13566         idx = -1;
13567  loop:
13568         while ((len = padvance(&path, name)) >= 0) {
13569                 fullname = stackblock();
13570                 idx++;
13571                 if (pathopt) {
13572                         if (prefix(pathopt, "builtin")) {
13573                                 if (bcmd)
13574                                         goto builtin_success;
13575                                 continue;
13576                         }
13577                         if ((act & DO_NOFUNC)
13578                          || !prefix(pathopt, "func")
13579                         ) {     /* ignore unimplemented options */
13580                                 continue;
13581                         }
13582                 }
13583                 /* if rehash, don't redo absolute path names */
13584                 if (fullname[0] == '/' && idx <= prev) {
13585                         if (idx < prev)
13586                                 continue;
13587                         TRACE(("searchexec \"%s\": no change\n", name));
13588                         goto success;
13589                 }
13590                 while (stat(fullname, &statb) < 0) {
13591 #ifdef SYSV
13592                         if (errno == EINTR)
13593                                 continue;
13594 #endif
13595                         if (errno != ENOENT && errno != ENOTDIR)
13596                                 e = errno;
13597                         goto loop;
13598                 }
13599                 e = EACCES;     /* if we fail, this will be the error */
13600                 if (!S_ISREG(statb.st_mode))
13601                         continue;
13602                 if (pathopt) {          /* this is a %func directory */
13603                         stalloc(len);
13604                         /* NB: stalloc will return space pointed by fullname
13605                          * (because we don't have any intervening allocations
13606                          * between stunalloc above and this stalloc) */
13607                         readcmdfile(fullname);
13608                         cmdp = cmdlookup(name, 0);
13609                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13610                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13611                         stunalloc(fullname);
13612                         goto success;
13613                 }
13614                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13615                 if (!updatetbl) {
13616                         entry->cmdtype = CMDNORMAL;
13617                         entry->u.index = idx;
13618                         return;
13619                 }
13620                 INT_OFF;
13621                 cmdp = cmdlookup(name, 1);
13622                 cmdp->cmdtype = CMDNORMAL;
13623                 cmdp->param.index = idx;
13624                 INT_ON;
13625                 goto success;
13626         }
13627
13628         /* We failed.  If there was an entry for this command, delete it */
13629         if (cmdp && updatetbl)
13630                 delete_cmd_entry();
13631         if (act & DO_ERR) {
13632 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13633                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13634                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13635                         char *argv[3];
13636                         argv[0] = (char*) "command_not_found_handle";
13637                         argv[1] = name;
13638                         argv[2] = NULL;
13639                         evalfun(hookp->param.func, 2, argv, 0);
13640                         entry->cmdtype = CMDUNKNOWN;
13641                         return;
13642                 }
13643 #endif
13644                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13645         }
13646         entry->cmdtype = CMDUNKNOWN;
13647         return;
13648
13649  builtin_success:
13650         if (!updatetbl) {
13651                 entry->cmdtype = CMDBUILTIN;
13652                 entry->u.cmd = bcmd;
13653                 return;
13654         }
13655         INT_OFF;
13656         cmdp = cmdlookup(name, 1);
13657         cmdp->cmdtype = CMDBUILTIN;
13658         cmdp->param.cmd = bcmd;
13659         INT_ON;
13660  success:
13661         cmdp->rehash = 0;
13662         entry->cmdtype = cmdp->cmdtype;
13663         entry->u = cmdp->param;
13664 }
13665
13666
13667 /*
13668  * The trap builtin.
13669  */
13670 static int FAST_FUNC
13671 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13672 {
13673         char *action;
13674         char **ap;
13675         int signo, exitcode;
13676
13677         nextopt(nullstr);
13678         ap = argptr;
13679         if (!*ap) {
13680                 for (signo = 0; signo < NSIG; signo++) {
13681                         char *tr = trap_ptr[signo];
13682                         if (tr) {
13683                                 /* note: bash adds "SIG", but only if invoked
13684                                  * as "bash". If called as "sh", or if set -o posix,
13685                                  * then it prints short signal names.
13686                                  * We are printing short names: */
13687                                 out1fmt("trap -- %s %s\n",
13688                                                 single_quote(tr),
13689                                                 get_signame(signo));
13690                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13691                  * In this case, we will exit very soon, no need to free(). */
13692                                 /* if (trap_ptr != trap && tp[0]) */
13693                                 /*      free(tr); */
13694                         }
13695                 }
13696                 /*
13697                 if (trap_ptr != trap) {
13698                         free(trap_ptr);
13699                         trap_ptr = trap;
13700                 }
13701                 */
13702                 return 0;
13703         }
13704
13705         /* Why the second check?
13706          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13707          * In this case, NUM is signal no, not an action.
13708          */
13709         action = NULL;
13710         if (ap[1] && !is_number(ap[0]))
13711                 action = *ap++;
13712
13713         exitcode = 0;
13714         while (*ap) {
13715                 signo = get_signum(*ap);
13716                 if (signo < 0) {
13717                         /* Mimic bash message exactly */
13718                         ash_msg("%s: invalid signal specification", *ap);
13719                         exitcode = 1;
13720                         goto next;
13721                 }
13722                 INT_OFF;
13723                 if (action) {
13724                         if (LONE_DASH(action))
13725                                 action = NULL;
13726                         else {
13727                                 if (action[0]) /* not NULL and not "" and not "-" */
13728                                         may_have_traps = 1;
13729                                 action = ckstrdup(action);
13730                         }
13731                 }
13732                 free(trap[signo]);
13733                 trap[signo] = action;
13734                 if (signo != 0)
13735                         setsignal(signo);
13736                 INT_ON;
13737  next:
13738                 ap++;
13739         }
13740         return exitcode;
13741 }
13742
13743
13744 /* ============ Builtins */
13745
13746 #if ENABLE_ASH_HELP
13747 static int FAST_FUNC
13748 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13749 {
13750         unsigned col;
13751         unsigned i;
13752
13753         out1fmt(
13754                 "Built-in commands:\n"
13755                 "------------------\n");
13756         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13757                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13758                                         builtintab[i].name + 1);
13759                 if (col > 60) {
13760                         out1fmt("\n");
13761                         col = 0;
13762                 }
13763         }
13764 # if ENABLE_FEATURE_SH_STANDALONE
13765         {
13766                 const char *a = applet_names;
13767                 while (*a) {
13768                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13769                         if (col > 60) {
13770                                 out1fmt("\n");
13771                                 col = 0;
13772                         }
13773                         while (*a++ != '\0')
13774                                 continue;
13775                 }
13776         }
13777 # endif
13778         newline_and_flush(stdout);
13779         return EXIT_SUCCESS;
13780 }
13781 #endif
13782
13783 #if MAX_HISTORY
13784 static int FAST_FUNC
13785 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13786 {
13787         if (line_input_state)
13788                 show_history(line_input_state);
13789         return EXIT_SUCCESS;
13790 }
13791 #endif
13792
13793 /*
13794  * The export and readonly commands.
13795  */
13796 static int FAST_FUNC
13797 exportcmd(int argc UNUSED_PARAM, char **argv)
13798 {
13799         struct var *vp;
13800         char *name;
13801         const char *p;
13802         char **aptr;
13803         char opt;
13804         int flag;
13805         int flag_off;
13806
13807         /* "readonly" in bash accepts, but ignores -n.
13808          * We do the same: it saves a conditional in nextopt's param.
13809          */
13810         flag_off = 0;
13811         while ((opt = nextopt("np")) != '\0') {
13812                 if (opt == 'n')
13813                         flag_off = VEXPORT;
13814         }
13815         flag = VEXPORT;
13816         if (argv[0][0] == 'r') {
13817                 flag = VREADONLY;
13818                 flag_off = 0; /* readonly ignores -n */
13819         }
13820         flag_off = ~flag_off;
13821
13822         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13823         {
13824                 aptr = argptr;
13825                 name = *aptr;
13826                 if (name) {
13827                         do {
13828                                 p = strchr(name, '=');
13829                                 if (p != NULL) {
13830                                         p++;
13831                                 } else {
13832                                         vp = *findvar(hashvar(name), name);
13833                                         if (vp) {
13834                                                 vp->flags = ((vp->flags | flag) & flag_off);
13835                                                 continue;
13836                                         }
13837                                 }
13838                                 setvar(name, p, (flag & flag_off));
13839                         } while ((name = *++aptr) != NULL);
13840                         return 0;
13841                 }
13842         }
13843
13844         /* No arguments. Show the list of exported or readonly vars.
13845          * -n is ignored.
13846          */
13847         showvars(argv[0], flag, 0);
13848         return 0;
13849 }
13850
13851 /*
13852  * Delete a function if it exists.
13853  */
13854 static void
13855 unsetfunc(const char *name)
13856 {
13857         struct tblentry *cmdp;
13858
13859         cmdp = cmdlookup(name, 0);
13860         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13861                 delete_cmd_entry();
13862 }
13863
13864 /*
13865  * The unset builtin command.  We unset the function before we unset the
13866  * variable to allow a function to be unset when there is a readonly variable
13867  * with the same name.
13868  */
13869 static int FAST_FUNC
13870 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13871 {
13872         char **ap;
13873         int i;
13874         int flag = 0;
13875
13876         while ((i = nextopt("vf")) != 0) {
13877                 flag = i;
13878         }
13879
13880         for (ap = argptr; *ap; ap++) {
13881                 if (flag != 'f') {
13882                         unsetvar(*ap);
13883                         continue;
13884                 }
13885                 if (flag != 'v')
13886                         unsetfunc(*ap);
13887         }
13888         return 0;
13889 }
13890
13891 static const unsigned char timescmd_str[] ALIGN1 = {
13892         ' ',  offsetof(struct tms, tms_utime),
13893         '\n', offsetof(struct tms, tms_stime),
13894         ' ',  offsetof(struct tms, tms_cutime),
13895         '\n', offsetof(struct tms, tms_cstime),
13896         0
13897 };
13898 static int FAST_FUNC
13899 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13900 {
13901         unsigned clk_tck;
13902         const unsigned char *p;
13903         struct tms buf;
13904
13905         clk_tck = bb_clk_tck();
13906
13907         times(&buf);
13908         p = timescmd_str;
13909         do {
13910                 unsigned sec, frac;
13911                 unsigned long t;
13912                 t = *(clock_t *)(((char *) &buf) + p[1]);
13913                 sec = t / clk_tck;
13914                 frac = t % clk_tck;
13915                 out1fmt("%um%u.%03us%c",
13916                         sec / 60, sec % 60,
13917                         (frac * 1000) / clk_tck,
13918                         p[0]);
13919                 p += 2;
13920         } while (*p);
13921
13922         return 0;
13923 }
13924
13925 #if ENABLE_FEATURE_SH_MATH
13926 /*
13927  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13928  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13929  *
13930  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13931  */
13932 static int FAST_FUNC
13933 letcmd(int argc UNUSED_PARAM, char **argv)
13934 {
13935         arith_t i;
13936
13937         argv++;
13938         if (!*argv)
13939                 ash_msg_and_raise_error("expression expected");
13940         do {
13941                 i = ash_arith(*argv);
13942         } while (*++argv);
13943
13944         return !i;
13945 }
13946 #endif
13947
13948 /*
13949  * The read builtin. Options:
13950  *      -r              Do not interpret '\' specially
13951  *      -s              Turn off echo (tty only)
13952  *      -n NCHARS       Read NCHARS max
13953  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13954  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13955  *      -u FD           Read from given FD instead of fd 0
13956  *      -d DELIM        End on DELIM char, not newline
13957  * This uses unbuffered input, which may be avoidable in some cases.
13958  * TODO: bash also has:
13959  *      -a ARRAY        Read into array[0],[1],etc
13960  *      -e              Use line editing (tty only)
13961  */
13962 static int FAST_FUNC
13963 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13964 {
13965         struct builtin_read_params params;
13966         const char *r;
13967         int i;
13968
13969         memset(&params, 0, sizeof(params));
13970
13971         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13972                 switch (i) {
13973                 case 'p':
13974                         params.opt_p = optionarg;
13975                         break;
13976                 case 'n':
13977                         params.opt_n = optionarg;
13978                         break;
13979                 case 's':
13980                         params.read_flags |= BUILTIN_READ_SILENT;
13981                         break;
13982                 case 't':
13983                         params.opt_t = optionarg;
13984                         break;
13985                 case 'r':
13986                         params.read_flags |= BUILTIN_READ_RAW;
13987                         break;
13988                 case 'u':
13989                         params.opt_u = optionarg;
13990                         break;
13991 #if BASH_READ_D
13992                 case 'd':
13993                         params.opt_d = optionarg;
13994                         break;
13995 #endif
13996                 default:
13997                         break;
13998                 }
13999         }
14000
14001         params.argv = argptr;
14002         params.setvar = setvar0;
14003         params.ifs = bltinlookup("IFS"); /* can be NULL */
14004
14005         /* "read -s" needs to save/restore termios, can't allow ^C
14006          * to jump out of it.
14007          */
14008  again:
14009         INT_OFF;
14010         r = shell_builtin_read(&params);
14011         INT_ON;
14012
14013         if ((uintptr_t)r == 1 && errno == EINTR) {
14014                 /* To get SIGCHLD: sleep 1 & read x; echo $x
14015                  * Correct behavior is to not exit "read"
14016                  */
14017                 if (pending_sig == 0)
14018                         goto again;
14019         }
14020
14021         if ((uintptr_t)r > 1)
14022                 ash_msg_and_raise_error(r);
14023
14024         return (uintptr_t)r;
14025 }
14026
14027 static int FAST_FUNC
14028 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14029 {
14030         static const char permuser[3] ALIGN1 = "ogu";
14031
14032         mode_t mask;
14033         int symbolic_mode = 0;
14034
14035         while (nextopt("S") != '\0') {
14036                 symbolic_mode = 1;
14037         }
14038
14039         INT_OFF;
14040         mask = umask(0);
14041         umask(mask);
14042         INT_ON;
14043
14044         if (*argptr == NULL) {
14045                 if (symbolic_mode) {
14046                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
14047                         char *p = buf;
14048                         int i;
14049
14050                         i = 2;
14051                         for (;;) {
14052                                 *p++ = ',';
14053                                 *p++ = permuser[i];
14054                                 *p++ = '=';
14055                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14056                                 if (!(mask & 0400)) *p++ = 'r';
14057                                 if (!(mask & 0200)) *p++ = 'w';
14058                                 if (!(mask & 0100)) *p++ = 'x';
14059                                 mask <<= 3;
14060                                 if (--i < 0)
14061                                         break;
14062                         }
14063                         *p = '\0';
14064                         puts(buf + 1);
14065                 } else {
14066                         out1fmt("%04o\n", mask);
14067                 }
14068         } else {
14069                 char *modestr = *argptr;
14070                 /* numeric umasks are taken as-is */
14071                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14072                 if (!isdigit(modestr[0]))
14073                         mask ^= 0777;
14074                 mask = bb_parse_mode(modestr, mask);
14075                 if ((unsigned)mask > 0777) {
14076                         ash_msg_and_raise_error("illegal mode: %s", modestr);
14077                 }
14078                 if (!isdigit(modestr[0]))
14079                         mask ^= 0777;
14080                 umask(mask);
14081         }
14082         return 0;
14083 }
14084
14085 static int FAST_FUNC
14086 ulimitcmd(int argc UNUSED_PARAM, char **argv)
14087 {
14088         return shell_builtin_ulimit(argv);
14089 }
14090
14091 /* ============ main() and helpers */
14092
14093 /*
14094  * Called to exit the shell.
14095  */
14096 static void
14097 exitshell(void)
14098 {
14099         struct jmploc loc;
14100         char *p;
14101
14102 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14103         if (line_input_state)
14104                 save_history(line_input_state);
14105 #endif
14106         savestatus = exitstatus;
14107         TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
14108         if (setjmp(loc.loc))
14109                 goto out;
14110         exception_handler = &loc;
14111         p = trap[0];
14112         if (p) {
14113                 trap[0] = NULL;
14114                 evalskip = 0;
14115                 evalstring(p, 0);
14116                 /*free(p); - we'll exit soon */
14117         }
14118  out:
14119         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14120          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14121          */
14122         setjobctl(0);
14123         flush_stdout_stderr();
14124         _exit(savestatus);
14125         /* NOTREACHED */
14126 }
14127
14128 /* Don't inline: conserve stack of caller from having our locals too */
14129 static NOINLINE void
14130 init(void)
14131 {
14132         /* we will never free this */
14133         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14134         basepf.linno = 1;
14135
14136         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14137         setsignal(SIGCHLD);
14138
14139         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
14140          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
14141          */
14142         signal(SIGHUP, SIG_DFL);
14143
14144         {
14145                 char **envp;
14146                 const char *p;
14147
14148                 initvar();
14149                 for (envp = environ; envp && *envp; envp++) {
14150 /* Used to have
14151  *                      p = endofname(*envp);
14152  *                      if (p != *envp && *p == '=') {
14153  * here to weed out badly-named variables, but this breaks
14154  * scenarios where people do want them passed to children:
14155  * import os
14156  * os.environ["test-test"]="test"
14157  * if os.fork() == 0:
14158  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14159  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14160  */
14161                         if (strchr(*envp, '=')) {
14162                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
14163                         }
14164                 }
14165
14166                 setvareq((char*)defifsvar, VTEXTFIXED);
14167                 setvareq((char*)defoptindvar, VTEXTFIXED);
14168
14169                 setvar0("PPID", utoa(getppid()));
14170 #if BASH_SHLVL_VAR
14171                 p = lookupvar("SHLVL");
14172                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14173 #endif
14174 #if BASH_HOSTNAME_VAR
14175                 if (!lookupvar("HOSTNAME")) {
14176                         struct utsname uts;
14177                         uname(&uts);
14178                         setvar0("HOSTNAME", uts.nodename);
14179                 }
14180 #endif
14181                 p = lookupvar("PWD");
14182                 if (p) {
14183                         struct stat st1, st2;
14184                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14185                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14186                         ) {
14187                                 p = NULL;
14188                         }
14189                 }
14190                 setpwd(p, 0);
14191         }
14192 }
14193
14194
14195 //usage:#define ash_trivial_usage
14196 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14197 //usage:#define ash_full_usage "\n\n"
14198 //usage:        "Unix shell interpreter"
14199
14200 /*
14201  * Process the shell command line arguments.
14202  */
14203 static int
14204 procargs(char **argv)
14205 {
14206         int i;
14207         const char *xminusc;
14208         char **xargv;
14209         int login_sh;
14210
14211         xargv = argv;
14212         login_sh = xargv[0] && xargv[0][0] == '-';
14213 #if NUM_SCRIPTS > 0
14214         if (minusc)
14215                 goto setarg0;
14216 #endif
14217         arg0 = xargv[0];
14218         /* if (xargv[0]) - mmm, this is always true! */
14219                 xargv++;
14220         argptr = xargv;
14221         for (i = 0; i < NOPTS; i++)
14222                 optlist[i] = 2;
14223         if (options(&login_sh)) {
14224                 /* it already printed err message */
14225                 raise_exception(EXERROR);
14226         }
14227         xargv = argptr;
14228         xminusc = minusc;
14229         if (*xargv == NULL) {
14230                 if (xminusc)
14231                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14232                 sflag = 1;
14233         }
14234         if (iflag == 2 /* no explicit -i given */
14235          && sflag == 1 /* -s given (or implied) */
14236          && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14237          && isatty(0) && isatty(1) /* we are on tty */
14238         ) {
14239                 iflag = 1;
14240         }
14241         if (mflag == 2)
14242                 mflag = iflag;
14243         for (i = 0; i < NOPTS; i++)
14244                 if (optlist[i] == 2)
14245                         optlist[i] = 0;
14246 #if DEBUG == 2
14247         debug = 1;
14248 #endif
14249         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14250         if (xminusc) {
14251                 minusc = *xargv++;
14252                 if (*xargv)
14253                         goto setarg0;
14254         } else if (!sflag) {
14255                 setinputfile(*xargv, 0);
14256  setarg0:
14257                 arg0 = *xargv++;
14258                 commandname = arg0;
14259         }
14260
14261         shellparam.p = xargv;
14262 #if ENABLE_ASH_GETOPTS
14263         shellparam.optind = 1;
14264         shellparam.optoff = -1;
14265 #endif
14266         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14267         while (*xargv) {
14268                 shellparam.nparam++;
14269                 xargv++;
14270         }
14271         optschanged();
14272
14273         return login_sh;
14274 }
14275
14276 /*
14277  * Read /etc/profile, ~/.profile, $ENV.
14278  */
14279 static void
14280 read_profile(const char *name)
14281 {
14282         name = expandstr(name, DQSYNTAX);
14283         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14284                 return;
14285         cmdloop(0);
14286         popfile();
14287 }
14288
14289 /*
14290  * This routine is called when an error or an interrupt occurs in an
14291  * interactive shell and control is returned to the main command loop
14292  * but prior to exitshell.
14293  */
14294 static void
14295 exitreset(void)
14296 {
14297         /* from eval.c: */
14298         evalskip = 0;
14299         loopnest = 0;
14300         if (savestatus >= 0) {
14301                 exitstatus = savestatus;
14302                 savestatus = -1;
14303         }
14304
14305         /* from expand.c: */
14306         ifsfree();
14307
14308         /* from redir.c: */
14309         unwindredir(NULL);
14310 }
14311
14312 /*
14313  * This routine is called when an error or an interrupt occurs in an
14314  * interactive shell and control is returned to the main command loop.
14315  * (In dash, this function is auto-generated by build machinery).
14316  */
14317 static void
14318 reset(void)
14319 {
14320         /* from input.c: */
14321         g_parsefile->left_in_buffer = 0;
14322         g_parsefile->left_in_line = 0;      /* clear input buffer */
14323         popallfiles();
14324
14325         /* from var.c: */
14326         unwindlocalvars(NULL);
14327 }
14328
14329 #if PROFILE
14330 static short profile_buf[16384];
14331 extern int etext();
14332 #endif
14333
14334 /*
14335  * Main routine.  We initialize things, parse the arguments, execute
14336  * profiles if we're a login shell, and then call cmdloop to execute
14337  * commands.  The setjmp call sets up the location to jump to when an
14338  * exception occurs.  When an exception occurs the variable "state"
14339  * is used to figure out how far we had gotten.
14340  */
14341 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14342 #if NUM_SCRIPTS > 0
14343 int ash_main(int argc, char **argv)
14344 #else
14345 int ash_main(int argc UNUSED_PARAM, char **argv)
14346 #endif
14347 /* note: 'argc' is used only if embedded scripts are enabled */
14348 {
14349         volatile smallint state;
14350         struct jmploc jmploc;
14351         struct stackmark smark;
14352         int login_sh;
14353
14354         /* Initialize global data */
14355         INIT_G_misc();
14356         INIT_G_memstack();
14357         INIT_G_var();
14358 #if ENABLE_ASH_ALIAS
14359         INIT_G_alias();
14360 #endif
14361         INIT_G_cmdtable();
14362
14363 #if PROFILE
14364         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14365 #endif
14366
14367         state = 0;
14368         if (setjmp(jmploc.loc)) {
14369                 smallint e;
14370                 smallint s;
14371
14372                 exitreset();
14373
14374                 e = exception_type;
14375                 s = state;
14376                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14377                         exitshell();
14378                 }
14379
14380                 reset();
14381
14382                 if (e == EXINT) {
14383                         newline_and_flush(stderr);
14384                 }
14385
14386                 popstackmark(&smark);
14387                 FORCE_INT_ON; /* enable interrupts */
14388                 if (s == 1)
14389                         goto state1;
14390                 if (s == 2)
14391                         goto state2;
14392                 if (s == 3)
14393                         goto state3;
14394                 goto state4;
14395         }
14396         exception_handler = &jmploc;
14397         rootpid = getpid();
14398
14399         init();
14400         setstackmark(&smark);
14401
14402 #if NUM_SCRIPTS > 0
14403         if (argc < 0)
14404                 /* Non-NULL minusc tells procargs that an embedded script is being run */
14405                 minusc = get_script_content(-argc - 1);
14406 #endif
14407         login_sh = procargs(argv);
14408 #if DEBUG
14409         TRACE(("Shell args: "));
14410         trace_puts_args(argv);
14411 #endif
14412
14413         if (login_sh) {
14414                 const char *hp;
14415
14416                 state = 1;
14417                 read_profile("/etc/profile");
14418  state1:
14419                 state = 2;
14420                 hp = lookupvar("HOME");
14421                 if (hp)
14422                         read_profile("$HOME/.profile");
14423         }
14424  state2:
14425         state = 3;
14426         if (
14427 #ifndef linux
14428          getuid() == geteuid() && getgid() == getegid() &&
14429 #endif
14430          iflag
14431         ) {
14432                 const char *shinit = lookupvar("ENV");
14433                 if (shinit != NULL && *shinit != '\0')
14434                         read_profile(shinit);
14435         }
14436         popstackmark(&smark);
14437  state3:
14438         state = 4;
14439         if (minusc) {
14440                 /* evalstring pushes parsefile stack.
14441                  * Ensure we don't falsely claim that 0 (stdin)
14442                  * is one of stacked source fds.
14443                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14444
14445                 // if (!sflag) g_parsefile->pf_fd = -1;
14446                 // ^^ not necessary since now we special-case fd 0
14447                 // in save_fd_on_redirect()
14448
14449                 // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14450                 // The above makes
14451                 //  ash -sc 'echo $-'
14452                 // continue reading input from stdin after running 'echo'.
14453                 // bash does not do this: it prints "hBcs" and exits.
14454                 evalstring(minusc, EV_EXIT);
14455         }
14456
14457         if (sflag || minusc == NULL) {
14458 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14459                 if (iflag) {
14460                         const char *hp = lookupvar("HISTFILE");
14461                         if (!hp) {
14462                                 hp = lookupvar("HOME");
14463                                 if (hp) {
14464                                         INT_OFF;
14465                                         hp = concat_path_file(hp, ".ash_history");
14466                                         setvar0("HISTFILE", hp);
14467                                         free((char*)hp);
14468                                         INT_ON;
14469                                         hp = lookupvar("HISTFILE");
14470                                 }
14471                         }
14472                         if (hp)
14473                                 line_input_state->hist_file = hp;
14474 # if ENABLE_FEATURE_SH_HISTFILESIZE
14475                         hp = lookupvar("HISTFILESIZE");
14476                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14477 # endif
14478                 }
14479 #endif
14480  state4: /* XXX ??? - why isn't this before the "if" statement */
14481                 cmdloop(1);
14482         }
14483 #if PROFILE
14484         monitor(0);
14485 #endif
14486 #ifdef GPROF
14487         {
14488                 extern void _mcleanup(void);
14489                 _mcleanup();
14490         }
14491 #endif
14492         TRACE(("End of main reached\n"));
14493         exitshell();
14494         /* NOTREACHED */
14495 }
14496
14497
14498 /*-
14499  * Copyright (c) 1989, 1991, 1993, 1994
14500  *      The Regents of the University of California.  All rights reserved.
14501  *
14502  * This code is derived from software contributed to Berkeley by
14503  * Kenneth Almquist.
14504  *
14505  * Redistribution and use in source and binary forms, with or without
14506  * modification, are permitted provided that the following conditions
14507  * are met:
14508  * 1. Redistributions of source code must retain the above copyright
14509  *    notice, this list of conditions and the following disclaimer.
14510  * 2. Redistributions in binary form must reproduce the above copyright
14511  *    notice, this list of conditions and the following disclaimer in the
14512  *    documentation and/or other materials provided with the distribution.
14513  * 3. Neither the name of the University nor the names of its contributors
14514  *    may be used to endorse or promote products derived from this software
14515  *    without specific prior written permission.
14516  *
14517  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14518  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14519  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14520  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14521  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14522  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14523  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14524  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14525  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14526  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14527  * SUCH DAMAGE.
14528  */