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